/* 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. * * $URL$ * $Id$ * */ #include "common/util.h" #include "common/stack.h" #include "graphics/primitives.h" #include "sci/sci.h" #include "sci/event.h" #include "sci/engine/state.h" #include "sci/gui/gui_gfx.h" #include "sci/gui/gui_font.h" #include "sci/gui/gui_text.h" #include "sci/gui/gui_controls.h" namespace Sci { SciGuiControls::SciGuiControls(SegManager *segMan, SciGuiGfx *gfx, SciGuiText *text) : _segMan(segMan), _gfx(gfx), _text(text) { init(); } SciGuiControls::~SciGuiControls() { } void SciGuiControls::init() { _texteditCursorVisible = false; } const char controlListUpArrow[2] = { 0x18, 0 }; const char controlListDownArrow[2] = { 0x19, 0 }; void SciGuiControls::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 = _text->GetFontId(); int16 oldPenColor = _gfx->_curPort->penClr; uint16 fontSize = 0; int16 i; const char *listEntry; int16 listEntryLen; int16 lastYpos; // draw basic window _gfx->EraseRect(workerRect); workerRect.grow(1); _gfx->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 workerRect.top++; _text->Box(controlListUpArrow, 0, workerRect, SCI_TEXT_ALIGNMENT_CENTER, 0); workerRect.top = workerRect.bottom - 10; _text->Box(controlListDownArrow, 0, workerRect, SCI_TEXT_ALIGNMENT_CENTER, 0); // Draw inner lines workerRect.top = rect.top + 9; workerRect.bottom -= 10; _gfx->FrameRect(workerRect); workerRect.grow(-1); _text->SetFont(fontId); fontSize = _gfx->_curPort->fontHeight; _gfx->PenColor(_gfx->_curPort->penClr); _gfx->BackColor(_gfx->_curPort->backClr); workerRect.bottom = workerRect.top + 9; lastYpos = rect.bottom - fontSize; // Write actual text for (i = upperPos; i < count; i++) { _gfx->EraseRect(workerRect); listEntry = entries[i]; if (listEntry[0]) { _gfx->MoveTo(workerRect.left, workerRect.top); listEntryLen = strlen(listEntry); _text->Draw(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor); if ((!isAlias) && (i == cursorPos)) { _gfx->InvertRect(workerRect); } } workerRect.translate(0, fontSize); if (workerRect.bottom > lastYpos) break; } _text->SetFont(oldFontId); } void SciGuiControls::TexteditCursorDraw(Common::Rect rect, const char *text, uint16 curPos) { int16 textWidth, i; if (!_texteditCursorVisible) { textWidth = 0; for (i = 0; i < curPos; i++) { textWidth += _text->_font->getCharWidth(text[i]); } _texteditCursorRect.left = rect.left + textWidth; _texteditCursorRect.top = rect.top; _texteditCursorRect.bottom = _texteditCursorRect.top + _text->_font->getHeight(); _texteditCursorRect.right = _texteditCursorRect.left + (text[curPos] == 0 ? 1 : _text->_font->getCharWidth(text[curPos])); _gfx->InvertRect(_texteditCursorRect); _gfx->BitsShow(_texteditCursorRect); _texteditCursorVisible = true; TexteditSetBlinkTime(); } } void SciGuiControls::TexteditCursorErase() { if (_texteditCursorVisible) { _gfx->InvertRect(_texteditCursorRect); _gfx->BitsShow(_texteditCursorRect); _texteditCursorVisible = false; } TexteditSetBlinkTime(); } void SciGuiControls::TexteditSetBlinkTime() { _texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60); } void SciGuiControls::TexteditChange(reg_t controlObject, reg_t eventObject) { uint16 cursorPos = GET_SEL32V(_segMan, controlObject, cursor); uint16 maxChars = GET_SEL32V(_segMan, controlObject, max); reg_t textReference = GET_SEL32(_segMan, controlObject, text); Common::String text; uint16 textSize, eventType, eventKey; bool textChanged = false; Common::Rect rect; if (textReference.isNull()) error("kEditControl called on object that doesnt have a text reference"); text = _segMan->getString(textReference); if (!eventObject.isNull()) { textSize = text.size(); eventType = GET_SEL32V(_segMan, eventObject, type); switch (eventType) { case SCI_EVENT_MOUSE_PRESS: // TODO: Implement mouse support for cursor change break; case SCI_EVENT_KEYBOARD: eventKey = GET_SEL32V(_segMan, eventObject, message); switch (eventKey) { case SCI_KEY_BACKSPACE: if (cursorPos > 0) { cursorPos--; text.deleteChar(cursorPos); textChanged = true; } break; case SCI_KEY_DELETE: 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; default: if (eventKey > 31 && eventKey < 256 && textSize < maxChars) { // insert pressed character // we check, if there is space left for this character text.insertChar(eventKey, cursorPos++); textChanged = true; } break; } break; } } if (textChanged) { GuiResourceId oldFontId = _text->GetFontId(); GuiResourceId fontId = GET_SEL32V(_segMan, controlObject, font); rect = Common::Rect(GET_SEL32V(_segMan, controlObject, nsLeft), GET_SEL32V(_segMan, controlObject, nsTop), GET_SEL32V(_segMan, controlObject, nsRight), GET_SEL32V(_segMan, controlObject, nsBottom)); TexteditCursorErase(); _gfx->EraseRect(rect); _text->Box(text.c_str(), 0, rect, SCI_TEXT_ALIGNMENT_LEFT, fontId); _gfx->BitsShow(rect); _text->SetFont(fontId); TexteditCursorDraw(rect, text.c_str(), cursorPos); _text->SetFont(oldFontId); // Write back string _segMan->strcpy(textReference, text.c_str()); } else { if (g_system->getMillis() >= _texteditBlinkTime) { _gfx->InvertRect(_texteditCursorRect); _gfx->BitsShow(_texteditCursorRect); _texteditCursorVisible = !_texteditCursorVisible; TexteditSetBlinkTime(); } } PUT_SEL32V(_segMan, controlObject, cursor, cursorPos); } } // End of namespace Sci