SCI/newgui: SciGuiControls created, SciGuiText now active

svn-id: r45457
This commit is contained in:
Martin Kiewitz 2009-10-28 12:58:13 +00:00
parent c781f01321
commit c6f96d6ac3
13 changed files with 742 additions and 623 deletions

View file

@ -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" />

View file

@ -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" />

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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 \