aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2009-12-17 07:55:08 +0000
committerPaul Gilbert2009-12-17 07:55:08 +0000
commit575308cea724b214d7f83a06cf8819f15b1e4f75 (patch)
tree19d691025b2c9040698b196cd66b74f4fffaed2e
parent690a410423207c3df4c6cf9427167c0948f08ad4 (diff)
downloadscummvm-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.cpp2
-rw-r--r--engines/m4/dialogs.cpp192
-rw-r--r--engines/m4/dialogs.h11
-rw-r--r--engines/m4/font.cpp2
-rw-r--r--engines/m4/font.h2
-rw-r--r--engines/m4/scene.cpp2
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);
}