void TextMgr::inputEditOff() { if (_inputEditEnabled) { _inputEditEnabled = false; if (_inputCursorChar) { displayCharacter(_inputCursorChar); } } }
void TextMgr::inputEditOn() { if (!_inputEditEnabled) { _inputEditEnabled = true; if (_inputCursorChar) { displayCharacter(0x08); // backspace } } }
void TextMgr::displayText(const char *textPtr, bool disabledLook) { const char *curTextPtr = textPtr; byte curCharacter = 0; while (1) { curCharacter = *curTextPtr; if (!curCharacter) break; curTextPtr++; displayCharacter(curCharacter, disabledLook); } }
void TextMgr::stringEdit(int16 stringMaxLen) { int16 inputStringLen = strlen((const char *)_inputString); // Remember current position for predictive dialog _inputStringRow = _textPos.row; _inputStringColumn = _textPos.column; if (_inputCursorChar) { // Cursor character is shown, which means we are one beyond the start of the input // Adjust the column for predictive input dialog _inputStringColumn--; } // Caller can set the input string _inputStringCursorPos = 0; while (_inputStringCursorPos < inputStringLen) { displayCharacter(_inputString[_inputStringCursorPos]); _inputStringCursorPos++; } // should never happen unless there is a coding glitch assert(_inputStringCursorPos <= stringMaxLen); _inputStringMaxLen = stringMaxLen; _inputStringEntered = false; inputEditOff(); do { _vm->processAGIEvents(); } while (_vm->cycleInnerLoopIsActive() && !(_vm->shouldQuit() || _vm->_restartGame)); inputEditOn(); // Forget non-blocking text, user was asked to enter something _vm->nonBlockingText_Forget(); }
void TextMgr::displayCharacter(byte character, bool disabledLook) { TextPos_Struct charCurPos; charPos_Get(&charCurPos); switch (character) { case 0x08: // backspace if (charCurPos.column) { charCurPos.column--; } else if (charCurPos.row > 21) { charCurPos.column = (FONT_COLUMN_CHARACTERS - 1); charCurPos.row--; } clearBlock(charCurPos.row, charCurPos.column, charCurPos.row, charCurPos.column, _textAttrib.background); charPos_Set(&charCurPos); break; case 0x0D: case 0x0A: // CR/LF if (charCurPos.row < (FONT_ROW_CHARACTERS - 1)) charCurPos.row++; charCurPos.column = _reset_Column; charPos_Set(&charCurPos); break; default: // ch_attrib(state.text_comb, conversion); _gfx->drawCharacter(charCurPos.row, charCurPos.column, character, _textAttrib.combinedForeground, _textAttrib.combinedBackground, disabledLook); charCurPos.column++; if (charCurPos.column <= (FONT_COLUMN_CHARACTERS - 1)) { charPos_Set(&charCurPos); } else { displayCharacter(0x0D); // go to next line } } }
void TextMgr::stringKeyPress(uint16 newKey) { inputEditOn(); switch (newKey) { case 0x3: // ctrl-c case 0x18: { // ctrl-x // clear string while (_inputStringCursorPos) { _inputStringCursorPos--; _inputString[_inputStringCursorPos] = 0; displayCharacter(0x08); } break; } case AGI_KEY_BACKSPACE: { if (_inputStringCursorPos) { _inputStringCursorPos--; _inputString[_inputStringCursorPos] = 0; displayCharacter(newKey); stringRememberForAutoComplete(); } break; } case AGI_KEY_ENTER: { stringRememberForAutoComplete(true); _inputStringEntered = true; _vm->cycleInnerLoopInactive(); // exit GetString-loop break; } case AGI_KEY_ESCAPE: { _inputString[0] = 0; _inputStringCursorPos = 0; _inputStringEntered = false; _vm->cycleInnerLoopInactive(); // exit GetString-loop break; } default: if (_inputStringMaxLen > _inputStringCursorPos) { bool acceptableInput = false; // FEATURE: Sierra didn't check for valid characters (filtered out umlauts etc.) // In text-mode this sort of worked at least with the DOS interpreter // but as soon as invalid characters were used in graphics mode they weren't properly shown switch (_vm->getLanguage()) { case Common::RU_RUS: if (newKey >= 0x20) acceptableInput = true; break; default: if ((newKey >= 0x20) && (newKey <= 0x7f)) acceptableInput = true; break; } if (acceptableInput) { if ((_vm->_game.cycleInnerLoopType == CYCLE_INNERLOOP_GETSTRING) || ((newKey >= '0') && (newKey <= '9'))) { // Additionally check for GETNUMBER-mode, if character is a number // Sierra also did not do this _inputString[_inputStringCursorPos] = newKey; _inputStringCursorPos++; _inputString[_inputStringCursorPos] = 0; displayCharacter(newKey); stringRememberForAutoComplete(); } } } break; } inputEditOff(); }
void TextMgr::promptKeyPress(uint16 newKey) { int16 maxChars = 0; int16 scriptsInputLen = _vm->getVar(VM_VAR_MAX_INPUT_CHARACTERS); if (_messageState.dialogue_Open) { maxChars = TEXT_STRING_MAX_SIZE - 4; } else { maxChars = TEXT_STRING_MAX_SIZE - strlen(_vm->_game.strings[0]); // string 0 is the prompt string prefix } if (_promptCursorPos) maxChars--; if (scriptsInputLen < maxChars) maxChars = scriptsInputLen; inputEditOn(); switch (newKey) { case AGI_KEY_BACKSPACE: { if (_promptCursorPos) { _promptCursorPos--; _prompt[_promptCursorPos] = 0; displayCharacter(newKey); promptRememberForAutoComplete(); } break; } case 0x0A: // LF break; case AGI_KEY_ENTER: { if (_promptCursorPos) { // something got entered? -> process it and pass it to the scripts promptRememberForAutoComplete(true); memcpy(&_promptPrevious, &_prompt, sizeof(_prompt)); // parse text _vm->_words->parseUsingDictionary((char *)&_prompt); _promptCursorPos = 0; _prompt[0] = 0; promptRedraw(); } break; } default: if (maxChars > _promptCursorPos) { bool acceptableInput = false; // FEATURE: Sierra didn't check for valid characters (filtered out umlauts etc.) // In text-mode this sort of worked at least with the DOS interpreter // but as soon as invalid characters were used in graphics mode they weren't properly shown switch (_vm->getLanguage()) { case Common::RU_RUS: if (newKey >= 0x20) acceptableInput = true; break; default: if ((newKey >= 0x20) && (newKey <= 0x7f)) acceptableInput = true; break; } if (acceptableInput) { _prompt[_promptCursorPos] = newKey; _promptCursorPos++; _prompt[_promptCursorPos] = 0; displayCharacter(newKey); promptRememberForAutoComplete(); } } break; } inputEditOff(); }
void H19::processCharacter(char ch) { // mask off the high bit just in case, the real H19 would not have it set. ch &= 0x7f; if (mode_m == Normal) { switch (ch) { case ascii::NUL: case ascii::SOH: case ascii::STX: case ascii::ETX: case ascii::EOT: case ascii::ENQ: case ascii::ACK: case ascii::VT: case ascii::FF: case ascii::SO: case ascii::SI: case ascii::DLE: case ascii::DC1: case ascii::DC2: case ascii::DC3: case ascii::DC4: case ascii::NAK: case ascii::SYN: case ascii::ETB: case ascii::EM: case ascii::SUB: case ascii::FS: case ascii::GS: case ascii::RS: case ascii::US: case ascii::DEL: // From manual, these characters are not processed by the terminal break; case ascii::BEL: // Rings the bell. /// \todo - implement ringing bell. consoleLog("<BEL>"); break; case ascii::BS: // Backspace consoleLog("<BS>"); processBS(); break; case ascii::HT: // Horizontal Tab consoleLog("<TAB>"); processTAB(); break; case ascii::LF: // Line Feed processLF(); if (autoCR_m) { processCR(); } consoleLog("\n"); break; case ascii::CR: // Carriage Return processCR(); if (autoLF_m) { processLF(); } break; case ascii::CAN: // Cancel. break; case ascii::ESC: // Escape mode_m = Escape; consoleLog("<ESC>"); break; default: // if Printable character display it. #if CONSOLE_LOG fprintf(console_out, "%c", ch); #endif displayCharacter(ch); break; } } else if (mode_m == Escape) { // Assume we go back to Normal, so only the few that don't need to set the mode. mode_m = Normal; switch (ch) { case ascii::CAN: // CAN - Cancel // return to Normal mode, already set. break; case ascii::ESC: // Escape // From the ROM listing, stay in this mode. mode_m = Escape; break; // Cursor Functions case 'H': // Cursor Home posX_m = posY_m = 0; updated_m = true; break; case 'C': // Cursor Forward cursorForward(); break; case 'D': // Cursor Backward processBS(); // same processing as cursor backward break; case 'B': // Cursor Down cursorDown(); break; case 'A': // Cursor Up cursorUp(); break; case 'I': // Reverse Index reverseIndex(); break; case 'n': // Cursor Position Report cursorPositionReport(); break; case 'j': // Save cursor position saveCursorPosition(); break; case 'k': // Restore cursor position restoreCursorPosition(); break; case 'Y': // Direct Cursor Addressing mode_m = DCA_1; break; // Erase and Editing case 'E': // Clear Display clearDisplay(); break; case 'b': // Erase Beginning of Display eraseBOD(); break; case 'J': // Erase to End of Page eraseEOP(); break; case 'l': // Erase entire Line eraseEL(); break; case 'o': // Erase Beginning Of Line eraseBOL(); break; case 'K': // Erase To End Of Line eraseEOL(); break; case 'L': // Insert Line insertLine(); break; case 'M': // Delete Line deleteLine(); break; case 'N': // Delete Character deleteChar(); break; case '@': // Enter Insert Character Mode insertMode_m = true; break; case 'O': // Exit Insert Character Mode insertMode_m = false; break; // Configuration case 'z': // Reset To Power-Up Configuration reset(); break; case 'r': // Modify the Baud Rate /// \todo - determine if we should support this. debugss(ssH19, ERROR, "Error Unimplemented Modify Baud\n"); break; case 'x': // Set Mode mode_m = SetMode; break; case 'y': // Reset Mode mode_m = ResetMode; break; case '<': // Enter ANSI Mode /// \todo - implement ANSI mode. // ROM - just sets the mode debugss(ssH19, ERROR, "Error Entering ANSI mode - unsupported\n"); break; // Modes of operation case '[': // Enter Hold Screen Mode holdScreen_m = true; break; case '\\': // Exit Hold Screen Mode holdScreen_m = false; break; case 'p': // Enter Reverse Video Mode reverseVideo_m = true; break; case 'q': // Exit Reverse Video Mode reverseVideo_m = false; break; case 'F': // Enter Graphics Mode graphicMode_m = true; break; case 'G': // Exit Graphics Mode graphicMode_m = false; break; case 't': // Enter Keypad Shifted Mode keypadShifted_m = true; break; case 'u': // Exit Keypad Shifted Mode // ROM - just sets the mode keypadShifted_m = false; break; case '=': // Enter Alternate Keypad Mode // ROM - just sets the mode keypadShifted_m = true; break; case '>': // Exit Alternate Keypad Mode // ROM - just sets the mode keypadShifted_m = false; break; // Additional Functions case '}': // Keyboard Disable /// \todo - determine whether to do this. keyboardEnabled_m = false; break; case '{': // Keyboard Enable keyboardEnabled_m = true; break; case 'v': // Wrap Around at End Of Line wrapEOL_m = true; break; case 'w': // Discard At End Of Line wrapEOL_m = false; break; case 'Z': // Identify as VT52 (Data: ESC / K) debugss(ssH19, ERROR, "Identify request\n"); sendData(ascii::ESC); sendData('/'); sendData('K'); break; case ']': // Transmit 25th Line transmitLine25(); break; case '#': // Transmit Page transmitPage(); break; default: debugss(ssH19, WARNING, "Unhandled ESC: %d\n", ch); /// \todo - verify this is how the H19 ROM does it. break; } } else if (mode_m == SetMode) { mode_m = Normal; switch (ch) { case '1': // Enable 25th line // From the ROM, it erases line 25 on the enable, but here we erase on the disable. line25_m = true; break; case '2': // No key click keyClick_m = true; break; case '3': // Hold screen mode holdScreen_m = true; break; case '4': // Block Cursor cursorBlock_m = true; updated_m = true; break; case '5': // Cursor Off cursorOff_m = true; updated_m = true; break; case '6': // Keypad Shifted keypadShifted_m = true; break; case '7': // Alternate Keypad mode altKeypadMode_m = true; break; case '8': // Auto LF autoLF_m = true; break; case '9': // Auto CR autoCR_m = true; break; default: /// \todo Need to process ch as if none of this happened... debugss(ssH19, WARNING, "Invalid set Mode: %c\n", ch); break; } } else if (mode_m == ResetMode) { mode_m = Normal; switch (ch) { case '1': // Disable 25th line eraseLine(rowsMain_c); line25_m = false; updated_m = true; break; case '2': // key click keyClick_m = false; break; case '3': // Hold screen mode holdScreen_m = false; break; case '4': // Block Cursor cursorBlock_m = false; updated_m = true; break; case '5': // Cursor On cursorOff_m = false; updated_m = true; break; case '6': // Keypad Unshifted keypadShifted_m = false; break; case '7': // Exit Alternate Keypad mode altKeypadMode_m = false; break; case '8': // No Auto LF autoLF_m = false; break; case '9': // No Auto CR autoCR_m = false; break; default: /// \todo Need to process ch as if none of this happened... debugss(ssH19, WARNING, "Invalid reset Mode: %c\n", ch); break; } } else if (mode_m == DCA_1) { // From actual H19, once the line is specified, the cursor // immediately moves to that line, so no need to save the // position and wait for the entire command. /// \todo verify that this is the same on newer H19s. if (ch == ascii::CAN) { // cancel mode_m = Normal; } else { // \todo handle error conditions int pos = ch - 31; // verify valid Position if (((pos > 0) && (pos < (signed) rows_c)) || ((pos == (signed) rows_c) && (line25_m))) { posY_m = pos - 1; } else { /// \todo check to see how a real h19 handles this. debugss(ssH19, INFO, "DCA invalid Y: %d\n", pos); } mode_m = DCA_2; } } else if (mode_m == DCA_2) { if (ch == ascii::CAN) { // cancel mode_m = Normal; } else { int pos = ch - 31; if ((pos > 0) && (pos < 81)) { posX_m = pos - 1; } else { posX_m = (cols_c - 1); } updated_m = true; mode_m = Normal; } } }