diff options
Diffstat (limited to 'engines/sci')
-rw-r--r-- | engines/sci/engine/kstring.cpp | 12 | ||||
-rw-r--r-- | engines/sci/engine/message.cpp | 56 | ||||
-rw-r--r-- | engines/sci/engine/message.h | 2 |
3 files changed, 60 insertions, 10 deletions
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 20f0f4793b..3898664921 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -713,7 +713,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { case K_MESSAGE_NEXT: { reg_t bufferReg; char *buffer = NULL; - const char *str; + Common::String str; reg_t retval; if (func == K_MESSAGE_GET) { @@ -735,18 +735,18 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { else retval = make_reg(0, s->_msgState.getTalker()); } else { - str = DUMMY_MESSAGE; + str = Common::String(DUMMY_MESSAGE); retval = NULL_REG; } if (!bufferReg.isNull()) { - int len = strlen(str) + 1; + int len = str.size() + 1; buffer = kernel_dereference_char_pointer(s, bufferReg, len); if (buffer) { - strcpy(buffer, str); + strcpy(buffer, str.c_str()); } else { - warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(bufferReg), len, str); + warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(bufferReg), len, str.c_str()); // Set buffer to empty string if possible buffer = kernel_dereference_char_pointer(s, bufferReg, 1); @@ -763,7 +763,7 @@ reg_t kMessage(EngineState *s, int funct_nr, int argc, reg_t *argv) { MessageState tempState; if (tempState.loadRes(s->resmgr, UKPV(1), false) && tempState.findTuple(tuple) && tempState.getMessage()) - return make_reg(0, strlen(tempState.getText()) + 1); + return make_reg(0, tempState.getText().size() + 1); else return NULL_REG; } diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index 61151e3218..4f5efa106c 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -153,9 +153,59 @@ int MessageState::getLastModule() { return _lastReturnedModule; } -char *MessageState::getText() { - int offset = READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5)); - return (char *)_currentResource->data + offset; +Common::String MessageState::getText() { + char *str = (char *)_currentResource->data + READ_LE_UINT16(_engineCursor.index_record + ((_version == 2101) ? 2 : 5)); + + Common::String strippedStr; + Common::String skippedSubstr; + bool skipping = false; + + for (uint i = 0; i < strlen(str); i++) { + if (skipping) { + // Skip stage direction + skippedSubstr += str[i]; + + // Hopefully these locale-dependant functions are good enough + if (islower(str[i]) || isdigit(str[i])) { + // Lowercase or digit found, this is not a stage direction + strippedStr += skippedSubstr; + skipping = false; + } else if (str[i] == ')') { + // End of stage direction, skip trailing white space + while ((i + 1 < strlen(str)) && isspace(str[i + 1])) + i++; + skipping = false; + } + } else { + if (str[i] == '(') { + // Start skipping stage direction + skippedSubstr = str[i]; + skipping = true; + } else if (str[i] == '\\') { + // Escape sequence + if ((i + 2 < strlen(str)) && isdigit(str[i + 1]) && isdigit(str[i + 2])) { + // Hex escape sequence + char hexStr[3]; + + hexStr[0] = str[++i]; + hexStr[1] = str[++i]; + hexStr[2] = 0; + + char *endptr; + int hexNr = strtol(hexStr, &endptr, 16); + if (*endptr == 0) + strippedStr += hexNr; + } else if (i + 1 < strlen(str)) { + // Literal escape sequence + strippedStr += str[++i]; + } + } else { + strippedStr += str[i]; + } + } + } + + return strippedStr; } void MessageState::gotoNext() { diff --git a/engines/sci/engine/message.h b/engines/sci/engine/message.h index b1cdb8ad99..5e30095a0c 100644 --- a/engines/sci/engine/message.h +++ b/engines/sci/engine/message.h @@ -54,7 +54,7 @@ public: MessageTuple getRefTuple(); int getMessage(); void gotoNext(); - char *getText(); + Common::String getText(); int getTalker(); int getLength(); MessageTuple &getLastTuple(); |