diff options
author | Paul Gilbert | 2009-12-19 05:47:31 +0000 |
---|---|---|
committer | Paul Gilbert | 2009-12-19 05:47:31 +0000 |
commit | 63350a0ecca8bb1b3c102ffea698ace04337665a (patch) | |
tree | 2cfd6ebc63f80c3f9050297b48d919cd7a1c3b22 | |
parent | ae50fdca7238c6898e9289935ec392f66e0311ae (diff) | |
download | scummvm-rg350-63350a0ecca8bb1b3c102ffea698ace04337665a.tar.gz scummvm-rg350-63350a0ecca8bb1b3c102ffea698ace04337665a.tar.bz2 scummvm-rg350-63350a0ecca8bb1b3c102ffea698ace04337665a.zip |
Further implementation of dialog/message script language
svn-id: r46418
-rw-r--r-- | engines/m4/console.cpp | 10 | ||||
-rw-r--r-- | engines/m4/dialogs.cpp | 163 | ||||
-rw-r--r-- | engines/m4/dialogs.h | 8 |
3 files changed, 153 insertions, 28 deletions
diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp index 719c58fcaa..c8fa316533 100644 --- a/engines/m4/console.cpp +++ b/engines/m4/console.cpp @@ -364,13 +364,15 @@ bool Console::cmdMessage(int argc, const char **argv) { if (argc == 1) DebugPrintf("message 'objnum'\n"); else { - int messageId = strToInt(argv[1]); - int idx = _vm->_globals->messageIndexOf(messageId); - if (idx == -1) + int messageIdx = strToInt(argv[1]); + if ((argc == 3) && !strcmp(argv[2], "id")) + messageIdx = _vm->_globals->messageIndexOf(messageIdx); + + if (messageIdx == -1) DebugPrintf("Unknown message"); else { - const char *msg = _vm->_globals->loadMessage(idx); + const char *msg = _vm->_globals->loadMessage(messageIdx); Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); _vm->_viewManager->addView(dlg); diff --git a/engines/m4/dialogs.cpp b/engines/m4/dialogs.cpp index 2796fe4030..442c31f35d 100644 --- a/engines/m4/dialogs.cpp +++ b/engines/m4/dialogs.cpp @@ -35,6 +35,13 @@ static void strToUpper(char *s) { } } +static void strToLower(char *s) { + while (*s) { + *s = tolower(*s); + ++s; + } +} + const RGB8 DIALOG_PALETTE[8] = { {0x80, 0x80, 0x80, 0xff}, {0x90, 0x90, 0x90, 0xff}, {0x70, 0x70, 0x70, 0xff}, {0x9c, 0x9c, 0x9c, 0xff}, {0x80, 0x80, 0x80, 0xff}, {0x90, 0x90, 0x90, 0xff}, {0xDC, 0xDC, 0xDC, 0xff}, {0x00, 0x00, 0x00, 0xff} @@ -44,10 +51,16 @@ const RGB8 DIALOG_PALETTE[8] = { const int DIALOG_SPACING = 1; +/** + * Handles any dialog initialisation + */ void Dialog::initDialog() { incLine(); } +/** + * Adds a new line to the dialog output + */ void Dialog::incLine() { _lineX = 0; _widthX = 0; @@ -56,6 +69,10 @@ void Dialog::incLine() { assert(_lines.size() <= 20); } +/** + * Writes some text to the dialog output, taking care of word wrapping if the text size + * exceeds the dialog's width + */ void Dialog::writeChars(const char *srcLine) { char wordStr[80]; char line[80]; @@ -124,6 +141,9 @@ void Dialog::writeChars(const char *srcLine) { } } +/** + * Appends some text to the current dialog line + */ void Dialog::appendText(const char *line) { _lineX += strlen(line); _widthX += _vm->_font->getWidth(line, DIALOG_SPACING); @@ -131,6 +151,9 @@ void Dialog::appendText(const char *line) { strcat(_lines[_lines.size() - 1].data, line); } +/** + * Adds a line of text to the dialog lines list + */ void Dialog::addLine(const char *line, bool underlineP) { if ((_widthX > 0) || (_lineX > 0)) incLine(); @@ -141,7 +164,7 @@ void Dialog::addLine(const char *line, bool underlineP) { if ((lineWidth > _dialogWidth) || (lineLen >= _widthChars)) writeChars(line); else { - _lines[_lines.size() - 1].xp = (_dialogWidth - lineWidth) / 2; + _lines[_lines.size() - 1].xp = (_dialogWidth - 10 - lineWidth) / 2; strcpy(_lines[_lines.size() - 1].data, line); } @@ -151,12 +174,97 @@ void Dialog::addLine(const char *line, bool underlineP) { incLine(); } +/** + * Adds a bar separation line to the dialog lines list + */ +void Dialog::addBarLine() { + if ((_widthX > 0) || (_lineX > 0)) + incLine(); + + // Flag the line as being a bar separator + _lines[_lines.size() - 1].barLine = true; + incLine(); +} + +/** + * Retrieves a specified vocab entry + */ +void Dialog::getVocab(int vocabId, char **line) { + assert(vocabId > 0); + const char *vocabStr = _vm->_globals->getVocab(vocabId); + strcpy(*line, vocabStr); + + if (_commandCase) + strToUpper(*line); + else + strToLower(*line); + + // Move the string pointer to after the added string + while (!**line) + ++*line; +} + +bool Dialog::handleNounSuffix(char *destP, int nounNum, const char *srcP) { + char srcLine[40]; + + // The next source character must be a colon in front of the first verb + if (*srcP != ':') + return false; + + // Copy the remainder of the line into a temporary buffer to get the seperate verbs + strcpy(srcLine, ++srcP); + char *altP = strchr(srcLine, ':'); + if (altP) + *altP = '\0'; + + if (*srcP != '\0') { + while (*srcP != ':') { + ++srcP; + if (!*srcP) break; + } + } + + if (*srcP != '\0') + ++srcP; + + // + char var_FC[40]; + char tempLine[40]; + strcpy(var_FC, srcP); + char *tmpP = &tempLine[0]; + char *tmp2P = tmpP; + + uint16 _vocabIds[2] = {1, 1}; // FIXME/TODO: Proper vocab ids + getVocab(_vocabIds[nounNum], &tmpP); + + if ((*(tmpP - 1) != 'S') && (*(tmpP - 1) != 's')) { + // Singular object + tmpP = &var_FC[0]; + } else if (!strcmp(tempLine, "a ")) { + // Pontially plural + char ch = tolower(*tmp2P); + + if (!((ch > 'U') || ((ch != 'A') && (ch != 'E') && (ch != 'I') && (ch != 'O')))) + strcpy(tempLine, "an "); + } + + strcpy(destP, tmpP); + return true; +} + +/** + * Checks whether the start of an extracted command matches a specified given command constant + */ bool Dialog::matchCommand(const char *s1, const char *s2) { - return strncmp(s1, s2, strlen(s2)) == 0; + bool result = scumm_strnicmp(s1, s2, strlen(s2)) == 0; + _commandCase = isupper(*s1); + return result; } Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, Common::Rect(0, 0, 0, 0)) { assert(msgData); + _vm->_font->setFont(FONT_INTERFACE_MADS); + const char *srcP = msgData; bool skipLine = false; bool initFlag = false; @@ -172,6 +280,7 @@ Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, C _lineX = 0; _widthX = 0; _dialogWidth = 0; + _commandCase = false; char dialogLine[256]; char cmdText[80]; @@ -226,7 +335,7 @@ Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, C if (id > 0) { // Suffix provided - specifies the dialog width in number of chars _widthChars = id * 2; - _dialogWidth = id * (_vm->_font->getMaxWidth() + 1) + 10; + _dialogWidth = id * (_vm->_font->getMaxWidth() + DIALOG_SPACING) + 10; } } else if (matchCommand(cmdText, "SENTENCE")) { // Sentence command - loads the title into the line buffer @@ -234,31 +343,45 @@ Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, C strToUpper(dialogLine); lineP += strlen(dialogLine) + 1; + } else if (matchCommand(cmdText, "BAR")) { + // Adds a full-width line instead of normal text + addBarLine(); + + } else if (matchCommand(cmdText, "CENTER")) { + // Center command + skipLine = true; + } else if (matchCommand(cmdText, "CR")) { // CR command if (skipLine) crFlag = true; - else { + else if (!initFlag) { initDialog(); + initFlag = true; } + } else if (matchCommand(cmdText, "NOUN1")) { + // Noun command 1 + handleNounSuffix(lineP, 1, cmdText + 5); + + } else if (matchCommand(cmdText, "NOUN1")) { + // Noun command 2 + handleNounSuffix(lineP, 2, cmdText + 5); + + } else if (matchCommand(cmdText, "VERB")) { + // Verb/vocab retrieval + int verbId = 1; // TODO: Get correct vocab + getVocab(verbId, &lineP); + } else if (matchCommand(cmdText, "UNDER")) { // Underline command underline = true; } else if (matchCommand(cmdText, "ASK")) { // doAsk(); - } else if (matchCommand(cmdText, "CENTER")) { - // Center command - skipLine = true; - } else if (matchCommand(cmdText, "VERB")) { - // Verb/vocab retrieval - /*getVocab(); */ } else if (matchCommand(cmdText, "INDEX")) { // Index command _dialogIndex = atoi(cmdText + 5); - } else if (matchCommand(cmdText, "NOUN")) { - // Noun command } else { error("Unknown dialog command '%s' encountered", cmdText); } @@ -279,19 +402,13 @@ Dialog::~Dialog() { } void Dialog::draw() { - _vm->_font->setFont(FONT_INTERFACE_MADS); + assert(_widthChars != 0); // Set up the palette for this view _palette = new RGBList(8, NULL); _palette->setRange(0, 8, DIALOG_PALETTE); _vm->_palette->addRange(_palette); - // Validation - if (_widthChars == 0) { - warning("Dialog being shown without TITLE specified"); - _widthChars = 30; - } - // Calculate bounds int dlgWidth = _dialogWidth; int dlgHeight = _lines.size() * (_vm->_font->getHeight() + 1) + 10; @@ -338,10 +455,12 @@ void Dialog::draw() { for (uint lineCtr = 0, yp = 5; lineCtr < _lines.size(); ++lineCtr, yp += _vm->_font->getHeight() + 1) { - if (_lines[lineCtr].xp == 0xff) { - hLine(2, width() - 6, ((_vm->_font->getHeight() + 1) >> 1) + yp); + if (_lines[lineCtr].barLine) { + // Bar separation line + hLine(5, width() - 6, ((_vm->_font->getHeight() + 1) >> 1) + yp); } else { - Common::Point pt((_lines[lineCtr].xp & 0x7f) + 5, yp); + // Standard line + Common::Point pt(_lines[lineCtr].xp + 5, yp); if (_lines[lineCtr].xp & 0x40) ++pt.y; diff --git a/engines/m4/dialogs.h b/engines/m4/dialogs.h index c9825b6d9b..c8b19338f3 100644 --- a/engines/m4/dialogs.h +++ b/engines/m4/dialogs.h @@ -37,8 +37,9 @@ public: char data[100]; uint8 xp; bool underline; + bool barLine; - DialogLine() { data[0] = '\0'; xp = 0; underline = false; } + DialogLine() { data[0] = '\0'; xp = 0; underline = barLine = false; } }; class Dialog: public View { @@ -51,7 +52,7 @@ private: RGBList *_palette; int _lineX; int _widthX; - + bool _commandCase; void initDialog(); void incLine(); @@ -59,6 +60,9 @@ private: void writeChars(const char *line); void addLine(const char *line, bool underlineP = false); void appendText(const char *line); + void addBarLine(); + void getVocab(int vocabId, char **line); + bool handleNounSuffix(char *destP, int nounNum, const char *srcP); void draw(); public: Dialog(M4Engine *vm, const char *msgData, const char *title = NULL); |