diff options
-rw-r--r-- | engines/lure/surface.cpp | 147 | ||||
-rw-r--r-- | engines/lure/surface.h | 15 |
2 files changed, 137 insertions, 25 deletions
diff --git a/engines/lure/surface.cpp b/engines/lure/surface.cpp index e254cfe501..ed64eab918 100644 --- a/engines/lure/surface.cpp +++ b/engines/lure/surface.cpp @@ -287,24 +287,13 @@ uint16 Surface::textWidth(const char *s, int numChars) { return result; } -Surface *Surface::newDialog(uint16 width, uint8 numLines, char **lines, bool varLength, uint8 colour) { - Surface *s = new Surface(width, (DIALOG_EDGE_SIZE + 3) * 2 + - numLines * (FONT_HEIGHT - 1)); - s->createDialog(); - - for (uint8 ctr = 0; ctr < numLines; ++ctr) - s->writeString(DIALOG_EDGE_SIZE + 3, DIALOG_EDGE_SIZE + 3 + - (ctr * (FONT_HEIGHT - 1)), lines[ctr], true, colour, varLength); - return s; -} - -Surface *Surface::newDialog(uint16 width, const char *line, uint8 colour) { - uint8 numLines = 1; +void Surface::wordWrap(char *text, uint16 width, char **&lines, uint8 &numLines) { + numLines = 1; uint16 lineWidth = 0; - char *s, *lineCopy; + char *s; bool newLine; - s = lineCopy = strdup(line); + s = text; // Scan through the text and insert NULLs to break the line into allowable widths @@ -320,20 +309,25 @@ Surface *Surface::newDialog(uint16 width, const char *line, uint8 colour) { newLine = false; } - if (wordEnd) --wordEnd; // move back one to end of word - else wordEnd = strchr(s, '\0') - 1; + if (wordEnd) { + if (!newLine) --wordEnd; + } else { + wordEnd = strchr(s, '\0') - 1; + } uint16 wordSize = textWidth(s, (int) (wordEnd - s + 1)); - if (lineWidth + wordSize > width - (DIALOG_EDGE_SIZE + 3) * 2) { + if (lineWidth + wordSize > width) { // Break word onto next line *(wordStart - 1) = '\0'; ++numLines; - lineWidth = textWidth(wordStart, (int) (wordEnd - wordStart + 1)); + if (newLine) + lineWidth = 0; + else + lineWidth = textWidth(wordStart, (int) (wordEnd - wordStart + 1)); } else if (newLine) { // Break on newline ++numLines; - ++wordEnd; *wordEnd = '\0'; lineWidth = 0; } else { @@ -345,10 +339,29 @@ Surface *Surface::newDialog(uint16 width, const char *line, uint8 colour) { } // Set up a list for the start of each line - char **lines = (char **) Memory::alloc(sizeof(char *) * numLines); - lines[0] = lineCopy; + lines = (char **) Memory::alloc(sizeof(char *) * numLines); + lines[0] = text; for (int ctr = 1; ctr < numLines; ++ctr) lines[ctr] = strchr(lines[ctr-1], 0) + 1; +} + +Surface *Surface::newDialog(uint16 width, uint8 numLines, char **lines, bool varLength, uint8 colour) { + Surface *s = new Surface(width, (DIALOG_EDGE_SIZE + 3) * 2 + + numLines * (FONT_HEIGHT - 1)); + s->createDialog(); + + for (uint8 ctr = 0; ctr < numLines; ++ctr) + s->writeString(DIALOG_EDGE_SIZE + 3, DIALOG_EDGE_SIZE + 3 + + (ctr * (FONT_HEIGHT - 1)), lines[ctr], true, colour, varLength); + return s; +} + +Surface *Surface::newDialog(uint16 width, const char *line, uint8 colour) { + char **lines; + char *lineCopy = strdup(line); + uint8 numLines; + wordWrap(lineCopy, width - (DIALOG_EDGE_SIZE + 3) * 2, lines, numLines); + // Create the dialog Surface *result = newDialog(width, numLines, lines, true, colour); @@ -387,12 +400,11 @@ void Dialog::show(const char *text) { void Dialog::show(uint16 stringId) { char buffer[MAX_DESC_SIZE]; + Resources &res = Resources::getReference(); Room &r = Room::getReference(); StringData &sl = StringData::getReference(); - Action action = r.getCurrentAction(); - - const char *actionName = (action == NONE) ? NULL : actionList[action]; + const char *actionName = res.getCurrentActionStr(); char hotspotName[MAX_HOTSPOT_NAME_SIZE]; if (r.hotspotId() == 0) strcpy(hotspotName, ""); @@ -453,4 +465,89 @@ void Dialog::showMessage(uint16 messageId, uint16 characterId) { } } +/*--------------------------------------------------------------------------*/ + +TalkDialog::TalkDialog(uint16 characterId, uint16 descId) { + StringData &strings = StringData::getReference(); + Resources &res = Resources::getReference(); + HotspotData *character = res.getHotspot(characterId); + char charName[MAX_DESC_SIZE]; + strings.getString(character->nameId, charName, NULL, NULL); + strings.getString(descId, _desc, NULL, NULL); + + // Apply word wrapping to figure out the needed size of the dialog + Surface::wordWrap(_desc, TALK_DIALOG_WIDTH - TALK_DIALOG_EDGE_SIZE * 2 - 2, + _lines, _numLines); + + _surface = new Surface(TALK_DIALOG_WIDTH, + (_numLines + 1) * FONT_HEIGHT + TALK_DIALOG_EDGE_SIZE * 4); + + // Draw the dialog + byte *pSrc = res.getTalkDialogData().data(); + byte *pDest = _surface->data().data(); + int xPos, yPos; + + // Handle the dialog top + for (yPos = 0; yPos < TALK_DIALOG_EDGE_SIZE; ++yPos) { + *pDest++ = *pSrc++; + *pDest++ = *pSrc++; + + for (xPos = 0; xPos < TALK_DIALOG_WIDTH - TALK_DIALOG_EDGE_SIZE - 2; ++xPos) + *pDest++ = *pSrc; + ++pSrc; + + for (xPos = 0; xPos < TALK_DIALOG_EDGE_SIZE; ++xPos) + *pDest++ = *pSrc++; + } + + // Handle the middle section + for (yPos = 0; yPos < _surface->height() - TALK_DIALOG_EDGE_SIZE * 2; ++yPos) { + byte *pSrcTemp = pSrc; + + // Left edge + for (xPos = 0; xPos < TALK_DIALOG_EDGE_SIZE; ++xPos) + *pDest++ = *pSrcTemp++; + + // Middle section + for (xPos = 0; xPos < _surface->width() - TALK_DIALOG_EDGE_SIZE * 2; ++xPos) + *pDest++ = *pSrcTemp; + ++pSrcTemp; + + // Right edge + for (xPos = 0; xPos < TALK_DIALOG_EDGE_SIZE; ++xPos) + *pDest++ = *pSrcTemp++; + } + + // Bottom section + pSrc += TALK_DIALOG_EDGE_SIZE * 2 + 1; + for (yPos = 0; yPos < TALK_DIALOG_EDGE_SIZE; ++yPos) { + for (xPos = 0; xPos < TALK_DIALOG_EDGE_SIZE; ++xPos) + *pDest++ = *pSrc++; + + for (xPos = 0; xPos < TALK_DIALOG_WIDTH - TALK_DIALOG_EDGE_SIZE - 2; ++xPos) + *pDest++ = *pSrc; + ++pSrc; + + *pDest++ = *pSrc++; + *pDest++ = *pSrc++; + } + + // Write out the character name + uint16 charWidth = Surface::textWidth(charName); + _surface->writeString((TALK_DIALOG_WIDTH-charWidth)/2, TALK_DIALOG_EDGE_SIZE + 2, + charName, true, DIALOG_WHITE_COLOUR); + + // TEMPORARY CODE - write out description. More properly, the text is meant to + // be displayed slowly, word by word + for (int lineCtr = 0; lineCtr < _numLines; ++lineCtr) + _surface->writeString(TALK_DIALOG_EDGE_SIZE + 2, + TALK_DIALOG_EDGE_SIZE + 4 + (lineCtr + 1) * FONT_HEIGHT, + _lines[lineCtr], true); +} + +TalkDialog::~TalkDialog() { + delete _lines; + delete _surface; +} + } // end of namespace Lure diff --git a/engines/lure/surface.h b/engines/lure/surface.h index 9febf542f5..730a824ac1 100644 --- a/engines/lure/surface.h +++ b/engines/lure/surface.h @@ -66,6 +66,7 @@ public: void centerOnScreen(); static uint16 textWidth(const char *s, int numChars = 0); + static void wordWrap(char *text, uint16 width, char **&lines, uint8 &numLines); static Surface *newDialog(uint16 width, uint8 numLines, char **lines, bool varLength = true, uint8 colour = DIALOG_TEXT_COLOUR); static Surface *newDialog(uint16 width, const char *lines, uint8 colour = DIALOG_TEXT_COLOUR); static Surface *getScreen(uint16 resourceId); @@ -78,6 +79,20 @@ public: static void showMessage(uint16 messageId, uint16 characterId); }; +class TalkDialog { +private: + Surface *_surface; + char _desc[MAX_DESC_SIZE]; + char **_lines; + uint8 _numLines; +public: + TalkDialog(uint16 characterId, uint16 descId); + ~TalkDialog(); + + char *desc() { return _desc; } + Surface &surface() { return *_surface; } +}; + } // End of namespace Lure #endif |