From ac559b0212c21c7f4a3a10455b8dff211d7ebb87 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 26 Oct 2011 01:48:20 +0300 Subject: SCI: Renamed GfxControls to GfxControls16 --- engines/sci/engine/kgraphics.cpp | 17 +- engines/sci/graphics/controls.cpp | 388 ------------------------------------ engines/sci/graphics/controls.h | 88 -------- engines/sci/graphics/controls16.cpp | 388 ++++++++++++++++++++++++++++++++++++ engines/sci/graphics/controls16.h | 88 ++++++++ engines/sci/module.mk | 2 +- engines/sci/sci.cpp | 8 +- engines/sci/sci.h | 4 +- 8 files changed, 493 insertions(+), 490 deletions(-) delete mode 100644 engines/sci/graphics/controls.cpp delete mode 100644 engines/sci/graphics/controls.h create mode 100644 engines/sci/graphics/controls16.cpp create mode 100644 engines/sci/graphics/controls16.h (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index ea2b4816fc..566f2a9a7d 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -39,7 +39,7 @@ #include "sci/graphics/animate.h" #include "sci/graphics/cache.h" #include "sci/graphics/compare.h" -#include "sci/graphics/controls.h" +#include "sci/graphics/controls16.h" #include "sci/graphics/cursor.h" #include "sci/graphics/palette.h" #include "sci/graphics/paint16.h" @@ -810,13 +810,13 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { switch (type) { case SCI_CONTROLS_TYPE_BUTTON: debugC(kDebugLevelGraphics, "drawing button %04x:%04x to %d,%d", PRINT_REG(controlObject), x, y); - g_sci->_gfxControls->kernelDrawButton(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, style, hilite); + g_sci->_gfxControls16->kernelDrawButton(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, style, hilite); return; case SCI_CONTROLS_TYPE_TEXT: alignment = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode)); debugC(kDebugLevelGraphics, "drawing text %04x:%04x ('%s') to %d,%d, mode=%d", PRINT_REG(controlObject), text.c_str(), x, y, alignment); - g_sci->_gfxControls->kernelDrawText(rect, controlObject, g_sci->strSplit(text.c_str()).c_str(), fontId, alignment, style, hilite); + g_sci->_gfxControls16->kernelDrawText(rect, controlObject, g_sci->strSplit(text.c_str()).c_str(), fontId, alignment, style, hilite); s->r_acc = g_sci->_gfxText16->allocAndFillReferenceRectArray(); return; @@ -830,7 +830,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { writeSelectorValue(s->_segMan, controlObject, SELECTOR(cursor), cursorPos); } debugC(kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d", PRINT_REG(controlObject), PRINT_REG(textReference), text.c_str(), x, y); - g_sci->_gfxControls->kernelDrawTextEdit(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, mode, style, cursorPos, maxChars, hilite); + g_sci->_gfxControls16->kernelDrawTextEdit(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, mode, style, cursorPos, maxChars, hilite); return; case SCI_CONTROLS_TYPE_ICON: @@ -847,7 +847,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { priority = -1; } debugC(kDebugLevelGraphics, "drawing icon control %04x:%04x to %d,%d", PRINT_REG(controlObject), x, y - 1); - g_sci->_gfxControls->kernelDrawIcon(rect, controlObject, viewId, loopNo, celNo, priority, style, hilite); + g_sci->_gfxControls16->kernelDrawIcon(rect, controlObject, viewId, loopNo, celNo, priority, style, hilite); return; case SCI_CONTROLS_TYPE_LIST: @@ -895,7 +895,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { } debugC(kDebugLevelGraphics, "drawing list control %04x:%04x to %d,%d, diff %d", PRINT_REG(controlObject), x, y, SCI_MAX_SAVENAME_LENGTH); - g_sci->_gfxControls->kernelDrawList(rect, controlObject, maxChars, listCount, listEntries, fontId, style, upperPos, cursorPos, isAlias, hilite); + g_sci->_gfxControls16->kernelDrawList(rect, controlObject, maxChars, listCount, listEntries, fontId, style, upperPos, cursorPos, isAlias, hilite); free(listEntries); delete[] listStrings; return; @@ -975,7 +975,10 @@ reg_t kEditControl(EngineState *s, int argc, reg_t *argv) { switch (controlType) { case SCI_CONTROLS_TYPE_TEXTEDIT: // Only process textedit controls in here - g_sci->_gfxControls->kernelTexteditChange(controlObject, eventObject); + g_sci->_gfxControls16->kernelTexteditChange(controlObject, eventObject); + break; + default: + break; } } return s->r_acc; diff --git a/engines/sci/graphics/controls.cpp b/engines/sci/graphics/controls.cpp deleted file mode 100644 index a0750c7d3e..0000000000 --- a/engines/sci/graphics/controls.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* 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 "common/util.h" -#include "common/stack.h" -#include "common/system.h" -#include "graphics/primitives.h" - -#include "sci/sci.h" -#include "sci/event.h" -#include "sci/engine/kernel.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/compare.h" -#include "sci/graphics/ports.h" -#include "sci/graphics/paint16.h" -#include "sci/graphics/font.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/text16.h" -#include "sci/graphics/controls.h" - -namespace Sci { - -GfxControls::GfxControls(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen) - : _segMan(segMan), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen) { - init(); -} - -GfxControls::~GfxControls() { -} - -void GfxControls::init() { - _texteditCursorVisible = false; -} - -const char controlListUpArrow[2] = { 0x18, 0 }; -const char controlListDownArrow[2] = { 0x19, 0 }; - -void GfxControls::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { - Common::Rect workerRect = rect; - GuiResourceId oldFontId = _text16->GetFontId(); - int16 oldPenColor = _ports->_curPort->penClr; - uint16 fontSize = 0; - int16 i; - const char *listEntry; - int16 listEntryLen; - int16 lastYpos; - - // draw basic window - _paint16->eraseRect(workerRect); - workerRect.grow(1); - _paint16->frameRect(workerRect); - - // draw UP/DOWN arrows - // we draw UP arrow one pixel lower than sierra did, because it looks nicer. Also the DOWN arrow has one pixel - // line inbetween as well - // They "fixed" this in SQ4 by having the arrow character start one pixel line later, we don't adjust there - if (g_sci->getGameId() != GID_SQ4) - workerRect.top++; - _text16->Box(controlListUpArrow, false, workerRect, SCI_TEXT16_ALIGNMENT_CENTER, 0); - workerRect.top = workerRect.bottom - 10; - _text16->Box(controlListDownArrow, false, workerRect, SCI_TEXT16_ALIGNMENT_CENTER, 0); - - // Draw inner lines - workerRect.top = rect.top + 9; - workerRect.bottom -= 10; - _paint16->frameRect(workerRect); - workerRect.grow(-1); - - _text16->SetFont(fontId); - fontSize = _ports->_curPort->fontHeight; - _ports->penColor(_ports->_curPort->penClr); _ports->backColor(_ports->_curPort->backClr); - workerRect.bottom = workerRect.top + fontSize; - lastYpos = rect.bottom - fontSize; - - // Write actual text - for (i = upperPos; i < count; i++) { - _paint16->eraseRect(workerRect); - listEntry = entries[i]; - if (listEntry[0]) { - _ports->moveTo(workerRect.left, workerRect.top); - listEntryLen = strlen(listEntry); - _text16->Draw(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor); - if ((!isAlias) && (i == cursorPos)) { - _paint16->invertRect(workerRect); - } - } - workerRect.translate(0, fontSize); - if (workerRect.bottom > lastYpos) - break; - } - - _text16->SetFont(oldFontId); -} - -void GfxControls::texteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos) { - int16 textWidth, i; - if (!_texteditCursorVisible) { - textWidth = 0; - for (i = 0; i < curPos; i++) { - textWidth += _text16->_font->getCharWidth((unsigned char)text[i]); - } - _texteditCursorRect.left = rect.left + textWidth; - _texteditCursorRect.top = rect.top; - _texteditCursorRect.bottom = _texteditCursorRect.top + _text16->_font->getHeight(); - _texteditCursorRect.right = _texteditCursorRect.left + (text[curPos] == 0 ? 1 : _text16->_font->getCharWidth((unsigned char)text[curPos])); - _paint16->invertRect(_texteditCursorRect); - _paint16->bitsShow(_texteditCursorRect); - _texteditCursorVisible = true; - texteditSetBlinkTime(); - } -} - -void GfxControls::texteditCursorErase() { - if (_texteditCursorVisible) { - _paint16->invertRect(_texteditCursorRect); - _paint16->bitsShow(_texteditCursorRect); - _texteditCursorVisible = false; - } - texteditSetBlinkTime(); -} - -void GfxControls::texteditSetBlinkTime() { - _texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60); -} - -void GfxControls::kernelTexteditChange(reg_t controlObject, reg_t eventObject) { - uint16 cursorPos = readSelectorValue(_segMan, controlObject, SELECTOR(cursor)); - uint16 maxChars = readSelectorValue(_segMan, controlObject, SELECTOR(max)); - reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text)); - Common::String text; - uint16 textSize, eventType, eventKey = 0, modifiers = 0; - bool textChanged = false; - bool textAddChar = false; - Common::Rect rect; - - if (textReference.isNull()) - error("kEditControl called on object that doesnt have a text reference"); - text = _segMan->getString(textReference); - - uint16 oldCursorPos = cursorPos; - - if (!eventObject.isNull()) { - textSize = text.size(); - eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type)); - - switch (eventType) { - case SCI_EVENT_MOUSE_PRESS: - // TODO: Implement mouse support for cursor change - break; - case SCI_EVENT_KEYBOARD: - eventKey = readSelectorValue(_segMan, eventObject, SELECTOR(message)); - modifiers = readSelectorValue(_segMan, eventObject, SELECTOR(modifiers)); - switch (eventKey) { - case SCI_KEY_BACKSPACE: - if (cursorPos > 0) { - cursorPos--; text.deleteChar(cursorPos); - textChanged = true; - } - break; - case SCI_KEY_DELETE: - if (cursorPos < textSize) { - text.deleteChar(cursorPos); - textChanged = true; - } - break; - case SCI_KEY_HOME: // HOME - cursorPos = 0; textChanged = true; - break; - case SCI_KEY_END: // END - cursorPos = textSize; textChanged = true; - break; - case SCI_KEY_LEFT: // LEFT - if (cursorPos > 0) { - cursorPos--; textChanged = true; - } - break; - case SCI_KEY_RIGHT: // RIGHT - if (cursorPos + 1 <= textSize) { - cursorPos++; textChanged = true; - } - break; - case 3: // returned in SCI1 late and newer when Control - C is pressed - if (modifiers & SCI_KEYMOD_CTRL) { - // Control-C erases the whole line - cursorPos = 0; text.clear(); - textChanged = true; - } - break; - default: - if ((modifiers & SCI_KEYMOD_CTRL) && eventKey == 99) { - // Control-C in earlier SCI games (SCI0 - SCI1 middle) - // Control-C erases the whole line - cursorPos = 0; text.clear(); - textChanged = true; - } else if (eventKey > 31 && eventKey < 256 && textSize < maxChars) { - // insert pressed character - textAddChar = true; - textChanged = true; - } - break; - } - break; - } - } - - if (g_sci->getVocabulary() && !textChanged && oldCursorPos != cursorPos) { - assert(!textAddChar); - textChanged = g_sci->getVocabulary()->checkAltInput(text, cursorPos); - } - - if (textChanged) { - GuiResourceId oldFontId = _text16->GetFontId(); - GuiResourceId fontId = readSelectorValue(_segMan, controlObject, SELECTOR(font)); - rect = g_sci->_gfxCompare->getNSRect(controlObject); - - _text16->SetFont(fontId); - if (textAddChar) { - - const char *textPtr = text.c_str(); - - // We check if we are really able to add the new char - uint16 textWidth = 0; - while (*textPtr) - textWidth += _text16->_font->getCharWidth((byte)*textPtr++); - textWidth += _text16->_font->getCharWidth(eventKey); - - // Does it fit? - if (textWidth >= rect.width()) { - _text16->SetFont(oldFontId); - return; - } - - text.insertChar(eventKey, cursorPos++); - - // Note: the following checkAltInput call might make the text - // too wide to fit, but SSCI fails to check that too. - } - if (g_sci->getVocabulary()) - g_sci->getVocabulary()->checkAltInput(text, cursorPos); - texteditCursorErase(); - _paint16->eraseRect(rect); - _text16->Box(text.c_str(), false, rect, SCI_TEXT16_ALIGNMENT_LEFT, -1); - _paint16->bitsShow(rect); - texteditCursorDraw(rect, text.c_str(), cursorPos); - _text16->SetFont(oldFontId); - // Write back string - _segMan->strcpy(textReference, text.c_str()); - } else { - if (g_system->getMillis() >= _texteditBlinkTime) { - _paint16->invertRect(_texteditCursorRect); - _paint16->bitsShow(_texteditCursorRect); - _texteditCursorVisible = !_texteditCursorVisible; - texteditSetBlinkTime(); - } - } - - writeSelectorValue(_segMan, controlObject, SELECTOR(cursor), cursorPos); -} - -int GfxControls::getPicNotValid() { - if (getSciVersion() >= SCI_VERSION_1_1) - return _screen->_picNotValidSci11; - return _screen->_picNotValid; -} - -void GfxControls::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite) { - int16 sci0EarlyPen = 0, sci0EarlyBack = 0; - if (!hilite) { - if (getSciVersion() == SCI_VERSION_0_EARLY) { - // SCI0early actually used hardcoded green/black buttons instead of using the port colors - sci0EarlyPen = _ports->_curPort->penClr; - sci0EarlyBack = _ports->_curPort->backClr; - _ports->penColor(0); - _ports->backColor(2); - } - rect.grow(1); - _paint16->eraseRect(rect); - _paint16->frameRect(rect); - rect.grow(-2); - _ports->textGreyedOutput(style & 1 ? false : true); - _text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId); - _ports->textGreyedOutput(false); - rect.grow(1); - if (style & SCI_CONTROLS_STYLE_SELECTED) - _paint16->frameRect(rect); - if (!getPicNotValid()) { - rect.grow(1); - _paint16->bitsShow(rect); - } - if (getSciVersion() == SCI_VERSION_0_EARLY) { - _ports->penColor(sci0EarlyPen); - _ports->backColor(sci0EarlyBack); - } - } else { - // SCI0early used xor to invert button rectangles resulting in pink/white buttons - if (getSciVersion() == SCI_VERSION_0_EARLY) - _paint16->invertRectViaXOR(rect); - else - _paint16->invertRect(rect); - _paint16->bitsShow(rect); - } -} - -void GfxControls::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, TextAlignment alignment, int16 style, bool hilite) { - if (!hilite) { - rect.grow(1); - _paint16->eraseRect(rect); - rect.grow(-1); - _text16->Box(text, false, rect, alignment, fontId); - if (style & SCI_CONTROLS_STYLE_SELECTED) { - _paint16->frameRect(rect); - } - if (!getPicNotValid()) - _paint16->bitsShow(rect); - } else { - _paint16->invertRect(rect); - _paint16->bitsShow(rect); - } -} - -void GfxControls::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) { - Common::Rect textRect = rect; - uint16 oldFontId = _text16->GetFontId(); - - rect.grow(1); - _texteditCursorVisible = false; - texteditCursorErase(); - _paint16->eraseRect(rect); - _text16->Box(text, false, textRect, SCI_TEXT16_ALIGNMENT_LEFT, fontId); - _paint16->frameRect(rect); - if (style & SCI_CONTROLS_STYLE_SELECTED) { - _text16->SetFont(fontId); - rect.grow(-1); - texteditCursorDraw(rect, text, cursorPos); - _text16->SetFont(oldFontId); - rect.grow(1); - } - if (!getPicNotValid()) - _paint16->bitsShow(rect); -} - -void GfxControls::kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite) { - if (!hilite) { - _paint16->drawCelAndShow(viewId, loopNo, celNo, rect.left, rect.top, priority, 0); - if (style & 0x20) { - _paint16->frameRect(rect); - } - if (!getPicNotValid()) - _paint16->bitsShow(rect); - } else { - _paint16->invertRect(rect); - _paint16->bitsShow(rect); - } -} - -void GfxControls::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) { - if (!hilite) { - drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias); - rect.grow(1); - if (isAlias && (style & SCI_CONTROLS_STYLE_SELECTED)) { - _paint16->frameRect(rect); - } - if (!getPicNotValid()) - _paint16->bitsShow(rect); - } -} - -} // End of namespace Sci diff --git a/engines/sci/graphics/controls.h b/engines/sci/graphics/controls.h deleted file mode 100644 index 17e7c39318..0000000000 --- a/engines/sci/graphics/controls.h +++ /dev/null @@ -1,88 +0,0 @@ -/* 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. - * - */ - -#ifndef SCI_GRAPHICS_CONTROLS_H -#define SCI_GRAPHICS_CONTROLS_H - -namespace Sci { - -enum controlStateFlags { - SCI_CONTROLS_STYLE_ENABLED = 0x0001, ///< 0001 - enabled buttons - SCI_CONTROLS_STYLE_DISABLED = 0x0004, ///< 0010 - grayed out buttons - SCI_CONTROLS_STYLE_SELECTED = 0x0008 ///< 1000 - widgets surrounded by a frame -}; - -// Control types and flags -enum { - SCI_CONTROLS_TYPE_BUTTON = 1, - SCI_CONTROLS_TYPE_TEXT = 2, - SCI_CONTROLS_TYPE_TEXTEDIT = 3, - SCI_CONTROLS_TYPE_ICON = 4, - SCI_CONTROLS_TYPE_LIST = 6, - SCI_CONTROLS_TYPE_LIST_ALIAS = 7, - SCI_CONTROLS_TYPE_DUMMY = 10 -}; - -class GfxPorts; -class GfxPaint16; -class Font; -class GfxText16; -class GfxScreen; -/** - * Controls class, handles drawing of controls in SCI16 (SCI0-SCI1.1) games - */ -class GfxControls { -public: - GfxControls(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen); - ~GfxControls(); - - void kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite); - void kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 alignment, int16 style, bool hilite); - void kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite); - void kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite); - void kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite); - void kernelTexteditChange(reg_t controlObject, reg_t eventObject); - -private: - void init(); - void texteditSetBlinkTime(); - - void drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias); - void texteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos); - void texteditCursorErase(); - int getPicNotValid(); - - SegManager *_segMan; - GfxPorts *_ports; - GfxPaint16 *_paint16; - GfxText16 *_text16; - GfxScreen *_screen; - - // Textedit-Control related - Common::Rect _texteditCursorRect; - bool _texteditCursorVisible; - uint32 _texteditBlinkTime; -}; - -} // End of namespace Sci - -#endif diff --git a/engines/sci/graphics/controls16.cpp b/engines/sci/graphics/controls16.cpp new file mode 100644 index 0000000000..ab54e468d1 --- /dev/null +++ b/engines/sci/graphics/controls16.cpp @@ -0,0 +1,388 @@ +/* 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 "common/util.h" +#include "common/stack.h" +#include "common/system.h" +#include "graphics/primitives.h" + +#include "sci/sci.h" +#include "sci/event.h" +#include "sci/engine/kernel.h" +#include "sci/engine/state.h" +#include "sci/engine/selector.h" +#include "sci/graphics/compare.h" +#include "sci/graphics/ports.h" +#include "sci/graphics/paint16.h" +#include "sci/graphics/font.h" +#include "sci/graphics/screen.h" +#include "sci/graphics/text16.h" +#include "sci/graphics/controls16.h" + +namespace Sci { + +GfxControls16::GfxControls16(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen) + : _segMan(segMan), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen) { + init(); +} + +GfxControls16::~GfxControls16() { +} + +void GfxControls16::init() { + _texteditCursorVisible = false; +} + +const char controlListUpArrow[2] = { 0x18, 0 }; +const char controlListDownArrow[2] = { 0x19, 0 }; + +void GfxControls16::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { + Common::Rect workerRect = rect; + GuiResourceId oldFontId = _text16->GetFontId(); + int16 oldPenColor = _ports->_curPort->penClr; + uint16 fontSize = 0; + int16 i; + const char *listEntry; + int16 listEntryLen; + int16 lastYpos; + + // draw basic window + _paint16->eraseRect(workerRect); + workerRect.grow(1); + _paint16->frameRect(workerRect); + + // draw UP/DOWN arrows + // we draw UP arrow one pixel lower than sierra did, because it looks nicer. Also the DOWN arrow has one pixel + // line inbetween as well + // They "fixed" this in SQ4 by having the arrow character start one pixel line later, we don't adjust there + if (g_sci->getGameId() != GID_SQ4) + workerRect.top++; + _text16->Box(controlListUpArrow, false, workerRect, SCI_TEXT16_ALIGNMENT_CENTER, 0); + workerRect.top = workerRect.bottom - 10; + _text16->Box(controlListDownArrow, false, workerRect, SCI_TEXT16_ALIGNMENT_CENTER, 0); + + // Draw inner lines + workerRect.top = rect.top + 9; + workerRect.bottom -= 10; + _paint16->frameRect(workerRect); + workerRect.grow(-1); + + _text16->SetFont(fontId); + fontSize = _ports->_curPort->fontHeight; + _ports->penColor(_ports->_curPort->penClr); _ports->backColor(_ports->_curPort->backClr); + workerRect.bottom = workerRect.top + fontSize; + lastYpos = rect.bottom - fontSize; + + // Write actual text + for (i = upperPos; i < count; i++) { + _paint16->eraseRect(workerRect); + listEntry = entries[i]; + if (listEntry[0]) { + _ports->moveTo(workerRect.left, workerRect.top); + listEntryLen = strlen(listEntry); + _text16->Draw(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor); + if ((!isAlias) && (i == cursorPos)) { + _paint16->invertRect(workerRect); + } + } + workerRect.translate(0, fontSize); + if (workerRect.bottom > lastYpos) + break; + } + + _text16->SetFont(oldFontId); +} + +void GfxControls16::texteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos) { + int16 textWidth, i; + if (!_texteditCursorVisible) { + textWidth = 0; + for (i = 0; i < curPos; i++) { + textWidth += _text16->_font->getCharWidth((unsigned char)text[i]); + } + _texteditCursorRect.left = rect.left + textWidth; + _texteditCursorRect.top = rect.top; + _texteditCursorRect.bottom = _texteditCursorRect.top + _text16->_font->getHeight(); + _texteditCursorRect.right = _texteditCursorRect.left + (text[curPos] == 0 ? 1 : _text16->_font->getCharWidth((unsigned char)text[curPos])); + _paint16->invertRect(_texteditCursorRect); + _paint16->bitsShow(_texteditCursorRect); + _texteditCursorVisible = true; + texteditSetBlinkTime(); + } +} + +void GfxControls16::texteditCursorErase() { + if (_texteditCursorVisible) { + _paint16->invertRect(_texteditCursorRect); + _paint16->bitsShow(_texteditCursorRect); + _texteditCursorVisible = false; + } + texteditSetBlinkTime(); +} + +void GfxControls16::texteditSetBlinkTime() { + _texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60); +} + +void GfxControls16::kernelTexteditChange(reg_t controlObject, reg_t eventObject) { + uint16 cursorPos = readSelectorValue(_segMan, controlObject, SELECTOR(cursor)); + uint16 maxChars = readSelectorValue(_segMan, controlObject, SELECTOR(max)); + reg_t textReference = readSelector(_segMan, controlObject, SELECTOR(text)); + Common::String text; + uint16 textSize, eventType, eventKey = 0, modifiers = 0; + bool textChanged = false; + bool textAddChar = false; + Common::Rect rect; + + if (textReference.isNull()) + error("kEditControl called on object that doesnt have a text reference"); + text = _segMan->getString(textReference); + + uint16 oldCursorPos = cursorPos; + + if (!eventObject.isNull()) { + textSize = text.size(); + eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type)); + + switch (eventType) { + case SCI_EVENT_MOUSE_PRESS: + // TODO: Implement mouse support for cursor change + break; + case SCI_EVENT_KEYBOARD: + eventKey = readSelectorValue(_segMan, eventObject, SELECTOR(message)); + modifiers = readSelectorValue(_segMan, eventObject, SELECTOR(modifiers)); + switch (eventKey) { + case SCI_KEY_BACKSPACE: + if (cursorPos > 0) { + cursorPos--; text.deleteChar(cursorPos); + textChanged = true; + } + break; + case SCI_KEY_DELETE: + if (cursorPos < textSize) { + text.deleteChar(cursorPos); + textChanged = true; + } + break; + case SCI_KEY_HOME: // HOME + cursorPos = 0; textChanged = true; + break; + case SCI_KEY_END: // END + cursorPos = textSize; textChanged = true; + break; + case SCI_KEY_LEFT: // LEFT + if (cursorPos > 0) { + cursorPos--; textChanged = true; + } + break; + case SCI_KEY_RIGHT: // RIGHT + if (cursorPos + 1 <= textSize) { + cursorPos++; textChanged = true; + } + break; + case 3: // returned in SCI1 late and newer when Control - C is pressed + if (modifiers & SCI_KEYMOD_CTRL) { + // Control-C erases the whole line + cursorPos = 0; text.clear(); + textChanged = true; + } + break; + default: + if ((modifiers & SCI_KEYMOD_CTRL) && eventKey == 99) { + // Control-C in earlier SCI games (SCI0 - SCI1 middle) + // Control-C erases the whole line + cursorPos = 0; text.clear(); + textChanged = true; + } else if (eventKey > 31 && eventKey < 256 && textSize < maxChars) { + // insert pressed character + textAddChar = true; + textChanged = true; + } + break; + } + break; + } + } + + if (g_sci->getVocabulary() && !textChanged && oldCursorPos != cursorPos) { + assert(!textAddChar); + textChanged = g_sci->getVocabulary()->checkAltInput(text, cursorPos); + } + + if (textChanged) { + GuiResourceId oldFontId = _text16->GetFontId(); + GuiResourceId fontId = readSelectorValue(_segMan, controlObject, SELECTOR(font)); + rect = g_sci->_gfxCompare->getNSRect(controlObject); + + _text16->SetFont(fontId); + if (textAddChar) { + + const char *textPtr = text.c_str(); + + // We check if we are really able to add the new char + uint16 textWidth = 0; + while (*textPtr) + textWidth += _text16->_font->getCharWidth((byte)*textPtr++); + textWidth += _text16->_font->getCharWidth(eventKey); + + // Does it fit? + if (textWidth >= rect.width()) { + _text16->SetFont(oldFontId); + return; + } + + text.insertChar(eventKey, cursorPos++); + + // Note: the following checkAltInput call might make the text + // too wide to fit, but SSCI fails to check that too. + } + if (g_sci->getVocabulary()) + g_sci->getVocabulary()->checkAltInput(text, cursorPos); + texteditCursorErase(); + _paint16->eraseRect(rect); + _text16->Box(text.c_str(), false, rect, SCI_TEXT16_ALIGNMENT_LEFT, -1); + _paint16->bitsShow(rect); + texteditCursorDraw(rect, text.c_str(), cursorPos); + _text16->SetFont(oldFontId); + // Write back string + _segMan->strcpy(textReference, text.c_str()); + } else { + if (g_system->getMillis() >= _texteditBlinkTime) { + _paint16->invertRect(_texteditCursorRect); + _paint16->bitsShow(_texteditCursorRect); + _texteditCursorVisible = !_texteditCursorVisible; + texteditSetBlinkTime(); + } + } + + writeSelectorValue(_segMan, controlObject, SELECTOR(cursor), cursorPos); +} + +int GfxControls16::getPicNotValid() { + if (getSciVersion() >= SCI_VERSION_1_1) + return _screen->_picNotValidSci11; + return _screen->_picNotValid; +} + +void GfxControls16::kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite) { + int16 sci0EarlyPen = 0, sci0EarlyBack = 0; + if (!hilite) { + if (getSciVersion() == SCI_VERSION_0_EARLY) { + // SCI0early actually used hardcoded green/black buttons instead of using the port colors + sci0EarlyPen = _ports->_curPort->penClr; + sci0EarlyBack = _ports->_curPort->backClr; + _ports->penColor(0); + _ports->backColor(2); + } + rect.grow(1); + _paint16->eraseRect(rect); + _paint16->frameRect(rect); + rect.grow(-2); + _ports->textGreyedOutput(style & 1 ? false : true); + _text16->Box(text, false, rect, SCI_TEXT16_ALIGNMENT_CENTER, fontId); + _ports->textGreyedOutput(false); + rect.grow(1); + if (style & SCI_CONTROLS_STYLE_SELECTED) + _paint16->frameRect(rect); + if (!getPicNotValid()) { + rect.grow(1); + _paint16->bitsShow(rect); + } + if (getSciVersion() == SCI_VERSION_0_EARLY) { + _ports->penColor(sci0EarlyPen); + _ports->backColor(sci0EarlyBack); + } + } else { + // SCI0early used xor to invert button rectangles resulting in pink/white buttons + if (getSciVersion() == SCI_VERSION_0_EARLY) + _paint16->invertRectViaXOR(rect); + else + _paint16->invertRect(rect); + _paint16->bitsShow(rect); + } +} + +void GfxControls16::kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, TextAlignment alignment, int16 style, bool hilite) { + if (!hilite) { + rect.grow(1); + _paint16->eraseRect(rect); + rect.grow(-1); + _text16->Box(text, false, rect, alignment, fontId); + if (style & SCI_CONTROLS_STYLE_SELECTED) { + _paint16->frameRect(rect); + } + if (!getPicNotValid()) + _paint16->bitsShow(rect); + } else { + _paint16->invertRect(rect); + _paint16->bitsShow(rect); + } +} + +void GfxControls16::kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite) { + Common::Rect textRect = rect; + uint16 oldFontId = _text16->GetFontId(); + + rect.grow(1); + _texteditCursorVisible = false; + texteditCursorErase(); + _paint16->eraseRect(rect); + _text16->Box(text, false, textRect, SCI_TEXT16_ALIGNMENT_LEFT, fontId); + _paint16->frameRect(rect); + if (style & SCI_CONTROLS_STYLE_SELECTED) { + _text16->SetFont(fontId); + rect.grow(-1); + texteditCursorDraw(rect, text, cursorPos); + _text16->SetFont(oldFontId); + rect.grow(1); + } + if (!getPicNotValid()) + _paint16->bitsShow(rect); +} + +void GfxControls16::kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite) { + if (!hilite) { + _paint16->drawCelAndShow(viewId, loopNo, celNo, rect.left, rect.top, priority, 0); + if (style & 0x20) { + _paint16->frameRect(rect); + } + if (!getPicNotValid()) + _paint16->bitsShow(rect); + } else { + _paint16->invertRect(rect); + _paint16->bitsShow(rect); + } +} + +void GfxControls16::kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite) { + if (!hilite) { + drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias); + rect.grow(1); + if (isAlias && (style & SCI_CONTROLS_STYLE_SELECTED)) { + _paint16->frameRect(rect); + } + if (!getPicNotValid()) + _paint16->bitsShow(rect); + } +} + +} // End of namespace Sci diff --git a/engines/sci/graphics/controls16.h b/engines/sci/graphics/controls16.h new file mode 100644 index 0000000000..90bd7beacb --- /dev/null +++ b/engines/sci/graphics/controls16.h @@ -0,0 +1,88 @@ +/* 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. + * + */ + +#ifndef SCI_GRAPHICS_CONTROLS16_H +#define SCI_GRAPHICS_CONTROLS16_H + +namespace Sci { + +enum controlStateFlags { + SCI_CONTROLS_STYLE_ENABLED = 0x0001, ///< 0001 - enabled buttons + SCI_CONTROLS_STYLE_DISABLED = 0x0004, ///< 0010 - grayed out buttons + SCI_CONTROLS_STYLE_SELECTED = 0x0008 ///< 1000 - widgets surrounded by a frame +}; + +// Control types and flags +enum { + SCI_CONTROLS_TYPE_BUTTON = 1, + SCI_CONTROLS_TYPE_TEXT = 2, + SCI_CONTROLS_TYPE_TEXTEDIT = 3, + SCI_CONTROLS_TYPE_ICON = 4, + SCI_CONTROLS_TYPE_LIST = 6, + SCI_CONTROLS_TYPE_LIST_ALIAS = 7, + SCI_CONTROLS_TYPE_DUMMY = 10 +}; + +class GfxPorts; +class GfxPaint16; +class Font; +class GfxText16; +class GfxScreen; +/** + * Controls class, handles drawing of controls in SCI16 (SCI0-SCI1.1) games + */ +class GfxControls16 { +public: + GfxControls16(SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen); + ~GfxControls16(); + + void kernelDrawButton(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 style, bool hilite); + void kernelDrawText(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 alignment, int16 style, bool hilite); + void kernelDrawTextEdit(Common::Rect rect, reg_t obj, const char *text, int16 fontId, int16 mode, int16 style, int16 cursorPos, int16 maxChars, bool hilite); + void kernelDrawIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, int16 loopNo, int16 celNo, int16 priority, int16 style, bool hilite); + void kernelDrawList(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 style, int16 upperPos, int16 cursorPos, bool isAlias, bool hilite); + void kernelTexteditChange(reg_t controlObject, reg_t eventObject); + +private: + void init(); + void texteditSetBlinkTime(); + + void drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias); + void texteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos); + void texteditCursorErase(); + int getPicNotValid(); + + SegManager *_segMan; + GfxPorts *_ports; + GfxPaint16 *_paint16; + GfxText16 *_text16; + GfxScreen *_screen; + + // Textedit-Control related + Common::Rect _texteditCursorRect; + bool _texteditCursorVisible; + uint32 _texteditBlinkTime; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/module.mk b/engines/sci/module.mk index c129ae5439..828a36298d 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -43,7 +43,7 @@ MODULE_OBJS := \ graphics/animate.o \ graphics/cache.o \ graphics/compare.o \ - graphics/controls.o \ + graphics/controls16.o \ graphics/coordadjuster.o \ graphics/cursor.o \ graphics/font.o \ diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 1d0d63870d..2dc8c95fec 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -46,7 +46,7 @@ #include "sci/graphics/animate.h" #include "sci/graphics/cache.h" #include "sci/graphics/compare.h" -#include "sci/graphics/controls.h" +#include "sci/graphics/controls16.h" #include "sci/graphics/coordadjuster.h" #include "sci/graphics/cursor.h" #include "sci/graphics/maciconbar.h" @@ -152,7 +152,7 @@ SciEngine::~SciEngine() { delete _gfxFrameout; #endif delete _gfxMenu; - delete _gfxControls; + delete _gfxControls16; delete _gfxText16; delete _gfxAnimate; delete _gfxPaint; @@ -588,7 +588,7 @@ void SciEngine::initGraphics() { _gfxAnimate = 0; _gfxCache = 0; _gfxCompare = 0; - _gfxControls = 0; + _gfxControls16 = 0; _gfxCoordAdjuster = 0; _gfxCursor = 0; _gfxMacIconBar = 0; @@ -636,7 +636,7 @@ void SciEngine::initGraphics() { _gfxPaint = _gfxPaint16; _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions); _gfxText16 = new GfxText16(_resMan, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); - _gfxControls = new GfxControls(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); + _gfxControls16 = new GfxControls16(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); _gfxMenu = new GfxMenu(_eventMan, _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); _gfxMenu->reset(); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 81bbdc51de..e76b71b61e 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -59,7 +59,7 @@ class SegManager; class GfxAnimate; class GfxCache; class GfxCompare; -class GfxControls; +class GfxControls16; class GfxCoordAdjuster; class GfxCursor; class GfxMacIconBar; @@ -303,7 +303,7 @@ public: GfxAnimate *_gfxAnimate; // Animate for 16-bit gfx GfxCache *_gfxCache; GfxCompare *_gfxCompare; - GfxControls *_gfxControls; // Controls for 16-bit gfx + GfxControls16 *_gfxControls16; // Controls for 16-bit gfx GfxCoordAdjuster *_gfxCoordAdjuster; GfxCursor *_gfxCursor; GfxMenu *_gfxMenu; // Menu for 16-bit gfx -- cgit v1.2.3