aboutsummaryrefslogtreecommitdiff
path: root/engines/sherlock/tattoo/widget_foolscap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sherlock/tattoo/widget_foolscap.cpp')
-rw-r--r--engines/sherlock/tattoo/widget_foolscap.cpp299
1 files changed, 299 insertions, 0 deletions
diff --git a/engines/sherlock/tattoo/widget_foolscap.cpp b/engines/sherlock/tattoo/widget_foolscap.cpp
new file mode 100644
index 0000000000..8246e9a371
--- /dev/null
+++ b/engines/sherlock/tattoo/widget_foolscap.cpp
@@ -0,0 +1,299 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "sherlock/tattoo/widget_foolscap.h"
+#include "sherlock/tattoo/tattoo_fixed_text.h"
+#include "sherlock/tattoo/tattoo_scene.h"
+#include "sherlock/tattoo/tattoo_user_interface.h"
+#include "sherlock/tattoo/tattoo.h"
+
+namespace Sherlock {
+
+namespace Tattoo {
+
+WidgetFoolscap::WidgetFoolscap(TattooEngine *vm) : WidgetBase(vm) {
+ for (int idx = 0; idx < 3; ++idx) {
+ Common::fill(&_answers[idx][0], &_answers[idx][10], 0);
+ _solutions[idx] = nullptr;
+ }
+ _images = nullptr;
+ _numWide = 0;
+ _spacing = 0;
+ _blinkFlag = false;
+ _blinkCounter = 0;
+ _lineNum = _charNum = 0;
+ _solved = false;
+}
+
+WidgetFoolscap::~WidgetFoolscap() {
+ delete _images;
+}
+
+void WidgetFoolscap::show() {
+ Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+
+ switch (_vm->getLanguage()) {
+ case Common::FR_FRA:
+ _lines[0] = Common::Point(34, 210);
+ _lines[1] = Common::Point(72, 242);
+ _lines[2] = Common::Point(34, 276);
+ _numWide = 8;
+ _spacing = 19;
+ _images = new ImageFile("paperf.vgs");
+ break;
+
+ case Common::DE_DEU:
+ _lines[0] = Common::Point(44, 73);
+ _lines[1] = Common::Point(56, 169);
+ _lines[2] = Common::Point(47, 256);
+ _numWide = 7;
+ _spacing = 19;
+ _images = new ImageFile("paperg.vgs");
+ break;
+
+ default:
+ // English
+ _lines[0] = Common::Point(65, 84);
+ _lines[1] = Common::Point(65, 159);
+ _lines[2] = Common::Point(75, 234);
+ _numWide = 5;
+ _spacing = 20;
+ _images = new ImageFile("paper.vgs");
+ break;
+ }
+
+ _solved = false;
+ _blinkFlag = false;
+ _blinkCounter = 0;
+ _lineNum = _charNum = 0;
+ _cursorPos = Common::Point(_lines[0].x + 8 - screen.widestChar() / 2, _lines[0].y - screen.fontHeight() - 2);
+
+ // Set up window bounds
+ ImageFrame &paperFrame = (*_images)[0];
+ _bounds = Common::Rect(paperFrame._width, paperFrame._height);
+ _bounds.moveTo(screen._currentScroll.x + (SHERLOCK_SCREEN_WIDTH - paperFrame._width) / 2,
+ (SHERLOCK_SCREEN_HEIGHT - paperFrame._height) / 2);
+
+ // Clear answer data and set correct solution strings
+ for (int idx = 0; idx < 3; ++idx)
+ Common::fill(&_answers[idx][0], &_answers[idx][10], 0);
+ _solutions[0] = FIXED(Apply);
+ _solutions[1] = FIXED(Water);
+ _solutions[2] = FIXED(Heat);
+
+ // Set up the window background
+ _surface.create(_bounds.width(), _bounds.height());
+ _surface.blitFrom(paperFrame, Common::Point(0, 0));
+
+ // If they have already solved the puzzle, put the answer on the graphic
+ if (_vm->readFlags(299)) {
+ Common::Point cursorPos;
+ for (int line = 0; line < 3; ++line) {
+ cursorPos.y = _lines[line].y - screen.fontHeight() - 2;
+
+ for (uint idx = 0; idx < strlen(_solutions[line]); ++idx) {
+ cursorPos.x = _lines[line].x + 8 - screen.widestChar() / 2 + idx * _spacing;
+ char c = _solutions[line][idx];
+
+ Common::String str = Common::String::format("%c", c);
+ _surface.writeString(str, Common::Point(cursorPos.x + screen.widestChar() / 2
+ - screen.charWidth(c) / 2, cursorPos.y), 0);
+ }
+ }
+ }
+
+ // Show the window
+ summonWindow();
+ ui._menuMode = FOOLSCAP_MODE;
+}
+
+void WidgetFoolscap::handleEvents() {
+ Events &events = *_vm->_events;
+ Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ Common::Point mousePos = events.mousePos();
+ byte cursorColor = 254;
+
+ if (events._firstPress && !_bounds.contains(mousePos))
+ _outsideMenu = true;
+
+ // If they have not solved the puzzle, let them solve it here
+ if (!_vm->readFlags(299)) {
+ if (!ui._keyState.keycode) {
+ if (--_blinkCounter < 0) {
+ _blinkCounter = 3;
+ _blinkFlag = !_blinkFlag;
+
+ if (_blinkFlag) {
+ // Draw the caret
+ _surface.fillRect(Common::Rect(_cursorPos.x, _cursorPos.y, _cursorPos.x + screen.widestChar() - 1,
+ _cursorPos.y + screen.fontHeight() - 1), cursorColor);
+
+ if (_answers[_lineNum][_charNum]) {
+ Common::String str = Common::String::format("%c", _answers[_lineNum][_charNum]);
+ _surface.writeString(str, Common::Point(_cursorPos.x + screen.widestChar() / 2
+ - screen.charWidth(_answers[_lineNum][_charNum]) / 2, _cursorPos.y), 0);
+ }
+ } else {
+ // Restore background
+ restoreChar();
+
+ // Draw the character at that position if there is one
+ if (_answers[_lineNum][_charNum]) {
+ Common::String str = Common::String::format("%c", _answers[_lineNum][_charNum]);
+ _surface.writeString(str, Common::Point(_cursorPos.x + screen.widestChar() / 2
+ - screen.charWidth(_answers[_lineNum][_charNum]) / 2, _cursorPos.y), 0);
+ }
+ }
+ }
+ } else {
+ // Handle keyboard events
+ handleKeyboardEvents();
+ }
+ }
+
+ if ((events._released || events._rightReleased) && _outsideMenu && !_bounds.contains(mousePos)) {
+ // Clicked outside window to close it
+ events.clearEvents();
+ close();
+ }
+}
+
+void WidgetFoolscap::handleKeyboardEvents() {
+ Screen &screen = *_vm->_screen;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ Common::KeyState keyState = ui._keyState;
+
+ if (((toupper(keyState.ascii) >= 'A') && (toupper(keyState.ascii) <= 'Z')) ||
+ ((keyState.ascii >= 128) && ((keyState.ascii <= 168) || (keyState.ascii == 225)))) {
+ // Visible key pressed, set it and set the keycode to move the caret to the right
+ _answers[_lineNum][_charNum] = keyState.ascii;
+ keyState.keycode = Common::KEYCODE_RIGHT;
+ }
+
+ // Restore background
+ restoreChar();
+
+ if (_answers[_lineNum][_charNum]) {
+ Common::String str = Common::String::format("%c", _answers[_lineNum][_charNum]);
+ _surface.writeString(str, Common::Point(_cursorPos.x + screen.widestChar() / 2
+ - screen.charWidth(_answers[_lineNum][_charNum]) / 2, _cursorPos.y), 0);
+ }
+
+ switch (keyState.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ close();
+ break;
+
+ case Common::KEYCODE_UP:
+ if (_lineNum) {
+ --_lineNum;
+ if (_charNum >= (int)strlen(_solutions[_lineNum]))
+ _charNum = (int)strlen(_solutions[_lineNum]) - 1;
+ }
+ break;
+
+ case Common::KEYCODE_DOWN:
+ if (_lineNum < 2) {
+ ++_lineNum;
+ if (_charNum >= (int)strlen(_solutions[_lineNum]))
+ _charNum = (int)strlen(_solutions[_lineNum]) - 1;
+ }
+ break;
+
+ case Common::KEYCODE_BACKSPACE:
+ case Common::KEYCODE_LEFT:
+ if (_charNum)
+ --_charNum;
+ else if (_lineNum) {
+ --_lineNum;
+
+ _charNum = strlen(_solutions[_lineNum]) - 1;
+ }
+
+ if (keyState.keycode == Common::KEYCODE_BACKSPACE)
+ _answers[_lineNum][_charNum] = ' ';
+ break;
+
+ case Common::KEYCODE_RIGHT:
+ if (_charNum < (int)strlen(_solutions[_lineNum]) - 1)
+ ++_charNum;
+ else if (_lineNum < 2) {
+ ++_lineNum;
+ _charNum = 0;
+ }
+ break;
+
+ case Common::KEYCODE_DELETE:
+ _answers[_lineNum][_charNum] = ' ';
+ break;
+
+ default:
+ break;
+ }
+
+ _cursorPos.x = _lines[_lineNum].x + 8 - screen.widestChar() / 2 + _charNum * _spacing;
+ _cursorPos.y = _lines[_lineNum].y - screen.fontHeight() - 2;
+
+ // See if all of their anwers are correct
+ if (!scumm_stricmp(_answers[0], _solutions[0]) && !scumm_stricmp(_answers[1], _solutions[1])
+ && !scumm_stricmp(_answers[2], _solutions[2])) {
+ _solved = true;
+ close();
+ }
+}
+
+void WidgetFoolscap::restoreChar() {
+ Screen &screen = *_vm->_screen;
+ ImageFrame &bgFrame = (*_images)[0];
+ _surface.blitFrom(bgFrame, _cursorPos, Common::Rect(_cursorPos.x, _cursorPos.y,
+ _cursorPos.x + screen.widestChar(), _cursorPos.y + screen.fontHeight()));
+}
+
+void WidgetFoolscap::close() {
+ TattooScene &scene = *(TattooScene *)_vm->_scene;
+ Talk &talk = *_vm->_talk;
+ TattooUserInterface &ui = *(TattooUserInterface *)_vm->_ui;
+ delete _images;
+ _images = nullptr;
+
+ // Close the window
+ banishWindow();
+ ui._menuMode = scene._labTableScene ? LAB_MODE : STD_MODE;
+
+ // Don't call the talk files if the puzzle has already been solved
+ if (!_vm->readFlags(299)) {
+ // Run the appropriate script depending on whether or not they solved the puzzle correctly
+ if (_solved) {
+ talk.talkTo("SLVE12S.TLK");
+ talk.talkTo("WATS12X.TLK");
+ _vm->setFlags(299);
+ } else {
+ talk.talkTo("HOLM12X.TLK");
+ }
+ }
+}
+
+} // End of namespace Tattoo
+
+} // End of namespace Sherlock