/** * Print text in the AGI engine screen. */ void AgiEngine::printText(const char *msg, int f, int x, int y, int len, int fg, int bg, bool checkerboard) { f *= CHAR_COLS; x *= CHAR_COLS; y *= CHAR_LINES; debugC(4, kDebugLevelText, "printText(): %s, %d, %d, %d, %d, %d, %d", msg, f, x, y, len, fg, bg); printText2(0, agiSprintf(msg), f, x, y, len, fg, bg, checkerboard); }
/** * Print user input prompt. */ void AgiEngine::writePrompt() { int l, fg, bg, pos; int promptLength = strlen(agiSprintf(_game.strings[0])); if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL) return; l = _game.lineUserInput; fg = _game.colorFg; bg = _game.colorBg; pos = _game.cursorPos; debugC(4, kDebugLevelText, "erase line %d", l); clearLines(l, l, _game.colorBg); debugC(4, kDebugLevelText, "prompt = '%s'", agiSprintf(_game.strings[0])); printText(_game.strings[0], 0, 0, l, promptLength + 1, fg, bg); printText((char *)_game.inputBuffer, 0, promptLength, l, pos + 1, fg, bg); _gfx->printCharacter(pos + promptLength, l, _game.cursorChar, fg, bg); flushLines(l, l); _gfx->doUpdate(); }
// // len is in characters, not pixels!! // void AgiEngine::blitTextbox(const char *p, int y, int x, int len) { // if x | y = -1, then center the box int xoff, yoff, lin, h, w; char *msg, *m; debugC(3, kDebugLevelText, "blitTextbox(): x=%d, y=%d, len=%d", x, y, len); if (_game.window.active) closeWindow(); if (x == 0 && y == 0 && len == 0) x = y = -1; if (len <= 0) len = 30; xoff = x * CHAR_COLS; yoff = y * CHAR_LINES; m = msg = wordWrapString(agiSprintf(p), &len); for (lin = 1; *m; m++) { // Test \r for MacOS 8 if (*m == '\n' || *m == '\r') lin++; } if (lin * CHAR_LINES > GFX_HEIGHT) lin = (GFX_HEIGHT / CHAR_LINES); w = (len + 2) * CHAR_COLS; h = (lin + 2) * CHAR_LINES; if (xoff < 0) xoff = (GFX_WIDTH - w - CHAR_COLS) / 2; else xoff -= CHAR_COLS; if (yoff < 0) yoff = (GFX_HEIGHT - 3 * CHAR_LINES - h) / 2; drawWindow(xoff, yoff, xoff + w - 1, yoff + h - 1); printText2(2, msg, 0, CHAR_COLS + xoff, CHAR_LINES + yoff, len + 1, MSG_BOX_TEXT, MSG_BOX_COLOR); free(msg); _gfx->doUpdate(); }
/** * Formats AGI string. * This function turns a AGI string into a real string expanding values * according to the AGI format specifiers. * @param s string containing the format specifier * @param n logic number */ char *AgiEngine::agiSprintf(const char *s) { static char agiSprintf_buf[768]; Common::String p; char z[16]; debugC(3, kDebugLevelText, "logic %d, '%s'", _game.lognum, s); while (*s) { switch (*s) { case '%': s++; switch (*s++) { int i; case 'v': i = strtoul(s, NULL, 10); while (*s >= '0' && *s <= '9') s++; sprintf(z, "%015i", getvar(i)); i = 99; if (*s == '|') { s++; i = strtoul(s, NULL, 10); while (*s >= '0' && *s <= '9') s++; } if (i == 99) { // remove all leading 0 // don't remove the 3rd zero if 000 for (i = 0; z[i] == '0' && i < 14; i++) ; } else { i = 15 - i; } safeStrcat(p, z + i); break; case '0': i = strtoul(s, NULL, 10) - 1; safeStrcat(p, objectName(i)); break; case 'g': i = strtoul(s, NULL, 10) - 1; safeStrcat(p, _game.logics[0].texts[i]); break; case 'w': i = strtoul(s, NULL, 10) - 1; safeStrcat(p, _game.egoWords[i].word); break; case 's': i = strtoul(s, NULL, 10); safeStrcat(p, agiSprintf(_game.strings[i])); break; case 'm': i = strtoul(s, NULL, 10) - 1; if (_game.logics[_game.lognum].numTexts > i) safeStrcat(p, agiSprintf(_game.logics[_game.lognum].texts[i])); break; } while (*s >= '0' && *s <= '9') s++; break; case '\\': s++; // FALL THROUGH default: p += *s++; break; } } assert(p.size() < sizeof(agiSprintf_buf)); strcpy(agiSprintf_buf, p.c_str()); return agiSprintf_buf; }
void AgiEngine::handleKeys(int key) { uint8 *p = NULL; int c = 0; static uint8 formattedEntry[40]; int l = _game.lineUserInput; int fg = _game.colorFg, bg = _game.colorBg; int promptLength = strlen(agiSprintf(_game.strings[0])); setvar(vWordNotFound, 0); debugC(3, kDebugLevelInput, "handling key: %02x", key); switch (key) { case KEY_ENTER: debugC(3, kDebugLevelInput, "KEY_ENTER"); _game.keypress = 0; // Remove all leading spaces for (p = _game.inputBuffer; *p && *p == 0x20; p++) ; // Copy to internal buffer for (; *p && c < 40-1; p++) { // Squash spaces if (*p == 0x20 && *(p + 1) == 0x20) { p++; continue; } formattedEntry[c++] = tolower(*p); } formattedEntry[c++] = 0; // Handle string only if it's not empty if (formattedEntry[0]) { strcpy((char *)_game.echoBuffer, (const char *)_game.inputBuffer); strcpy(_lastSentence, (const char *)formattedEntry); dictionaryWords(_lastSentence); } // Clear to start a new line _game.hasPrompt = 0; _game.inputBuffer[_game.cursorPos = 0] = 0; debugC(3, kDebugLevelInput | kDebugLevelText, "clear lines"); clearLines(l, l + 1, bg); flushLines(l, l + 1); #ifdef __DS__ DS::findWordCompletions((char *) _game.inputBuffer); #endif break; case KEY_ESCAPE: debugC(3, kDebugLevelInput, "KEY_ESCAPE"); newInputMode(INPUT_MENU); break; case KEY_BACKSPACE: // Ignore backspace at start of line if (_game.cursorPos == 0) break; // erase cursor _gfx->printCharacter(_game.cursorPos + promptLength, l, ' ', fg, bg); _game.inputBuffer[--_game.cursorPos] = 0; // Print cursor _gfx->printCharacter(_game.cursorPos + promptLength, l, _game.cursorChar, fg, bg); #ifdef __DS__ DS::findWordCompletions((char *) _game.inputBuffer); #endif break; default: // Ignore invalid keystrokes if (key < 0x20 || key > 0x7f) break; // Maximum input size reached if (_game.cursorPos >= getvar(vMaxInputChars)) break; _game.inputBuffer[_game.cursorPos++] = key; _game.inputBuffer[_game.cursorPos] = 0; #ifdef __DS__ DS::findWordCompletions((char *) _game.inputBuffer); #endif // echo _gfx->printCharacter(_game.cursorPos + promptLength - 1, l, _game.inputBuffer[_game.cursorPos - 1], fg, bg); // Print cursor _gfx->printCharacter(_game.cursorPos + promptLength, l, _game.cursorChar, fg, bg); break; } }