TONY: Use Common::String in writeText.

This uses an array of lines rather than trying to stick nulls into
the string, and so fixes wrapping on hyphens (which overwrote the
character before the hyphen). Thanks to eriktorbjorn for both
finding the bug and working out what was going wrong.
This commit is contained in:
Alyssa Milburn 2012-08-24 22:35:22 +02:00
parent af134e0244
commit f917a4beab
3 changed files with 47 additions and 42 deletions

View file

@ -1801,7 +1801,7 @@ void RMText::removeThis(CORO_PARAM, bool &result) {
result = true; result = true;
} }
void RMText::writeText(const RMString &text, int nFont, int *time) { void RMText::writeText(const Common::String &text, int nFont, int *time) {
// Initializes the font (only once) // Initializes the font (only once)
if (_fonts[0] == NULL) { if (_fonts[0] == NULL) {
_fonts[0] = new RMFontDialog; _fonts[0] = new RMFontDialog;
@ -1817,15 +1817,13 @@ void RMText::writeText(const RMString &text, int nFont, int *time) {
writeText(text, _fonts[nFont], time); writeText(text, _fonts[nFont], time);
} }
void RMText::writeText(const RMString &text, RMFontColor *font, int *time) { void RMText::writeText(Common::String text, RMFontColor *font, int *time) {
RMGfxPrimitive *prim; RMGfxPrimitive *prim;
char *p, *old_p; uint p, old_p;
int i, j, x, y; int j, x, y;
int len; int len;
int numchar; int numchar;
int width, height; int width, height;
char *string;
int numlines;
// Set the base color // Set the base color
font->setBaseColor(_textR, _textG, _textB); font->setBaseColor(_textR, _textG, _textB);
@ -1834,17 +1832,18 @@ void RMText::writeText(const RMString &text, RMFontColor *font, int *time) {
destroy(); destroy();
// If the string is empty, do nothing // If the string is empty, do nothing
if (text == NULL || text[0] == '\0') if (text.empty())
return; return;
// Divide the words into lines. In this cycle, X contains the maximum length reached by a line, // Divide the words into lines. In this cycle, X contains the maximum length reached by a line,
// and the number of lines // and the number of lines
string = p = text; Common::Array<Common::String> lines;
i = j = x = 0; p = 0;
while (*p != '\0') { j = x = 0;
j += font->stringLen(*p); while (p < text.size()) {
if (j > (((_aHorType == HLEFTPAR) && (i > 0)) ? _maxLineLength - 25 : _maxLineLength)) { j += font->stringLen(text[p]);
j -= font->stringLen(*p, p[1]); if (j > (((_aHorType == HLEFTPAR) && (lines.size() > 0)) ? _maxLineLength - 25 : _maxLineLength)) {
j -= font->stringLen(text[p], (p + 1 == text.size()) ? '\0' : text[p + 1]);
if (j > x) if (j > x)
x = j; x = j;
@ -1855,21 +1854,24 @@ void RMText::writeText(const RMString &text, RMFontColor *font, int *time) {
// This workaround has the partial word broken up so it will still display // This workaround has the partial word broken up so it will still display
// //
old_p = p; old_p = p;
while (*p != ' ' && *p != '-' && p > string) while (text[p] != ' ' && text[p] != '-' && p > 0)
p--; p--;
if (p == string) if (p == 0)
p = old_p; p = old_p;
// Check if there are any blanks to end // Check if there are any blanks to end
while (*p == ' ' && *p != '\0') while ((text[p] == ' ' || text[p] == '-') && p + 1 < text.size())
p++; p++;
if (*p == '\0') if (p == text.size())
break; break;
p--; lines.push_back(Common::String(text.c_str(), p));
i++; if (text[p] == ' ')
*p = '\0'; p++;
text = text.c_str() + p;
p = 0;
j = 0; j = 0;
continue;
} }
p++; p++;
} }
@ -1877,27 +1879,29 @@ void RMText::writeText(const RMString &text, RMFontColor *font, int *time) {
if (j > x) if (j > x)
x = j; x = j;
i++; // Add the last line of text.
numlines = i; lines.push_back(text);
x += 8; x += 8;
// Starting position for the surface: X1, Y // Starting position for the surface: X1, Y
width = x; width = x;
height = (numlines - 1) * font->letterHeight() + font->_fontDimy; height = (lines.size() - 1) * font->letterHeight() + font->_fontDimy;
// Create the surface // Create the surface
create(width, height); create(width, height);
Common::fill(_buf, _buf + width * height * 2, 0); Common::fill(_buf, _buf + width * height * 2, 0);
p = string; p = 0;
y = 0; y = 0;
numchar = 0; numchar = 0;
for (; i > 0; i--) { for (uint i = 0; i < lines.size(); ++i) {
const Common::String &line = lines[i];
// Measure the length of the line // Measure the length of the line
x = 0; x = 0;
j = font->stringLen(RMString(p)); j = font->stringLen(RMString(line.c_str()));
switch (_aHorType) { switch (_aHorType) {
case HLEFT: case HLEFT:
@ -1905,7 +1909,7 @@ void RMText::writeText(const RMString &text, RMFontColor *font, int *time) {
break; break;
case HLEFTPAR: case HLEFTPAR:
if (i == numlines) if (i == 0)
x = 0; x = 0;
else else
x = 25; x = 25;
@ -1920,21 +1924,22 @@ void RMText::writeText(const RMString &text, RMFontColor *font, int *time) {
break; break;
} }
while (*p != '\0') { p = 0;
if (*p == ' ') { while (p < line.size()) {
x += font->stringLen(*p); if (line[p] == ' ') {
x += font->stringLen(line[p]);
p++; p++;
continue; continue;
} }
prim = font->makeLetterPrimitive(*p, len); prim = font->makeLetterPrimitive(line[p], len);
prim->getDst()._x1 = x; prim->getDst()._x1 = x;
prim->getDst()._y1 = y; prim->getDst()._y1 = y;
addPrim(prim); addPrim(prim);
numchar++; numchar++;
x += font->stringLen(*p, p[1]); x += font->stringLen(line[p], (p + 1 == line.size()) ? '\0' : line[p + 1]);
p++; p++;
} }
p++; p++;
@ -2021,14 +2026,14 @@ void RMTextDialog::hide(CORO_PARAM) {
} }
void RMTextDialog::writeText(const RMString &text, int font, int *time) { void RMTextDialog::writeText(const RMString &text, int font, int *time) {
RMText::writeText(text, font, &_time); RMText::writeText(Common::String(text), font, &_time);
if (time != NULL) if (time != NULL)
*time = _time; *time = _time;
} }
void RMTextDialog::writeText(const RMString &text, RMFontColor *font, int *time) { void RMTextDialog::writeText(const RMString &text, RMFontColor *font, int *time) {
RMText::writeText(text, font, &_time); RMText::writeText(Common::String(text), font, &_time);
if (time != NULL) if (time != NULL)
*time = _time; *time = _time;
@ -2251,7 +2256,7 @@ void RMTextItemName::doFrame(CORO_PARAM, RMGfxTargetBuffer &bigBuf, RMLocation &
_item->getName(itemName); _item->getName(itemName);
// Write it // Write it
writeText(itemName, 1); writeText(Common::String(itemName), 1);
// Handle the change If the selected item is different from the previous one // Handle the change If the selected item is different from the previous one
if (_ctx->lastItem != _item) { if (_ctx->lastItem != _item) {
@ -2389,7 +2394,7 @@ void RMDialogChoice::setNumChoices(int num) {
void RMDialogChoice::addChoice(const RMString &string) { void RMDialogChoice::addChoice(const RMString &string) {
// Draw the string // Draw the string
assert(_curAdded < _numChoices); assert(_curAdded < _numChoices);
_drawedStrings[_curAdded++].writeText(string, 0); _drawedStrings[_curAdded++].writeText(Common::String(string), 0);
} }
void RMDialogChoice::prepare(CORO_PARAM) { void RMDialogChoice::prepare(CORO_PARAM) {

View file

@ -215,8 +215,8 @@ public:
void setMaxLineLength(int max); void setMaxLineLength(int max);
// Write the text // Write the text
void writeText(const RMString &text, int font, int *time = NULL); void writeText(const Common::String &text, int font, int *time = NULL);
void writeText(const RMString &text, RMFontColor *font, int *time = NULL); void writeText(Common::String text, RMFontColor *font, int *time = NULL);
// Overloaded function to decide when you delete the object from the OT list // Overloaded function to decide when you delete the object from the OT list
virtual void removeThis(CORO_PARAM, bool &result); virtual void removeThis(CORO_PARAM, bool &result);

View file

@ -506,15 +506,15 @@ void RMOptionScreen::refreshAll(CORO_PARAM) {
} }
for (_ctx->i = 0; _ctx->i < 6; _ctx->i++) { for (_ctx->i = 0; _ctx->i < 6; _ctx->i++) {
RMString s; Common::String s;
if (_bEditSaveName && _nEditPos == _ctx->i) if (_bEditSaveName && _nEditPos == _ctx->i)
s.format("%02d)%s*", _statePos + _ctx->i, _editName); s = Common::String::format("%02d)%s*", _statePos + _ctx->i, _editName);
else { else {
if (_statePos == 0 && _ctx->i == 0) if (_statePos == 0 && _ctx->i == 0)
s.format("Autosave"); s = "Autosave";
else else
s.format("%02d)%s", _statePos + _ctx->i, (const char *)_curThumbName[_ctx->i]); s = Common::String::format("%02d)%s", _statePos + _ctx->i, (const char *)_curThumbName[_ctx->i]);
} }
_ctx->num[_ctx->i] = new RMText; _ctx->num[_ctx->i] = new RMText;