diff options
author | Paul Gilbert | 2009-12-17 07:55:08 +0000 |
---|---|---|
committer | Paul Gilbert | 2009-12-17 07:55:08 +0000 |
commit | 575308cea724b214d7f83a06cf8819f15b1e4f75 (patch) | |
tree | 19d691025b2c9040698b196cd66b74f4fffaed2e | |
parent | 690a410423207c3df4c6cf9427167c0948f08ad4 (diff) | |
download | scummvm-rg350-575308cea724b214d7f83a06cf8819f15b1e4f75.tar.gz scummvm-rg350-575308cea724b214d7f83a06cf8819f15b1e4f75.tar.bz2 scummvm-rg350-575308cea724b214d7f83a06cf8819f15b1e4f75.zip |
Implemented basic message parsing
svn-id: r46402
-rw-r--r-- | engines/m4/console.cpp | 2 | ||||
-rw-r--r-- | engines/m4/dialogs.cpp | 192 | ||||
-rw-r--r-- | engines/m4/dialogs.h | 11 | ||||
-rw-r--r-- | engines/m4/font.cpp | 2 | ||||
-rw-r--r-- | engines/m4/font.h | 2 | ||||
-rw-r--r-- | engines/m4/scene.cpp | 2 |
6 files changed, 170 insertions, 41 deletions
diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp index a6a757d2ab..719c58fcaa 100644 --- a/engines/m4/console.cpp +++ b/engines/m4/console.cpp @@ -371,7 +371,7 @@ bool Console::cmdMessage(int argc, const char **argv) { else { const char *msg = _vm->_globals->loadMessage(idx); - Dialog *dlg = new Dialog(_vm, msg); + Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); _vm->_viewManager->addView(dlg); _vm->_viewManager->moveToFront(dlg); diff --git a/engines/m4/dialogs.cpp b/engines/m4/dialogs.cpp index 9989d99309..2796fe4030 100644 --- a/engines/m4/dialogs.cpp +++ b/engines/m4/dialogs.cpp @@ -42,60 +42,168 @@ const RGB8 DIALOG_PALETTE[8] = { #define ROR16(v,amt) (((uint16)(v) >> amt) | ((uint16)(v) << (16 - amt))) -void Dialog::initDialog() { +const int DIALOG_SPACING = 1; +void Dialog::initDialog() { + incLine(); } void Dialog::incLine() { + _lineX = 0; + _widthX = 0; + _lines.push_back(*new DialogLine()); - assert(_lines.size() < 20); + assert(_lines.size() <= 20); +} + +void Dialog::writeChars(const char *srcLine) { + char wordStr[80]; + char line[80]; + int lineLen, lineWidth; + const char *srcP = srcLine; + + while (*srcP) { + bool wordEndedP = false, newlineP = false; + char *destP = &wordStr[0]; + Common::set_to(&wordStr[0], &wordStr[80], 0); + + // Try and get the next word + for (;;) { + char v = *srcP; + *destP++ = v; + + if (v == '\0') break; + if (v == '\n') { + newlineP = true; + ++srcP; + --destP; + break; + } + + if (v == ' ') { + // Word separator + ++srcP; + --destP; + wordEndedP = true; + } else { + // Standard character + if (!wordEndedP) + // Still in the initial word + ++srcP; + else { + // First character of next word, so time to break + --destP; + break; + } + } + } + + if (destP < &wordStr[0]) + destP = &wordStr[0]; + *destP = '\0'; + + lineLen = strlen(wordStr); + + strcpy(line, ""); + if (_lineX > 0) + strcat(line, " "); + strcat(line, wordStr); + + lineLen = strlen(line); + lineWidth = _vm->_font->getWidth(line, DIALOG_SPACING); + + if (((_lineX + lineLen) > _widthChars) || ((_widthX + lineWidth) > _dialogWidth)) { + incLine(); + appendText(wordStr); + } else { + appendText(line); + } + + if (newlineP) + incLine(); + } } -void Dialog::writeChars(const char *line) { - assert(_lines.size() > 0); - strcpy(_lines[_lines.size() - 1].data, line); +void Dialog::appendText(const char *line) { + _lineX += strlen(line); + _widthX += _vm->_font->getWidth(line, DIALOG_SPACING); + + strcat(_lines[_lines.size() - 1].data, line); } -void Dialog::addLine(const char *line) { +void Dialog::addLine(const char *line, bool underlineP) { + if ((_widthX > 0) || (_lineX > 0)) + incLine(); + + int lineWidth = _vm->_font->getWidth(line, DIALOG_SPACING); + int lineLen = strlen(line); + + if ((lineWidth > _dialogWidth) || (lineLen >= _widthChars)) + writeChars(line); + else { + _lines[_lines.size() - 1].xp = (_dialogWidth - lineWidth) / 2; + strcpy(_lines[_lines.size() - 1].data, line); + } + + if (underlineP) + _lines[_lines.size() - 1].underline = true; + incLine(); } bool Dialog::matchCommand(const char *s1, const char *s2) { return strncmp(s1, s2, strlen(s2)) == 0; } -Dialog::Dialog(M4Engine *vm, const char *msgData): View(vm, Common::Rect(0, 0, 0, 0)) { +Dialog::Dialog(M4Engine *vm, const char *msgData, const char *title): View(vm, Common::Rect(0, 0, 0, 0)) { assert(msgData); const char *srcP = msgData; bool skipLine = false; bool initFlag = false; bool cmdFlag = false; bool crFlag = false; + bool underline = false; _screenType = LAYER_DIALOG; _widthChars = 0; _dialogIndex = 0; _askPosition.x = 0; _askPosition.y = 0; + _lineX = 0; + _widthX = 0; + _dialogWidth = 0; char dialogLine[256]; char cmdText[80]; char *lineP = &dialogLine[0]; char *cmdP = NULL; - while (*srcP != '\0') { - if (*srcP == '\n') { + while (*(srcP - 1) != '\0') { + if ((*srcP == '\n') || (*srcP == '\0')) { // Line completed *lineP = '\0'; ++srcP; if (!initFlag) { initDialog(); - incLine(); initFlag = true; - } else { + } + + if (!skipLine) writeChars(dialogLine); + else { + addLine(dialogLine, underline); + + if (crFlag) + incLine(); } + + // Clear the current line contents + dialogLine[0] = '\0'; + lineP = &dialogLine[0]; + skipLine = crFlag = underline = false; + continue; + } else if (*srcP == '[') { // Start of a command sequence cmdFlag = true; @@ -108,15 +216,24 @@ Dialog::Dialog(M4Engine *vm, const char *msgData): View(vm, Common::Rect(0, 0, 0 cmdFlag = false; strToUpper(cmdText); - if (matchCommand(cmdText, "CENTER")) - // Center command + if (matchCommand(cmdText, "TITLE")) { + // Title command - specifies the dialog width in number of characters skipLine = true; - else if (matchCommand(cmdText, "TITLE")) { - // Title command + crFlag = true; + underline = true; + int id = atoi(cmdText + 5); - if (id > 0) + if (id > 0) { // Suffix provided - specifies the dialog width in number of chars - _widthChars = id; + _widthChars = id * 2; + _dialogWidth = id * (_vm->_font->getMaxWidth() + 1) + 10; + } + } else if (matchCommand(cmdText, "SENTENCE")) { + // Sentence command - loads the title into the line buffer + strcpy(dialogLine, title); + strToUpper(dialogLine); + lineP += strlen(dialogLine) + 1; + } else if (matchCommand(cmdText, "CR")) { // CR command if (skipLine) @@ -124,8 +241,16 @@ Dialog::Dialog(M4Engine *vm, const char *msgData): View(vm, Common::Rect(0, 0, 0 else { initDialog(); } + + } 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(); */ @@ -134,26 +259,17 @@ Dialog::Dialog(M4Engine *vm, const char *msgData): View(vm, Common::Rect(0, 0, 0 _dialogIndex = atoi(cmdText + 5); } else if (matchCommand(cmdText, "NOUN")) { // Noun command - } else if (matchCommand(cmdText, "SENTENCE")) { - // Sentence command } else { error("Unknown dialog command '%s' encountered", cmdText); } } + *lineP++ = *srcP; if (cmdFlag) *cmdP++ = *srcP; ++srcP; } - if (!skipLine) - incLine(); - - // FIXME: Remove dummy dialog test string - incLine(); - strcpy(_lines[_lines.size() - 1].data, "Test dialog"); - _lines[_lines.size() - 1].xp = 20; - draw(); } @@ -170,9 +286,15 @@ void Dialog::draw() { _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 = _widthChars * (_vm->_font->getMaxWidth() + 1) + 10; - int dlgHeight = (_lines.size() + 1) * (_vm->_font->getHeight() + 1) + 10; + int dlgWidth = _dialogWidth; + int dlgHeight = _lines.size() * (_vm->_font->getHeight() + 1) + 10; int dialogX = (_vm->_screen->width() - dlgWidth) / 2; int dialogY = (_vm->_screen->height() - dlgHeight) / 2; @@ -219,14 +341,16 @@ void Dialog::draw() { if (_lines[lineCtr].xp == 0xff) { hLine(2, width() - 6, ((_vm->_font->getHeight() + 1) >> 1) + yp); } else { - Common::Point pt(_lines[lineCtr].xp & 0x7f, yp + - (((_lines[lineCtr].xp & 0x40) != 0) ? 1 : 0)); + Common::Point pt((_lines[lineCtr].xp & 0x7f) + 5, yp); + if (_lines[lineCtr].xp & 0x40) + ++pt.y; - _vm->_font->writeString(this, _lines[lineCtr].data, pt.x, pt.y, 0, 0); + _vm->_font->writeString(this, _lines[lineCtr].data, pt.x, pt.y, 0, DIALOG_SPACING); - if (_lines[lineCtr].xp & 0x80) + if (_lines[lineCtr].underline) // Underline needed - hLine(pt.x, pt.x + _vm->_font->getWidth(_lines[lineCtr].data), pt.y); + hLine(pt.x, pt.x + _vm->_font->getWidth(_lines[lineCtr].data, DIALOG_SPACING), + pt.y + _vm->_font->getHeight()); } } diff --git a/engines/m4/dialogs.h b/engines/m4/dialogs.h index beb87ae17e..c9825b6d9b 100644 --- a/engines/m4/dialogs.h +++ b/engines/m4/dialogs.h @@ -36,27 +36,32 @@ class DialogLine { public: char data[100]; uint8 xp; + bool underline; - DialogLine() { data[0] = '\0'; xp = 0; } + DialogLine() { data[0] = '\0'; xp = 0; underline = false; } }; class Dialog: public View { private: Common::Array<DialogLine> _lines; int _widthChars; + int _dialogWidth; int _dialogIndex; Common::Point _askPosition; RGBList *_palette; + int _lineX; + int _widthX; void initDialog(); void incLine(); bool matchCommand(const char *s1, const char *s2); void writeChars(const char *line); - void addLine(const char *line); + void addLine(const char *line, bool underlineP = false); + void appendText(const char *line); void draw(); public: - Dialog(M4Engine *vm, const char *msgData); + Dialog(M4Engine *vm, const char *msgData, const char *title = NULL); virtual ~Dialog(); bool onEvent(M4EventType eventType, int param1, int x, int y, bool &captureEvents); diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp index a0ca27f745..a6ddeca830 100644 --- a/engines/m4/font.cpp +++ b/engines/m4/font.cpp @@ -252,7 +252,7 @@ int32 Font::write(M4Surface *surface, const char *text, int x, int y, int width, } -int32 Font::getWidth(char *text, int spaceWidth) { +int32 Font::getWidth(const char *text, int spaceWidth) { /* if (custom_ascii_converter) { // if there is a function to convert the extended ASCII characters custom_ascii_converter(out_string); // call it with the string diff --git a/engines/m4/font.h b/engines/m4/font.h index f75e76e425..121c179562 100644 --- a/engines/m4/font.h +++ b/engines/m4/font.h @@ -67,7 +67,7 @@ public: void setColour(uint8 colour) { setColor(colour); } void setColours(uint8 alt1, uint8 alt2, uint8 foreground) { setColors(alt1, alt2, foreground); } - int32 getWidth(char *text, int spaceWidth = -1); + int32 getWidth(const char *text, int spaceWidth = -1); int32 getHeight() const { return _maxHeight; } int32 getMaxWidth() const { return _maxWidth; } int32 write(M4Surface *surface, const char *text, int x, int y, int width, int spaceWidth, uint8 colors[]); diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp index 843bc9c1d7..4177825da2 100644 --- a/engines/m4/scene.cpp +++ b/engines/m4/scene.cpp @@ -560,7 +560,7 @@ bool Scene::onEvent(M4EventType eventType, int param1, int x, int y, bool &captu // ***DEBUG*** - sample dialog display int idx = _vm->_globals->messageIndexOf(0x277a); const char *msg = _vm->_globals->loadMessage(idx); - Dialog *dlg = new Dialog(_vm, msg); + Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); _vm->_viewManager->addView(dlg); _vm->_viewManager->moveToFront(dlg); } |