diff options
-rw-r--r-- | dists/msvc8/sci.vcproj | 2 | ||||
-rw-r--r-- | dists/msvc9/sci.vcproj | 2 | ||||
-rw-r--r-- | engines/sci/gui/gui.cpp | 42 | ||||
-rw-r--r-- | engines/sci/gui/gui.h | 11 | ||||
-rw-r--r-- | engines/sci/gui/gui_controls.cpp | 231 | ||||
-rw-r--r-- | engines/sci/gui/gui_controls.h | 60 | ||||
-rw-r--r-- | engines/sci/gui/gui_gfx.cpp | 548 | ||||
-rw-r--r-- | engines/sci/gui/gui_gfx.h | 49 | ||||
-rw-r--r-- | engines/sci/gui/gui_text.cpp | 367 | ||||
-rw-r--r-- | engines/sci/gui/gui_text.h | 30 | ||||
-rw-r--r-- | engines/sci/gui/gui_windowmgr.cpp | 17 | ||||
-rw-r--r-- | engines/sci/gui/gui_windowmgr.h | 5 | ||||
-rw-r--r-- | engines/sci/module.mk | 1 |
13 files changed, 742 insertions, 623 deletions
diff --git a/dists/msvc8/sci.vcproj b/dists/msvc8/sci.vcproj index bc78051367..a514f4239e 100644 --- a/dists/msvc8/sci.vcproj +++ b/dists/msvc8/sci.vcproj @@ -84,6 +84,8 @@ <File RelativePath="..\..\engines\sci\gui\gui.h" /> <File RelativePath="..\..\engines\sci\gui\gui_animate.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_animate.h" /> + <File RelativePath="..\..\engines\sci\gui\gui_controls.cpp" /> + <File RelativePath="..\..\engines\sci\gui\gui_controls.h" /> <File RelativePath="..\..\engines\sci\gui\gui_cursor.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_cursor.h" /> <File RelativePath="..\..\engines\sci\gui\gui_font.cpp" /> diff --git a/dists/msvc9/sci.vcproj b/dists/msvc9/sci.vcproj index 0e8abf8d8f..0c6a29dfab 100644 --- a/dists/msvc9/sci.vcproj +++ b/dists/msvc9/sci.vcproj @@ -85,6 +85,8 @@ <File RelativePath="..\..\engines\sci\gui\gui.h" /> <File RelativePath="..\..\engines\sci\gui\gui_animate.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_animate.h" /> + <File RelativePath="..\..\engines\sci\gui\gui_controls.cpp" /> + <File RelativePath="..\..\engines\sci\gui\gui_controls.h" /> <File RelativePath="..\..\engines\sci\gui\gui_cursor.cpp" /> <File RelativePath="..\..\engines\sci\gui\gui_cursor.h" /> <File RelativePath="..\..\engines\sci\gui\gui_font.cpp" /> diff --git a/engines/sci/gui/gui.cpp b/engines/sci/gui/gui.cpp index 40434de5ff..4c3ed22999 100644 --- a/engines/sci/gui/gui.cpp +++ b/engines/sci/gui/gui.cpp @@ -36,6 +36,8 @@ #include "sci/gui/gui_gfx.h" #include "sci/gui/gui_windowmgr.h" #include "sci/gui/gui_animate.h" +#include "sci/gui/gui_controls.h" +#include "sci/gui/gui_text.h" #include "sci/gui/gui_transitions.h" #include "sci/gui/gui_view.h" @@ -56,7 +58,11 @@ SciGui::SciGui(EngineState *state, SciGuiScreen *screen, SciGuiPalette *palette, _gfx = new SciGuiGfx(_s, _screen, _palette); _transitions = new SciGuiTransitions(this, _screen, _palette, _s->resMan->isVGA()); _animate = new SciGuiAnimate(_s, _gfx, _screen, _palette); - _windowMgr = new SciGuiWindowMgr(_screen, _gfx, _animate); + _text = new SciGuiText(_s->resMan, _gfx, _screen); + _windowMgr = new SciGuiWindowMgr(_screen, _gfx, _animate, _text); + _controls = new SciGuiControls(_s->_segMan, _gfx, _text); + _gfx->init(_text); + _windowMgr->init(); // _gui32 = new SciGui32(_s, _screen, _palette, _cursor); // for debug purposes } @@ -212,7 +218,7 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { argc--; argv++; break; case SCI_DISPLAY_SETFONT: - _gfx->SetFont(argv[0].toUint16()); + _text->SetFont(argv[0].toUint16()); argc--; argv++; break; case SCI_DISPLAY_WIDTH: @@ -240,7 +246,7 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { } // now drawing the text - _gfx->TextSize(rect, text, -1, width); + _text->Size(rect, text, -1, width); rect.moveTo(_gfx->GetPort()->curLeft, _gfx->GetPort()->curTop); _gfx->Move(rect.right <= _screen->_width ? 0 : _screen->_width - rect.right, rect.bottom <= _screen->_height ? 0 : _screen->_width - rect.bottom); rect.moveTo(_gfx->GetPort()->curLeft, _gfx->GetPort()->curTop); @@ -249,7 +255,7 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { _s->r_acc = _gfx->BitsSave(rect, SCI_SCREEN_MASK_VISUAL); if (bgcolor != -1) _gfx->FillRect(rect, SCI_SCREEN_MASK_VISUAL, bgcolor, 0, 0); - _gfx->TextBox(text, 0, rect, alignment, -1); + _text->Box(text, 0, rect, alignment, -1); if (_screen->_picNotValid == 0 && bRedraw) _gfx->BitsShow(rect); // restoring port and cursor pos @@ -263,18 +269,18 @@ void SciGui::display(const char *text, int argc, reg_t *argv) { void SciGui::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { Common::Rect rect(0, 0, *textWidth, *textHeight); - _gfx->TextSize(rect, text, font, maxWidth); + _text->Size(rect, text, font, maxWidth); *textWidth = rect.width(); *textHeight = rect.height(); } // Used SCI1+ for text codes void SciGui::textFonts(int argc, reg_t *argv) { - _gfx->SetTextFonts(argc, argv); + _text->CodeSetFonts(argc, argv); } // Used SCI1+ for text codes void SciGui::textColors(int argc, reg_t *argv) { - _gfx->SetTextColors(argc, argv); + _text->CodeSetColors(argc, argv); } void SciGui::drawStatus(const char *text, int16 colorPen, int16 colorBack) { @@ -283,7 +289,7 @@ void SciGui::drawStatus(const char *text, int16 colorPen, int16 colorBack) { _gfx->FillRect(_gfx->_menuRect, 1, colorBack); _gfx->PenColor(colorPen); _gfx->MoveTo(0, 1); - _gfx->Draw_String(text); + _text->Draw_String(text); _gfx->BitsShow(_gfx->_menuRect); _gfx->SetPort(oldPort); } @@ -323,7 +329,7 @@ void SciGui::drawControlButton(Common::Rect rect, reg_t obj, const char *text, i _gfx->FrameRect(rect); rect.grow(-2); _gfx->TextFace(style & 1 ? 0 : 1); - _gfx->TextBox(text, 0, rect, SCI_TEXT_ALIGNMENT_CENTER, fontId); + _text->Box(text, 0, rect, SCI_TEXT_ALIGNMENT_CENTER, fontId); _gfx->TextFace(0); rect.grow(1); if (style & 8) // selected @@ -343,7 +349,7 @@ void SciGui::drawControlText(Common::Rect rect, reg_t obj, const char *text, int rect.grow(1); _gfx->EraseRect(rect); rect.grow(-1); - _gfx->TextBox(text, 0, rect, alignment, fontId); + _text->Box(text, 0, rect, alignment, fontId); if (style & 8) { // selected _gfx->FrameRect(rect); } @@ -358,18 +364,18 @@ void SciGui::drawControlText(Common::Rect rect, reg_t obj, const char *text, int void SciGui::drawControlTextEdit(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 = _gfx->GetFontId(); + uint16 oldFontId = _text->GetFontId(); rect.grow(1); - _gfx->TexteditCursorErase(); + _controls->TexteditCursorErase(); _gfx->EraseRect(rect); - _gfx->TextBox(text, 0, textRect, SCI_TEXT_ALIGNMENT_LEFT, fontId); + _text->Box(text, 0, textRect, SCI_TEXT_ALIGNMENT_LEFT, fontId); _gfx->FrameRect(rect); if (style & 8) { - _gfx->SetFont(fontId); + _text->SetFont(fontId); rect.grow(-1); - _gfx->TexteditCursorDraw(rect, text, cursorPos); - _gfx->SetFont(oldFontId); + _controls->TexteditCursorDraw(rect, text, cursorPos); + _text->SetFont(oldFontId); rect.grow(1); } if (_screen->_picNotValid == 0) @@ -392,7 +398,7 @@ void SciGui::drawControlIcon(Common::Rect rect, reg_t obj, GuiResourceId viewId, void SciGui::drawControlList(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) { - _gfx->drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias); + _controls->drawListControl(rect, obj, maxChars, count, entries, fontId, upperPos, cursorPos, isAlias); rect.grow(1); if (isAlias && (style & 8)) { _gfx->FrameRect(rect); @@ -408,7 +414,7 @@ void SciGui::editControl(reg_t controlObject, reg_t eventObject) { switch (controlType) { case SCI_CONTROLS_TYPE_TEXTEDIT: // Only process textedit controls in here - _gfx->TexteditChange(controlObject, eventObject); + _controls->TexteditChange(controlObject, eventObject); return; } } diff --git a/engines/sci/gui/gui.h b/engines/sci/gui/gui.h index 08ac12686a..6c5ac46bdf 100644 --- a/engines/sci/gui/gui.h +++ b/engines/sci/gui/gui.h @@ -45,10 +45,11 @@ class SciGuiScreen; class SciGuiPalette; class SciGuiCursor; class SciGuiGfx; -class SciGuiresources; class SciGuiWindowMgr; -class SciGuiTransitions; class SciGuiAnimate; +class SciGuiControls; +class SciGuiText; +class SciGuiTransitions; class SciGui32; // for debug purposes class SciGui { @@ -147,10 +148,12 @@ private: virtual void addToPicSetPicNotValid(); SciGuiGfx *_gfx; - SciGuiresources *_resources; +// SciGuiresources *_resources; SciGuiWindowMgr *_windowMgr; - SciGuiTransitions *_transitions; SciGuiAnimate *_animate; + SciGuiControls *_controls; + SciGuiText *_text; + SciGuiTransitions *_transitions; // SciGui32 *_gui32; // for debug purposes bool _usesOldGfxFunctions; diff --git a/engines/sci/gui/gui_controls.cpp b/engines/sci/gui/gui_controls.cpp new file mode 100644 index 0000000000..906cbc1257 --- /dev/null +++ b/engines/sci/gui/gui_controls.cpp @@ -0,0 +1,231 @@ +/* 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/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) { + //SegManager *segMan = _s->_segMan; + 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_EVT_MOUSE_PRESS: + // TODO: Implement mouse support for cursor change + break; + case SCI_EVT_KEYBOARD: + eventKey = GET_SEL32V(_segMan, eventObject, message); + switch (eventKey) { + case SCI_K_BACKSPACE: + if (cursorPos > 0) { + cursorPos--; text.deleteChar(cursorPos); + textChanged = true; + } + break; + case SCI_K_DELETE: + text.deleteChar(cursorPos); + textChanged = true; + break; + case SCI_K_HOME: // HOME + cursorPos = 0; textChanged = true; + break; + case SCI_K_END: // END + cursorPos = textSize; textChanged = true; + break; + case SCI_K_LEFT: // LEFT + if (cursorPos > 0) { + cursorPos--; textChanged = true; + } + break; + case SCI_K_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 diff --git a/engines/sci/gui/gui_controls.h b/engines/sci/gui/gui_controls.h new file mode 100644 index 0000000000..426cd6b96e --- /dev/null +++ b/engines/sci/gui/gui_controls.h @@ -0,0 +1,60 @@ +/* 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$ + * + */ + +#ifndef SCI_GUI_CONTROLS_H +#define SCI_GUI_CONTROLS_H + +namespace Sci { + +class SciGuiGfx; +class SciGuiFont; +class SciGuiText; +class SciGuiControls { +public: + SciGuiControls(SegManager *segMan, SciGuiGfx *gfx, SciGuiText *text); + ~SciGuiControls(); + + 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(); + void TexteditChange(reg_t controlObject, reg_t eventObject); + +private: + void init(void); + void TexteditSetBlinkTime(); + + SegManager *_segMan; + SciGuiGfx *_gfx; + SciGuiText *_text; + + // Textedit-Control related + Common::Rect _texteditCursorRect; + bool _texteditCursorVisible; + uint32 _texteditBlinkTime; +}; + +} // End of namespace Sci + +#endif diff --git a/engines/sci/gui/gui_gfx.cpp b/engines/sci/gui/gui_gfx.cpp index 3eb69f0553..36df1492b1 100644 --- a/engines/sci/gui/gui_gfx.cpp +++ b/engines/sci/gui/gui_gfx.cpp @@ -36,12 +36,12 @@ #include "sci/gui/gui_view.h" #include "sci/gui/gui_screen.h" #include "sci/gui/gui_palette.h" +#include "sci/gui/gui_text.h" namespace Sci { SciGuiGfx::SciGuiGfx(EngineState *state, SciGuiScreen *screen, SciGuiPalette *palette) : _s(state), _screen(screen), _palette(palette) { - init(); } SciGuiGfx::~SciGuiGfx() { @@ -49,12 +49,8 @@ SciGuiGfx::~SciGuiGfx() { delete _menuPort; } -void SciGuiGfx::init() { - _font = NULL; - _textFonts = NULL; _textFontsCount = 0; - _textColors = NULL; _textColorsCount = 0; - - _texteditCursorVisible = false; +void SciGuiGfx::init(SciGuiText *text) { + _text = text; // _mainPort is not known to windowmanager, that's okay according to sierra sci // its not even used currently in our engine @@ -65,7 +61,7 @@ void SciGuiGfx::init() { // _menuPort has actually hardcoded id 0xFFFF. Its not meant to be known to windowmanager according to sierra sci _menuPort = new GuiPort(0xFFFF); OpenPort(_menuPort); - SetFont(0); + _text->SetFont(0); _menuPort->rect = Common::Rect(0, 0, _screen->_width, _screen->_height); _menuRect = Common::Rect(0, 0, _screen->_width, 9); } @@ -95,32 +91,13 @@ void SciGuiGfx::Move(int16 left, int16 top) { _curPort->curLeft += left; } -GuiResourceId SciGuiGfx::GetFontId() { - return _curPort->fontId; -} - -SciGuiFont *SciGuiGfx::GetFont() { - if ((_font == NULL) || (_font->getResourceId() != _curPort->fontId)) - _font = new SciGuiFont(_s->resMan, _curPort->fontId); - - return _font; -} - -void SciGuiGfx::SetFont(GuiResourceId fontId) { - if ((_font == NULL) || (_font->getResourceId() != fontId)) - _font = new SciGuiFont(_s->resMan, fontId); - - _curPort->fontId = _font->getResourceId(); - _curPort->fontHeight = _font->getHeight(); -} - void SciGuiGfx::OpenPort(GuiPort *port) { port->fontId = 0; port->fontHeight = 8; GuiPort *tmp = _curPort; _curPort = port; - SetFont(port->fontId); + _text->SetFont(port->fontId); _curPort = tmp; port->top = 0; @@ -257,331 +234,6 @@ void SciGuiGfx::OffsetLine(Common::Point &start, Common::Point &end) { end.y += _curPort->top; } -//----------------------------- - -void SciGuiGfx::ClearChar(int16 chr) { - if (_curPort->penMode != 1) - return; - Common::Rect rect; - rect.top = _curPort->curTop; - rect.bottom = rect.top + _curPort->fontHeight; - rect.left = _curPort->curLeft; - rect.right = rect.left + GetFont()->getCharWidth(chr); - EraseRect(rect); -} - -void SciGuiGfx::DrawChar(int16 chr) { - chr = chr & 0xFF; - ClearChar(chr); - StdChar(chr); - _curPort->curLeft += GetFont()->getCharWidth(chr); -} - -void SciGuiGfx::StdChar(int16 chr) { -#if 0 - CResFont*res = getResFont(); - if (res) - res->Draw(chr, _curPort->top + _curPort->curTop, _curPort->left - + _curPort->curLeft, _vSeg, 320, _curPort->penClr, - _curPort->textFace); -#endif -} - -void SciGuiGfx::SetTextFonts(int argc, reg_t *argv) { - int i; - - if (_textFonts) { - delete _textFonts; - } - _textFontsCount = argc; - _textFonts = new GuiResourceId[argc]; - for (i = 0; i < argc; i++) { - _textFonts[i] = (GuiResourceId)argv[i].toUint16(); - } -} - -void SciGuiGfx::SetTextColors(int argc, reg_t *argv) { - int i; - - if (_textColors) { - delete _textColors; - } - _textColorsCount = argc; - _textColors = new uint16[argc]; - for (i = 0; i < argc; i++) { - _textColors[i] = argv[i].toUint16(); - } -} - -// This internal function gets called as soon as a '|' is found in a text -// It will process the encountered code and set new font/set color -// We only support one-digit codes currently, don't know if multi-digit codes are possible -// Returns textcode character count -int16 SciGuiGfx::TextCodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor) { - const char *textCode = text; - int16 textCodeSize = 0; - char curCode; - unsigned char curCodeParm; - - // Find the end of the textcode - while ((++textCodeSize) && (*text != 0) && (*text++ != 0x7C)) { } - - // possible TextCodes: - // c -> sets textColor to current port pen color - // cX -> sets textColor to _textColors[X-1] - curCode = textCode[0]; - curCodeParm = textCode[1]; - if (isdigit(curCodeParm)) { - curCodeParm -= '0'; - } else { - curCodeParm = 0; - } - switch (curCode) { - case 'c': // set text color - if (curCodeParm == 0) { - _curPort->penClr = orgPenColor; - } else { - if (curCodeParm < _textColorsCount) { - _curPort->penClr = _textColors[curCodeParm]; - } - } - break; - case 'f': - if (curCodeParm == 0) { - SetFont(orgFontId); - } else { - if (curCodeParm < _textFontsCount) { - SetFont(_textFonts[curCodeParm]); - } - } - break; - } - return textCodeSize; -} - -// return max # of chars to fit maxwidth with full words -int16 SciGuiGfx::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId) { - char curChar; - int16 maxChars = 0, curCharCount = 0; - uint16 width = 0; - GuiResourceId oldFontId = GetFontId(); - int16 oldPenColor = _curPort->penClr; - - GetFont(); - if (!_font) - return 0; - - while (width <= maxWidth) { - curChar = *text++; - switch (curChar) { - case 0x7C: - if (getSciVersion() >= SCI_VERSION_1_1) { - curCharCount++; - curCharCount += TextCodeProcessing(text, orgFontId, oldPenColor); - continue; - } - break; - - case 0xD: - curCharCount++; - continue; - - case 0xA: - curCharCount++; - case 0: - SetFont(oldFontId); - PenColor(oldPenColor); - return curCharCount; - - case ' ': - maxChars = curCharCount + 1; - break; - } - width += _font->getCharWidth(curChar); - curCharCount++; - } - SetFont(oldFontId); - PenColor(oldPenColor); - return maxChars; -} - -void SciGuiGfx::TextWidth(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) { - unsigned char curChar; - GuiResourceId oldFontId = GetFontId(); - int16 oldPenColor = _curPort->penClr; - - textWidth = 0; textHeight = 0; - - GetFont(); - if (_font) { - text += from; - while (len--) { - curChar = *text++; - switch (curChar) { - case 0x0A: - case 0x0D: - textHeight = MAX<int16> (textHeight, _curPort->fontHeight); - break; - case 0x7C: - if (getSciVersion() >= SCI_VERSION_1_1) { - len -= TextCodeProcessing(text, orgFontId, 0); - break; - } - default: - textHeight = MAX<int16> (textHeight, _curPort->fontHeight); - textWidth += _font->getCharWidth(curChar); - } - } - } - SetFont(oldFontId); - PenColor(oldPenColor); - return; -} - -void SciGuiGfx::StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) { - TextWidth(str, 0, (int16)strlen(str), orgFontId, textWidth, textHeight); -} - -int16 SciGuiGfx::TextSize(Common::Rect &rect, const char *str, GuiResourceId fontId, int16 maxWidth) { - GuiResourceId oldFontId = GetFontId(); - int16 oldPenColor = _curPort->penClr; - int16 charCount; - int16 maxTextWidth = 0, textWidth; - int16 totalHeight = 0, textHeight; - - if (fontId != -1) - SetFont(fontId); - rect.top = rect.left = 0; - - if (maxWidth < 0) { // force output as single line - StringWidth(str, oldFontId, textWidth, textHeight); - rect.bottom = textHeight; - rect.right = textWidth; - } else { - // rect.right=found widest line with RTextWidth and GetLongest - // rect.bottom=num. lines * GetPointSize - rect.right = (maxWidth ? maxWidth : 192); - const char*p = str; - while (*p) { - //if (*p == 0xD || *p == 0xA) { - // p++; - // continue; - //} - charCount = GetLongest(p, rect.right, oldFontId); - if (charCount == 0) - break; - TextWidth(p, 0, charCount, oldFontId, textWidth, textHeight); - maxTextWidth = MAX(textWidth, maxTextWidth); - totalHeight += textHeight; - p += charCount; - } - rect.bottom = totalHeight; - rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth); - } - SetFont(oldFontId); - PenColor(oldPenColor); - return rect.right; -} - -// returns maximum font height used -void SciGuiGfx::DrawText(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor) { - int16 curChar, charWidth; - Common::Rect rect; - - GetFont(); - if (!_font) - return; - - rect.top = _curPort->curTop; - rect.bottom = rect.top + _curPort->fontHeight; - text += from; - while (len--) { - curChar = (*text++); - switch (curChar) { - case 0x0A: - case 0x0D: - case 0: - break; - case 0x7C: - if (getSciVersion() >= SCI_VERSION_1_1) { - len -= TextCodeProcessing(text, orgFontId, orgPenColor); - break; - } - default: - charWidth = _font->getCharWidth(curChar); - // clear char - if (_curPort->penMode == 1) { - rect.left = _curPort->curLeft; - rect.right = rect.left + charWidth; - EraseRect(rect); - } - // CharStd - _font->draw(_screen, curChar, _curPort->top + _curPort->curTop, _curPort->left + _curPort->curLeft, _curPort->penClr, _curPort->textFace); - _curPort->curLeft += charWidth; - } - } -} - -// returns maximum font height used -void SciGuiGfx::ShowText(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor) { - Common::Rect rect; - - rect.top = _curPort->curTop; - rect.bottom = rect.top + GetPointSize(); - rect.left = _curPort->curLeft; - DrawText(text, from, len, orgFontId, orgPenColor); - rect.right = _curPort->curLeft; - BitsShow(rect); -} - -// Draws a text in rect. -void SciGuiGfx::TextBox(const char *text, int16 bshow, const Common::Rect &rect, GuiTextAlignment alignment, GuiResourceId fontId) { - int16 textWidth, textHeight, charCount, offset; - int16 hline = 0; - GuiResourceId orgFontId = GetFontId(); - int16 orgPenColor = _curPort->penClr; - - if (fontId != -1) - SetFont(fontId); - - while (*text) { -// if (*text == 0xD || *text == 0xA) { -// text++; -// continue; -// } - charCount = GetLongest(text, rect.width(), orgFontId); - if (charCount == 0) - break; - TextWidth(text, 0, charCount, orgFontId, textWidth, textHeight); - switch (alignment) { - case SCI_TEXT_ALIGNMENT_RIGHT: - offset = rect.width() - textWidth; - break; - case SCI_TEXT_ALIGNMENT_CENTER: - offset = (rect.width() - textWidth) / 2; - break; - case SCI_TEXT_ALIGNMENT_LEFT: - offset = 0; - break; - - default: // left-aligned - warning("Invalid alignment %d used in TextBox()", alignment); - } - MoveTo(rect.left + offset, rect.top + hline); - - if (bshow) { - ShowText(text, 0, charCount, orgFontId, orgPenColor); - } else { - DrawText(text, 0, charCount, orgFontId, orgPenColor); - } - - hline += textHeight; - text += charCount; - } - SetFont(orgFontId); - PenColor(orgPenColor); -} - void SciGuiGfx::BitsShow(const Common::Rect &rect) { Common::Rect workerRect(rect.left, rect.top, rect.right, rect.bottom); workerRect.clip(_curPort->rect); @@ -644,15 +296,6 @@ void SciGuiGfx::BitsFree(GuiMemoryHandle memoryHandle) { } } -void SciGuiGfx::Draw_String(const char *text) { - GuiResourceId orgFontId = GetFontId(); - int16 orgPenColor = _curPort->penClr; - - DrawText(text, 0, strlen(text), orgFontId, orgPenColor); - SetFont(orgFontId); - PenColor(orgPenColor); -} - void SciGuiGfx::drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId) { SciGuiPicture *picture; @@ -727,187 +370,6 @@ void SciGuiGfx::drawCel(SciGuiView *view, GuiViewLoopNo loopNo, GuiViewCelNo cel view->draw(celRect, clipRect, clipRectTranslated, loopNo, celNo, priority, paletteNo); } -const char controlListUpArrow[2] = { 0x18, 0 }; -const char controlListDownArrow[2] = { 0x19, 0 }; - -void SciGuiGfx::drawListControl(Common::Rect rect, reg_t obj, int16 maxChars, int16 count, const char **entries, GuiResourceId fontId, int16 upperPos, int16 cursorPos, bool isAlias) { - //SegManager *segMan = _s->_segMan; - Common::Rect workerRect = rect; - GuiResourceId oldFontId = GetFontId(); - int16 oldPenColor = _curPort->penClr; - uint16 fontSize = 0; - int16 i; - const char *listEntry; - int16 listEntryLen; - int16 lastYpos; - - // draw basic window - EraseRect(workerRect); - workerRect.grow(1); - 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++; - TextBox(controlListUpArrow, 0, workerRect, SCI_TEXT_ALIGNMENT_CENTER, 0); - workerRect.top = workerRect.bottom - 10; - TextBox(controlListDownArrow, 0, workerRect, SCI_TEXT_ALIGNMENT_CENTER, 0); - - // Draw inner lines - workerRect.top = rect.top + 9; - workerRect.bottom -= 10; - FrameRect(workerRect); - workerRect.grow(-1); - - SetFont(fontId); - fontSize = _curPort->fontHeight; - PenColor(_curPort->penClr); BackColor(_curPort->backClr); - workerRect.bottom = workerRect.top + 9; - lastYpos = rect.bottom - fontSize; - - // Write actual text - for (i = upperPos; i < count; i++) { - EraseRect(workerRect); - listEntry = entries[i]; - if (listEntry[0]) { - MoveTo(workerRect.left, workerRect.top); - listEntryLen = strlen(listEntry); - DrawText(listEntry, 0, MIN(maxChars, listEntryLen), oldFontId, oldPenColor); - if ((!isAlias) && (i == cursorPos)) { - InvertRect(workerRect); - } - } - workerRect.translate(0, fontSize); - if (workerRect.bottom > lastYpos) - break; - } - - SetFont(oldFontId); -} - -void SciGuiGfx::TexteditCursorDraw (Common::Rect rect, const char *text, uint16 curPos) { - int16 textWidth, i; - if (!_texteditCursorVisible) { - textWidth = 0; - for (i = 0; i < curPos; i++) { - textWidth += _font->getCharWidth(text[i]); - } - _texteditCursorRect.left = rect.left + textWidth; - _texteditCursorRect.top = rect.top; - _texteditCursorRect.bottom = _texteditCursorRect.top + _font->getHeight(); - _texteditCursorRect.right = _texteditCursorRect.left + (text[curPos] == 0 ? 1 : _font->getCharWidth(text[curPos])); - InvertRect(_texteditCursorRect); - BitsShow(_texteditCursorRect); - _texteditCursorVisible = true; - TexteditSetBlinkTime(); - } -} - -void SciGuiGfx::TexteditCursorErase() { - if (_texteditCursorVisible) { - InvertRect(_texteditCursorRect); - BitsShow(_texteditCursorRect); - _texteditCursorVisible = false; - } - TexteditSetBlinkTime(); -} - -void SciGuiGfx::TexteditSetBlinkTime() { - _texteditBlinkTime = g_system->getMillis() + (30 * 1000 / 60); -} - -void SciGuiGfx::TexteditChange(reg_t controlObject, reg_t eventObject) { - SegManager *segMan = _s->_segMan; - 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_EVT_MOUSE_PRESS: - // TODO: Implement mouse support for cursor change - break; - case SCI_EVT_KEYBOARD: - eventKey = GET_SEL32V(segMan, eventObject, message); - switch (eventKey) { - case SCI_K_BACKSPACE: - if (cursorPos > 0) { - cursorPos--; text.deleteChar(cursorPos); - textChanged = true; - } - break; - case SCI_K_DELETE: - text.deleteChar(cursorPos); - textChanged = true; - break; - case SCI_K_HOME: // HOME - cursorPos = 0; textChanged = true; - break; - case SCI_K_END: // END - cursorPos = textSize; textChanged = true; - break; - case SCI_K_LEFT: // LEFT - if (cursorPos > 0) { - cursorPos--; textChanged = true; - } - break; - case SCI_K_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 = 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(); - EraseRect(rect); - TextBox(text.c_str(), 0, rect, SCI_TEXT_ALIGNMENT_LEFT, fontId); - BitsShow(rect); - SetFont(fontId); - TexteditCursorDraw(rect, text.c_str(), cursorPos); - SetFont(oldFontId); - // Write back string - segMan->strcpy(textReference, text.c_str()); - } else { - if (g_system->getMillis() >= _texteditBlinkTime) { - InvertRect(_texteditCursorRect); - BitsShow(_texteditCursorRect); - _texteditCursorVisible = !_texteditCursorVisible; - TexteditSetBlinkTime(); - } - } - - PUT_SEL32V(segMan, controlObject, cursor, cursorPos); -} - uint16 SciGuiGfx::onControl(uint16 screenMask, Common::Rect rect) { Common::Rect outRect(rect.left, rect.top, rect.right, rect.bottom); int16 x, y; diff --git a/engines/sci/gui/gui_gfx.h b/engines/sci/gui/gui_gfx.h index 61f7b414bf..257f2a6609 100644 --- a/engines/sci/gui/gui_gfx.h +++ b/engines/sci/gui/gui_gfx.h @@ -44,7 +44,7 @@ public: SciGuiGfx(EngineState *state, SciGuiScreen *screen, SciGuiPalette *palette); ~SciGuiGfx(); - void init(void); + void init(SciGuiText *text); // FIXME: Don't store EngineState void resetEngineState(EngineState *newState) { _s = newState; } @@ -63,9 +63,6 @@ public: void PenMode(int16 mode); void TextFace(int16 textFace); int16 GetPointSize(void); - GuiResourceId GetFontId(); - SciGuiFont *GetFont(); - void SetFont(GuiResourceId fontId); void ClearScreen(byte color = 255); void InvertRect(const Common::Rect &rect); @@ -76,36 +73,16 @@ public: void OffsetRect(Common::Rect &r); void OffsetLine(Common::Point &start, Common::Point &end); - void ClearChar(int16 chr); - void DrawChar(int16 chr); - void StdChar(int16 chr); - - void SetTextFonts(int argc, reg_t *argv); - void SetTextColors(int argc, reg_t *argv); - int16 TextSize(Common::Rect &rect, const char *str, GuiResourceId fontId, int16 maxwidth); - void ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) { - ShowText(str, 0, (int16)strlen(str), orgFontId, orgPenColor); - } - void DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) { - DrawText(str, 0, (int16)strlen(str), orgFontId, orgPenColor); - } - void TextBox(const char *str, int16 bshow, const Common::Rect &rect, GuiTextAlignment alignment, GuiResourceId fontId); void BitsShow(const Common::Rect &r); GuiMemoryHandle BitsSave(const Common::Rect &rect, byte screenFlags); void BitsGetRect(GuiMemoryHandle memoryHandle, Common::Rect *destRect); void BitsRestore(GuiMemoryHandle memoryHandle); void BitsFree(GuiMemoryHandle memoryHandle); - void Draw_String(const char *text); - void drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId); void drawCel(GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo); void drawCel(GuiResourceId viewId, GuiViewLoopNo loopNo, GuiViewCelNo celNo, Common::Rect celRect, byte priority, uint16 paletteNo); void drawCel(SciGuiView *view, GuiViewLoopNo loopNo, GuiViewCelNo celNo, Common::Rect celRect, byte priority, uint16 paletteNo); - 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(); - void TexteditChange(reg_t controlObject, reg_t eventObject); uint16 onControl(uint16 screenMask, Common::Rect rect); @@ -120,40 +97,20 @@ public: GuiPort *_menuPort; Common::Rect _menuRect; + GuiPort *_curPort; private: - int16 TextCodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor); - void TextWidth(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); - void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); - int16 GetLongest(const char *str, int16 maxwidth, GuiResourceId orgFontId); - void DrawText(const char *str, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor); - void ShowText(const char *str, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor); - - void TexteditSetBlinkTime(); - EngineState *_s; SciGuiScreen *_screen; SciGuiPalette *_palette; + SciGuiText *_text; Common::Rect _bounds; GuiPort *_mainPort; - GuiPort *_curPort; - - int _textFontsCount; - GuiResourceId *_textFonts; - int _textColorsCount; - uint16 *_textColors; // Priority Bands related variables int16 _priorityTop, _priorityBottom, _priorityBandCount; byte _priorityBands[200]; - - // Textedit-Control related - Common::Rect _texteditCursorRect; - bool _texteditCursorVisible; - uint32 _texteditBlinkTime; - - SciGuiFont *_font; }; } // End of namespace Sci diff --git a/engines/sci/gui/gui_text.cpp b/engines/sci/gui/gui_text.cpp index 3ba99f0566..91cc02a0f5 100644 --- a/engines/sci/gui/gui_text.cpp +++ b/engines/sci/gui/gui_text.cpp @@ -28,13 +28,15 @@ #include "graphics/primitives.h" #include "sci/sci.h" -#include "sci/gui/gui_screen.h" +#include "sci/engine/state.h" +#include "sci/gui/gui_gfx.h" +#include "sci/gui/gui_font.h" #include "sci/gui/gui_text.h" namespace Sci { -SciGuiText::SciGuiText(SciGuiScreen *screen) - : _screen(screen) { +SciGuiText::SciGuiText(ResourceManager *resMan, SciGuiGfx *gfx, SciGuiScreen *screen) + : _resMan(resMan), _gfx(gfx), _screen(screen) { init(); } @@ -42,8 +44,367 @@ SciGuiText::~SciGuiText() { } void SciGuiText::init() { + _font = NULL; _codeFonts = NULL; _codeFontsCount = 0; _codeColors = NULL; _codeColorsCount = 0; } +GuiResourceId SciGuiText::GetFontId() { + return _gfx->_curPort->fontId; +} + +SciGuiFont *SciGuiText::GetFont() { + if ((_font == NULL) || (_font->getResourceId() != _gfx->_curPort->fontId)) + _font = new SciGuiFont(_resMan, _gfx->_curPort->fontId); + + return _font; +} + +void SciGuiText::SetFont(GuiResourceId fontId) { + if ((_font == NULL) || (_font->getResourceId() != fontId)) + _font = new SciGuiFont(_resMan, fontId); + + _gfx->_curPort->fontId = _font->getResourceId(); + _gfx->_curPort->fontHeight = _font->getHeight(); +} + +void SciGuiText::CodeSetFonts(int argc, reg_t *argv) { + int i; + + if (_codeFonts) { + delete _codeFonts; + } + _codeFontsCount = argc; + _codeFonts = new GuiResourceId[argc]; + for (i = 0; i < argc; i++) { + _codeFonts[i] = (GuiResourceId)argv[i].toUint16(); + } +} + +void SciGuiText::CodeSetColors(int argc, reg_t *argv) { + int i; + + if (_codeColors) { + delete _codeColors; + } + _codeColorsCount = argc; + _codeColors = new uint16[argc]; + for (i = 0; i < argc; i++) { + _codeColors[i] = argv[i].toUint16(); + } +} + +void SciGuiText::ClearChar(int16 chr) { + if (_gfx->_curPort->penMode != 1) + return; + Common::Rect rect; + rect.top = _gfx->_curPort->curTop; + rect.bottom = rect.top + _gfx->_curPort->fontHeight; + rect.left = _gfx->_curPort->curLeft; + rect.right = rect.left + GetFont()->getCharWidth(chr); + _gfx->EraseRect(rect); +} + +void SciGuiText::DrawChar(int16 chr) { + chr = chr & 0xFF; + ClearChar(chr); + StdChar(chr); + _gfx->_curPort->curLeft += GetFont()->getCharWidth(chr); +} + +void SciGuiText::StdChar(int16 chr) { +#if 0 + CResFont*res = getResFont(); + if (res) + res->Draw(chr, _curPort->top + _curPort->curTop, _curPort->left + + _curPort->curLeft, _vSeg, 320, _curPort->penClr, + _curPort->textFace); +#endif +} + +// This internal function gets called as soon as a '|' is found in a text +// It will process the encountered code and set new font/set color +// We only support one-digit codes currently, don't know if multi-digit codes are possible +// Returns textcode character count +int16 SciGuiText::CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor) { + const char *textCode = text; + int16 textCodeSize = 0; + char curCode; + unsigned char curCodeParm; + + // Find the end of the textcode + while ((++textCodeSize) && (*text != 0) && (*text++ != 0x7C)) { } + + // possible TextCodes: + // c -> sets textColor to current port pen color + // cX -> sets textColor to _textColors[X-1] + curCode = textCode[0]; + curCodeParm = textCode[1]; + if (isdigit(curCodeParm)) { + curCodeParm -= '0'; + } else { + curCodeParm = 0; + } + switch (curCode) { + case 'c': // set text color + if (curCodeParm == 0) { + _gfx->_curPort->penClr = orgPenColor; + } else { + if (curCodeParm < _codeColorsCount) { + _gfx->_curPort->penClr = _codeColors[curCodeParm]; + } + } + break; + case 'f': + if (curCodeParm == 0) { + SetFont(orgFontId); + } else { + if (curCodeParm < _codeFontsCount) { + SetFont(_codeFonts[curCodeParm]); + } + } + break; + } + return textCodeSize; +} + +// return max # of chars to fit maxwidth with full words +int16 SciGuiText::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId) { + char curChar; + int16 maxChars = 0, curCharCount = 0; + uint16 width = 0; + GuiResourceId oldFontId = GetFontId(); + int16 oldPenColor = _gfx->_curPort->penClr; + + GetFont(); + if (!_font) + return 0; + + while (width <= maxWidth) { + curChar = *text++; + switch (curChar) { + case 0x7C: + if (getSciVersion() >= SCI_VERSION_1_1) { + curCharCount++; + curCharCount += CodeProcessing(text, orgFontId, oldPenColor); + continue; + } + break; + + case 0xD: + curCharCount++; + continue; + + case 0xA: + curCharCount++; + case 0: + SetFont(oldFontId); + _gfx->PenColor(oldPenColor); + return curCharCount; + + case ' ': + maxChars = curCharCount + 1; + break; + } + width += _font->getCharWidth(curChar); + curCharCount++; + } + SetFont(oldFontId); + _gfx->PenColor(oldPenColor); + return maxChars; +} + +void SciGuiText::Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) { + unsigned char curChar; + GuiResourceId oldFontId = GetFontId(); + int16 oldPenColor = _gfx->_curPort->penClr; + + textWidth = 0; textHeight = 0; + + GetFont(); + if (_font) { + text += from; + while (len--) { + curChar = *text++; + switch (curChar) { + case 0x0A: + case 0x0D: + textHeight = MAX<int16> (textHeight, _gfx->_curPort->fontHeight); + break; + case 0x7C: + if (getSciVersion() >= SCI_VERSION_1_1) { + len -= CodeProcessing(text, orgFontId, 0); + break; + } + default: + textHeight = MAX<int16> (textHeight, _gfx->_curPort->fontHeight); + textWidth += _font->getCharWidth(curChar); + } + } + } + SetFont(oldFontId); + _gfx->PenColor(oldPenColor); + return; +} + +void SciGuiText::StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight) { + Width(str, 0, (int16)strlen(str), orgFontId, textWidth, textHeight); +} + +void SciGuiText::ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) { + Show(str, 0, (int16)strlen(str), orgFontId, orgPenColor); +} +void SciGuiText::DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColor) { + Draw(str, 0, (int16)strlen(str), orgFontId, orgPenColor); +} + +int16 SciGuiText::Size(Common::Rect &rect, const char *str, GuiResourceId fontId, int16 maxWidth) { + GuiResourceId oldFontId = GetFontId(); + int16 oldPenColor = _gfx->_curPort->penClr; + int16 charCount; + int16 maxTextWidth = 0, textWidth; + int16 totalHeight = 0, textHeight; + + if (fontId != -1) + SetFont(fontId); + rect.top = rect.left = 0; + + if (maxWidth < 0) { // force output as single line + StringWidth(str, oldFontId, textWidth, textHeight); + rect.bottom = textHeight; + rect.right = textWidth; + } else { + // rect.right=found widest line with RTextWidth and GetLongest + // rect.bottom=num. lines * GetPointSize + rect.right = (maxWidth ? maxWidth : 192); + const char*p = str; + while (*p) { + //if (*p == 0xD || *p == 0xA) { + // p++; + // continue; + //} + charCount = GetLongest(p, rect.right, oldFontId); + if (charCount == 0) + break; + Width(p, 0, charCount, oldFontId, textWidth, textHeight); + maxTextWidth = MAX(textWidth, maxTextWidth); + totalHeight += textHeight; + p += charCount; + } + rect.bottom = totalHeight; + rect.right = maxWidth ? maxWidth : MIN(rect.right, maxTextWidth); + } + SetFont(oldFontId); + _gfx->PenColor(oldPenColor); + return rect.right; +} + +// returns maximum font height used +void SciGuiText::Draw(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor) { + int16 curChar, charWidth; + Common::Rect rect; + + GetFont(); + if (!_font) + return; + + rect.top = _gfx->_curPort->curTop; + rect.bottom = rect.top + _gfx->_curPort->fontHeight; + text += from; + while (len--) { + curChar = (*text++); + switch (curChar) { + case 0x0A: + case 0x0D: + case 0: + break; + case 0x7C: + if (getSciVersion() >= SCI_VERSION_1_1) { + len -= CodeProcessing(text, orgFontId, orgPenColor); + break; + } + default: + charWidth = _font->getCharWidth(curChar); + // clear char + if (_gfx->_curPort->penMode == 1) { + rect.left = _gfx->_curPort->curLeft; + rect.right = rect.left + charWidth; + _gfx->EraseRect(rect); + } + // CharStd + _font->draw(_screen, curChar, _gfx->_curPort->top + _gfx->_curPort->curTop, _gfx->_curPort->left + _gfx->_curPort->curLeft, _gfx->_curPort->penClr, _gfx->_curPort->textFace); + _gfx->_curPort->curLeft += charWidth; + } + } +} + +// returns maximum font height used +void SciGuiText::Show(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor) { + Common::Rect rect; + + rect.top = _gfx->_curPort->curTop; + rect.bottom = rect.top + _gfx->GetPointSize(); + rect.left = _gfx->_curPort->curLeft; + Draw(text, from, len, orgFontId, orgPenColor); + rect.right = _gfx->_curPort->curLeft; + _gfx->BitsShow(rect); +} + +// Draws a text in rect. +void SciGuiText::Box(const char *text, int16 bshow, const Common::Rect &rect, GuiTextAlignment alignment, GuiResourceId fontId) { + int16 textWidth, textHeight, charCount, offset; + int16 hline = 0; + GuiResourceId orgFontId = GetFontId(); + int16 orgPenColor = _gfx->_curPort->penClr; + + if (fontId != -1) + SetFont(fontId); + + while (*text) { +// if (*text == 0xD || *text == 0xA) { +// text++; +// continue; +// } + charCount = GetLongest(text, rect.width(), orgFontId); + if (charCount == 0) + break; + Width(text, 0, charCount, orgFontId, textWidth, textHeight); + switch (alignment) { + case SCI_TEXT_ALIGNMENT_RIGHT: + offset = rect.width() - textWidth; + break; + case SCI_TEXT_ALIGNMENT_CENTER: + offset = (rect.width() - textWidth) / 2; + break; + case SCI_TEXT_ALIGNMENT_LEFT: + offset = 0; + break; + + default: // left-aligned + warning("Invalid alignment %d used in TextBox()", alignment); + } + _gfx->MoveTo(rect.left + offset, rect.top + hline); + + if (bshow) { + Show(text, 0, charCount, orgFontId, orgPenColor); + } else { + Draw(text, 0, charCount, orgFontId, orgPenColor); + } + + hline += textHeight; + text += charCount; + } + SetFont(orgFontId); + _gfx->PenColor(orgPenColor); +} + +void SciGuiText::Draw_String(const char *text) { + GuiResourceId orgFontId = GetFontId(); + int16 orgPenColor = _gfx->_curPort->penClr; + + Draw(text, 0, strlen(text), orgFontId, orgPenColor); + SetFont(orgFontId); + _gfx->PenColor(orgPenColor); +} + } // End of namespace Sci diff --git a/engines/sci/gui/gui_text.h b/engines/sci/gui/gui_text.h index 856e3d47ce..75bd90e326 100644 --- a/engines/sci/gui/gui_text.h +++ b/engines/sci/gui/gui_text.h @@ -32,16 +32,44 @@ namespace Sci { #define SCI_TEXT_ALIGNMENT_CENTER 1 #define SCI_TEXT_ALIGNMENT_LEFT 0 +class SciGuiGfx; class SciGuiScreen; class SciGuiFont; class SciGuiText { public: - SciGuiText(SciGuiScreen *screen); + SciGuiText(ResourceManager *_resMan, SciGuiGfx *gfx, SciGuiScreen *screen); ~SciGuiText(); + GuiResourceId GetFontId(); + SciGuiFont *GetFont(); + void SetFont(GuiResourceId fontId); + + void CodeSetFonts(int argc, reg_t *argv); + void CodeSetColors(int argc, reg_t *argv); + int16 CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor); + + void ClearChar(int16 chr); + void DrawChar(int16 chr); + void StdChar(int16 chr); + + int16 GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId); + void Width(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); + void StringWidth(const char *str, GuiResourceId orgFontId, int16 &textWidth, int16 &textHeight); + void ShowString(const char *str, GuiResourceId orgFontId, int16 orgPenColor); + void DrawString(const char *str, GuiResourceId orgFontId, int16 orgPenColor); + int16 Size(Common::Rect &rect, const char *str, GuiResourceId fontId, int16 maxWidth); + void Draw(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor); + void Show(const char *text, int16 from, int16 len, GuiResourceId orgFontId, int16 orgPenColor); + void Box(const char *text, int16 bshow, const Common::Rect &rect, GuiTextAlignment alignment, GuiResourceId fontId); + void Draw_String(const char *text); + + SciGuiFont *_font; + private: void init(void); + ResourceManager *_resMan; + SciGuiGfx *_gfx; SciGuiScreen *_screen; int _codeFontsCount; diff --git a/engines/sci/gui/gui_windowmgr.cpp b/engines/sci/gui/gui_windowmgr.cpp index 1d40fa353d..6db959b3cc 100644 --- a/engines/sci/gui/gui_windowmgr.cpp +++ b/engines/sci/gui/gui_windowmgr.cpp @@ -30,6 +30,7 @@ #include "sci/gui/gui_screen.h" #include "sci/gui/gui_gfx.h" #include "sci/gui/gui_animate.h" +#include "sci/gui/gui_text.h" #include "sci/gui/gui_windowmgr.h" namespace Sci { @@ -43,9 +44,15 @@ enum { SCI_WINDOWMGR_STYLE_USER = (1 << 7) }; -SciGuiWindowMgr::SciGuiWindowMgr(SciGuiScreen *screen, SciGuiGfx *gfx, SciGuiAnimate *animate) - : _screen(screen), _gfx(gfx), _animate(animate) { +SciGuiWindowMgr::SciGuiWindowMgr(SciGuiScreen *screen, SciGuiGfx *gfx, SciGuiAnimate *animate, SciGuiText *text) + : _screen(screen), _gfx(gfx), _animate(animate), _text(text) { +} + +SciGuiWindowMgr::~SciGuiWindowMgr() { + // TODO: Clear _windowList and delete all stuff in it? +} +void SciGuiWindowMgr::init() { _wmgrPort = new GuiPort(0); _windowsById.resize(1); _windowsById[0] = _wmgrPort; @@ -66,10 +73,6 @@ SciGuiWindowMgr::SciGuiWindowMgr(SciGuiScreen *screen, SciGuiGfx *gfx, SciGuiAni _picWind = NewWindow(Common::Rect(0, offTop, _screen->_width, _screen->_height), 0, 0, SCI_WINDOWMGR_STYLE_TRANSPARENT | SCI_WINDOWMGR_STYLE_NOFRAME, 0, true); } -SciGuiWindowMgr::~SciGuiWindowMgr() { - // TODO: Clear _windowList and delete all stuff in it? -} - int16 SciGuiWindowMgr::isFrontWindow(GuiWindow *pWnd) { return _windowList.back() == pWnd; } @@ -224,7 +227,7 @@ void SciGuiWindowMgr::DrawWindow(GuiWindow *pWnd) { if (!pWnd->title.empty()) { int16 oldcolor = _gfx->GetPort()->penClr; _gfx->PenColor(255); - _gfx->TextBox(pWnd->title.c_str(), 1, r, SCI_TEXT_ALIGNMENT_CENTER, 0); + _text->Box(pWnd->title.c_str(), 1, r, SCI_TEXT_ALIGNMENT_CENTER, 0); _gfx->PenColor(oldcolor); } diff --git a/engines/sci/gui/gui_windowmgr.h b/engines/sci/gui/gui_windowmgr.h index 8ec95720e2..ae3e4f5bca 100644 --- a/engines/sci/gui/gui_windowmgr.h +++ b/engines/sci/gui/gui_windowmgr.h @@ -33,9 +33,11 @@ namespace Sci { class SciGuiWindowMgr { public: - SciGuiWindowMgr(SciGuiScreen *screen, SciGuiGfx *gfx, SciGuiAnimate *animate); + SciGuiWindowMgr(SciGuiScreen *screen, SciGuiGfx *gfx, SciGuiAnimate *animate, SciGuiText *text); ~SciGuiWindowMgr(); + void init(); + int16 isFrontWindow(GuiWindow *wnd); void BeginUpdate(GuiWindow *wnd); void EndUpdate(GuiWindow *wnd); @@ -55,6 +57,7 @@ private: SciGuiScreen *_screen; SciGuiGfx *_gfx; SciGuiAnimate *_animate; + SciGuiText *_text; /** The list of open 'windows' (and ports), in visual order. */ PortList _windowList; diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 4437cc03ac..2335b4b60f 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -48,6 +48,7 @@ MODULE_OBJS := \ gfx/palette.o \ gui/gui.o \ gui/gui_animate.o \ + gui/gui_controls.o \ gui/gui_cursor.o \ gui/gui_font.o \ gui/gui_gfx.o \ |