aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute/UI
diff options
context:
space:
mode:
authorEinar Johan Trøan Sømåen2012-06-02 02:21:01 +0200
committerEinar Johan Trøan Sømåen2012-06-02 13:09:34 +0200
commit221490a93df13fb6b17589c48c536c73ef6576b5 (patch)
treef477c4c8285928e1c49652bf7a4b0d9ee12ac918 /engines/wintermute/UI
parente6729615ea471891be17d5681b63fe3492f127bd (diff)
downloadscummvm-rg350-221490a93df13fb6b17589c48c536c73ef6576b5.tar.gz
scummvm-rg350-221490a93df13fb6b17589c48c536c73ef6576b5.tar.bz2
scummvm-rg350-221490a93df13fb6b17589c48c536c73ef6576b5.zip
WINTERMUTE: Add subfolders for math, UI, tinyxml and Sys
Diffstat (limited to 'engines/wintermute/UI')
-rw-r--r--engines/wintermute/UI/UIButton.cpp1043
-rw-r--r--engines/wintermute/UI/UIButton.h79
-rw-r--r--engines/wintermute/UI/UIEdit.cpp860
-rw-r--r--engines/wintermute/UI/UIEdit.h72
-rw-r--r--engines/wintermute/UI/UIEntity.cpp339
-rw-r--r--engines/wintermute/UI/UIEntity.h58
-rw-r--r--engines/wintermute/UI/UIObject.cpp589
-rw-r--r--engines/wintermute/UI/UIObject.h83
-rw-r--r--engines/wintermute/UI/UIText.cpp489
-rw-r--r--engines/wintermute/UI/UIText.h59
-rw-r--r--engines/wintermute/UI/UITiledImage.cpp370
-rw-r--r--engines/wintermute/UI/UITiledImage.h62
-rw-r--r--engines/wintermute/UI/UIWindow.cpp1321
-rw-r--r--engines/wintermute/UI/UIWindow.h92
14 files changed, 5516 insertions, 0 deletions
diff --git a/engines/wintermute/UI/UIButton.cpp b/engines/wintermute/UI/UIButton.cpp
new file mode 100644
index 0000000000..75cc3d5689
--- /dev/null
+++ b/engines/wintermute/UI/UIButton.cpp
@@ -0,0 +1,1043 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/Base/BDynBuffer.h"
+#include "engines/wintermute/Base/BGame.h"
+#include "engines/wintermute/UI/UIButton.h"
+#include "engines/wintermute/UI/UITiledImage.h"
+#include "engines/wintermute/Base/BParser.h"
+#include "engines/wintermute/Base/BActiveRect.h"
+#include "engines/wintermute/Base/BFontStorage.h"
+#include "engines/wintermute/Base/BFont.h"
+#include "engines/wintermute/Base/BStringTable.h"
+#include "engines/wintermute/Base/BSprite.h"
+#include "engines/wintermute/Base/BFileManager.h"
+#include "engines/wintermute/PlatformSDL.h"
+#include "engines/wintermute/Base/scriptables/ScValue.h"
+#include "engines/wintermute/Base/scriptables/ScScript.h"
+#include "engines/wintermute/Base/scriptables/ScStack.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIButton, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIButton::CUIButton(CBGame *inGame): CUIObject(inGame) {
+ _backPress = _backHover = _backDisable = _backFocus = NULL;
+
+ _fontHover = _fontPress = _fontDisable = _fontFocus = NULL;
+
+ _imageDisable = _imagePress = _imageHover = _imageFocus = NULL;
+
+ _align = TAL_CENTER;
+
+ _hover = _press = false;
+
+ _type = UI_BUTTON;
+
+ _canFocus = false;
+ _stayPressed = false;
+
+ _oneTimePress = false;
+ _centerImage = false;
+
+ _pixelPerfect = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIButton::~CUIButton() {
+ if (_backPress) delete _backPress;
+ if (_backHover) delete _backHover;
+ if (_backDisable) delete _backDisable;
+ if (_backFocus) delete _backFocus;
+
+ if (!_sharedFonts) {
+ if (_fontHover) Game->_fontStorage->RemoveFont(_fontHover);
+ if (_fontPress) Game->_fontStorage->RemoveFont(_fontPress);
+ if (_fontDisable) Game->_fontStorage->RemoveFont(_fontDisable);
+ if (_fontFocus) Game->_fontStorage->RemoveFont(_fontFocus);
+ }
+
+ if (!_sharedImages) {
+ if (_imageHover) delete _imageHover;
+ if (_imagePress) delete _imagePress;
+ if (_imageDisable) delete _imageDisable;
+ if (_imageFocus) delete _imageFocus;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::LoadFile(const char *Filename) {
+ byte *Buffer = Game->_fileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIButton::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ _filename = new char [strlen(Filename) + 1];
+ strcpy(_filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing BUTTON file '%s'", Filename);
+
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(BUTTON)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(FOCUSABLE)
+TOKEN_DEF(BACK_HOVER)
+TOKEN_DEF(BACK_PRESS)
+TOKEN_DEF(BACK_DISABLE)
+TOKEN_DEF(BACK_FOCUS)
+TOKEN_DEF(BACK)
+TOKEN_DEF(CENTER_IMAGE)
+TOKEN_DEF(IMAGE_HOVER)
+TOKEN_DEF(IMAGE_PRESS)
+TOKEN_DEF(IMAGE_DISABLE)
+TOKEN_DEF(IMAGE_FOCUS)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(FONT_HOVER)
+TOKEN_DEF(FONT_PRESS)
+TOKEN_DEF(FONT_DISABLE)
+TOKEN_DEF(FONT_FOCUS)
+TOKEN_DEF(FONT)
+TOKEN_DEF(TEXT_ALIGN)
+TOKEN_DEF(TEXT)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(WIDTH)
+TOKEN_DEF(HEIGHT)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(NAME)
+TOKEN_DEF(EVENTS)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF(PARENT_NOTIFY)
+TOKEN_DEF(PRESSED)
+TOKEN_DEF(PIXEL_PERFECT)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(BUTTON)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(FOCUSABLE)
+ TOKEN_TABLE(BACK_HOVER)
+ TOKEN_TABLE(BACK_PRESS)
+ TOKEN_TABLE(BACK_DISABLE)
+ TOKEN_TABLE(BACK_FOCUS)
+ TOKEN_TABLE(BACK)
+ TOKEN_TABLE(CENTER_IMAGE)
+ TOKEN_TABLE(IMAGE_HOVER)
+ TOKEN_TABLE(IMAGE_PRESS)
+ TOKEN_TABLE(IMAGE_DISABLE)
+ TOKEN_TABLE(IMAGE_FOCUS)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(FONT_HOVER)
+ TOKEN_TABLE(FONT_PRESS)
+ TOKEN_TABLE(FONT_DISABLE)
+ TOKEN_TABLE(FONT_FOCUS)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TEXT_ALIGN)
+ TOKEN_TABLE(TEXT)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(WIDTH)
+ TOKEN_TABLE(HEIGHT)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(EVENTS)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE(PARENT_NOTIFY)
+ TOKEN_TABLE(PRESSED)
+ TOKEN_TABLE(PIXEL_PERFECT)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_BUTTON) {
+ Game->LOG(0, "'BUTTON' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_CAPTION:
+ SetCaption((char *)params);
+ break;
+
+ case TOKEN_BACK:
+ delete _back;
+ _back = new CUITiledImage(Game);
+ if (!_back || FAILED(_back->LoadFile((char *)params))) {
+ delete _back;
+ _back = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_HOVER:
+ delete _backHover;
+ _backHover = new CUITiledImage(Game);
+ if (!_backHover || FAILED(_backHover->LoadFile((char *)params))) {
+ delete _backHover;
+ _backHover = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_PRESS:
+ delete _backPress;
+ _backPress = new CUITiledImage(Game);
+ if (!_backPress || FAILED(_backPress->LoadFile((char *)params))) {
+ delete _backPress;
+ _backPress = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_DISABLE:
+ delete _backDisable;
+ _backDisable = new CUITiledImage(Game);
+ if (!_backDisable || FAILED(_backDisable->LoadFile((char *)params))) {
+ delete _backDisable;
+ _backDisable = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_FOCUS:
+ delete _backFocus;
+ _backFocus = new CUITiledImage(Game);
+ if (!_backFocus || FAILED(_backFocus->LoadFile((char *)params))) {
+ delete _backFocus;
+ _backFocus = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE:
+ delete _image;
+ _image = new CBSprite(Game);
+ if (!_image || FAILED(_image->LoadFile((char *)params))) {
+ delete _image;
+ _image = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_HOVER:
+ delete _imageHover;
+ _imageHover = new CBSprite(Game);
+ if (!_imageHover || FAILED(_imageHover->LoadFile((char *)params))) {
+ delete _imageHover;
+ _imageHover = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_PRESS:
+ delete _imagePress;
+ _imagePress = new CBSprite(Game);
+ if (!_imagePress || FAILED(_imagePress->LoadFile((char *)params))) {
+ delete _imagePress;
+ _imagePress = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_DISABLE:
+ delete _imageDisable;
+ _imageDisable = new CBSprite(Game);
+ if (!_imageDisable || FAILED(_imageDisable->LoadFile((char *)params))) {
+ delete _imageDisable;
+ _imageDisable = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_FOCUS:
+ delete _imageFocus;
+ _imageFocus = new CBSprite(Game);
+ if (!_imageFocus || FAILED(_imageFocus->LoadFile((char *)params))) {
+ delete _imageFocus;
+ _imageFocus = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_FONT:
+ if (_font) Game->_fontStorage->RemoveFont(_font);
+ _font = Game->_fontStorage->AddFont((char *)params);
+ if (!_font) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_HOVER:
+ if (_fontHover) Game->_fontStorage->RemoveFont(_fontHover);
+ _fontHover = Game->_fontStorage->AddFont((char *)params);
+ if (!_fontHover) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_PRESS:
+ if (_fontPress) Game->_fontStorage->RemoveFont(_fontPress);
+ _fontPress = Game->_fontStorage->AddFont((char *)params);
+ if (!_fontPress) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_DISABLE:
+ if (_fontDisable) Game->_fontStorage->RemoveFont(_fontDisable);
+ _fontDisable = Game->_fontStorage->AddFont((char *)params);
+ if (!_fontDisable) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_FOCUS:
+ if (_fontFocus) Game->_fontStorage->RemoveFont(_fontFocus);
+ _fontFocus = Game->_fontStorage->AddFont((char *)params);
+ if (!_fontFocus) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_TEXT:
+ SetText((char *)params);
+ Game->_stringTable->Expand(&_text);
+ break;
+
+ case TOKEN_TEXT_ALIGN:
+ if (scumm_stricmp((char *)params, "left") == 0) _align = TAL_LEFT;
+ else if (scumm_stricmp((char *)params, "right") == 0) _align = TAL_RIGHT;
+ else _align = TAL_CENTER;
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &_posX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &_posY);
+ break;
+
+ case TOKEN_WIDTH:
+ parser.ScanStr((char *)params, "%d", &_width);
+ break;
+
+ case TOKEN_HEIGHT:
+ parser.ScanStr((char *)params, "%d", &_height);
+ break;
+
+ case TOKEN_CURSOR:
+ delete _cursor;
+ _cursor = new CBSprite(Game);
+ if (!_cursor || FAILED(_cursor->LoadFile((char *)params))) {
+ delete _cursor;
+ _cursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_PARENT_NOTIFY:
+ parser.ScanStr((char *)params, "%b", &_parentNotify);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &_disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &_visible);
+ break;
+
+ case TOKEN_FOCUSABLE:
+ parser.ScanStr((char *)params, "%b", &_canFocus);
+ break;
+
+ case TOKEN_CENTER_IMAGE:
+ parser.ScanStr((char *)params, "%b", &_centerImage);
+ break;
+
+ case TOKEN_PRESSED:
+ parser.ScanStr((char *)params, "%b", &_stayPressed);
+ break;
+
+ case TOKEN_PIXEL_PERFECT:
+ parser.ScanStr((char *)params, "%b", &_pixelPerfect);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in BUTTON definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading BUTTON definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "BUTTON\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", _name);
+ Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption());
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (_back && _back->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK=\"%s\"\n", _back->_filename);
+ if (_backHover && _backHover->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_HOVER=\"%s\"\n", _backHover->_filename);
+ if (_backPress && _backPress->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_PRESS=\"%s\"\n", _backPress->_filename);
+ if (_backDisable && _backDisable->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_DISABLE=\"%s\"\n", _backDisable->_filename);
+ if (_backFocus && _backFocus->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_FOCUS=\"%s\"\n", _backFocus->_filename);
+
+ if (_image && _image->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", _image->_filename);
+ if (_imageHover && _imageHover->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_HOVER=\"%s\"\n", _imageHover->_filename);
+ if (_imagePress && _imagePress->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_PRESS=\"%s\"\n", _imagePress->_filename);
+ if (_imageDisable && _imageDisable->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_DISABLE=\"%s\"\n", _imageDisable->_filename);
+ if (_imageFocus && _imageFocus->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_FOCUS=\"%s\"\n", _imageFocus->_filename);
+
+ if (_font && _font->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT=\"%s\"\n", _font->_filename);
+ if (_fontHover && _fontHover->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->_filename);
+ if (_fontPress && _fontPress->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_PRESS=\"%s\"\n", _fontPress->_filename);
+ if (_fontDisable && _fontDisable->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_DISABLE=\"%s\"\n", _fontDisable->_filename);
+ if (_fontFocus && _fontFocus->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_FOCUS=\"%s\"\n", _fontFocus->_filename);
+
+ if (_cursor && _cursor->_filename)
+ Buffer->PutTextIndent(Indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename);
+
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (_text)
+ Buffer->PutTextIndent(Indent + 2, "TEXT=\"%s\"\n", _text);
+
+ switch (_align) {
+ case TAL_LEFT:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "left");
+ break;
+ case TAL_RIGHT:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "right");
+ break;
+ case TAL_CENTER:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "center");
+ break;
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", _posX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", _posY);
+ Buffer->PutTextIndent(Indent + 2, "WIDTH=%d\n", _width);
+ Buffer->PutTextIndent(Indent + 2, "HEIGHT=%d\n", _height);
+
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "FOCUSABLE=%s\n", _canFocus ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "CENTER_IMAGE=%s\n", _centerImage ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PRESSED=%s\n", _stayPressed ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PIXEL_PERFECT=%s\n", _pixelPerfect ? "TRUE" : "FALSE");
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // scripts
+ for (int i = 0; i < _scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CUIButton::CorrectSize() {
+ RECT rect;
+
+ CBSprite *img = NULL;
+ if (_image) img = _image;
+ else if (_imageDisable) img = _imageDisable;
+ else if (_imageHover) img = _imageHover;
+ else if (_imagePress) img = _imagePress;
+ else if (_imageFocus) img = _imageFocus;
+
+ if (_width <= 0) {
+ if (img) {
+ img->GetBoundingRect(&rect, 0, 0);
+ _width = rect.right - rect.left;
+ } else _width = 100;
+ }
+
+ if (_height <= 0) {
+ if (img) {
+ img->GetBoundingRect(&rect, 0, 0);
+ _height = rect.bottom - rect.top;
+ }
+ }
+
+ if (_text) {
+ int text_height;
+ if (_font) text_height = _font->GetTextHeight((byte *)_text, _width);
+ else text_height = Game->_systemFont->GetTextHeight((byte *)_text, _width);
+
+ if (text_height > _height) _height = text_height;
+ }
+
+ if (_height <= 0) _height = 100;
+
+ if (_back) _back->CorrectSize(&_width, &_height);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::Display(int OffsetX, int OffsetY) {
+ if (!_visible) return S_OK;
+
+ CUITiledImage *back = NULL;
+ CBSprite *image = NULL;
+ CBFont *font = 0;
+
+ //RECT rect;
+ //CBPlatform::SetRect(&rect, OffsetX + _posX, OffsetY + _posY, OffsetX+_posX+_width, OffsetY+_posY+_height);
+ //_hover = (!_disable && CBPlatform::PtInRect(&rect, Game->_mousePos)!=FALSE);
+ _hover = (!_disable && Game->_activeObject == this && (Game->_interactive || Game->_state == GAME_SEMI_FROZEN));
+
+ if ((_press && _hover && !Game->_mouseLeftDown) ||
+ (_oneTimePress && CBPlatform::GetTime() - _oneTimePressTime >= 100)) Press();
+
+
+ if (_disable) {
+ if (_backDisable) back = _backDisable;
+ if (_imageDisable) image = _imageDisable;
+ if (_text && _fontDisable) font = _fontDisable;
+ } else if (_press || _oneTimePress || _stayPressed) {
+ if (_backPress) back = _backPress;
+ if (_imagePress) image = _imagePress;
+ if (_text && _fontPress) font = _fontPress;
+ } else if (_hover) {
+ if (_backHover) back = _backHover;
+ if (_imageHover) image = _imageHover;
+ if (_text && _fontHover) font = _fontHover;
+ } else if (_canFocus && IsFocused()) {
+ if (_backFocus) back = _backFocus;
+ if (_imageFocus) image = _imageFocus;
+ if (_text && _fontFocus) font = _fontFocus;
+ }
+
+ if (!back && _back) back = _back;
+ if (!image && _image) image = _image;
+ if (_text && !font) {
+ if (_font) font = _font;
+ else font = Game->_systemFont;
+ }
+
+ int ImageX = OffsetX + _posX;
+ int ImageY = OffsetY + _posY;
+
+ if (image && _centerImage) {
+ RECT rc;
+ image->GetBoundingRect(&rc, 0, 0);
+ ImageX += (_width - (rc.right - rc.left)) / 2;
+ ImageY += (_height - (rc.bottom - rc.top)) / 2;
+ }
+
+ if (back) back->Display(OffsetX + _posX, OffsetY + _posY, _width, _height);
+ //if(image) image->Draw(ImageX +((_press||_oneTimePress)&&back?1:0), ImageY +((_press||_oneTimePress)&&back?1:0), NULL);
+ if (image) image->Draw(ImageX + ((_press || _oneTimePress) && back ? 1 : 0), ImageY + ((_press || _oneTimePress) && back ? 1 : 0), _pixelPerfect ? this : NULL);
+
+ if (font && _text) {
+ int text_offset = (_height - font->GetTextHeight((byte *)_text, _width)) / 2;
+ font->DrawText((byte *)_text, OffsetX + _posX + ((_press || _oneTimePress) ? 1 : 0), OffsetY + _posY + text_offset + ((_press || _oneTimePress) ? 1 : 0), _width, _align);
+ }
+
+ if (!_pixelPerfect || !_image) Game->_renderer->_rectList.Add(new CBActiveRect(Game, this, NULL, OffsetX + _posX, OffsetY + _posY, _width, _height, 100, 100, false));
+
+ // reset unused sprites
+ if (_image && _image != image) _image->Reset();
+ if (_imageDisable && _imageDisable != image) _imageDisable->Reset();
+ if (_imageFocus && _imageFocus != image) _imageFocus->Reset();
+ if (_imagePress && _imagePress != image) _imagePress->Reset();
+ if (_imageHover && _imageHover != image) _imageHover->Reset();
+
+ _press = _hover && Game->_mouseLeftDown && Game->_capturedObject == this;
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIButton::Press() {
+ ApplyEvent("Press");
+ if (_listenerObject) _listenerObject->Listen(_listenerParamObject, _listenerParamDWORD);
+ if (_parentNotify && _parent) _parent->ApplyEvent(_name);
+
+ _oneTimePress = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetDisabledFont
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SetDisabledFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (_fontDisable) Game->_fontStorage->RemoveFont(_fontDisable);
+ if (Val->IsNULL()) {
+ _fontDisable = NULL;
+ Stack->PushBool(true);
+ } else {
+ _fontDisable = Game->_fontStorage->AddFont(Val->GetString());
+ Stack->PushBool(_fontDisable != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetHoverFont
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetHoverFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (_fontHover) Game->_fontStorage->RemoveFont(_fontHover);
+ if (Val->IsNULL()) {
+ _fontHover = NULL;
+ Stack->PushBool(true);
+ } else {
+ _fontHover = Game->_fontStorage->AddFont(Val->GetString());
+ Stack->PushBool(_fontHover != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetPressedFont
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetPressedFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (_fontPress) Game->_fontStorage->RemoveFont(_fontPress);
+ if (Val->IsNULL()) {
+ _fontPress = NULL;
+ Stack->PushBool(true);
+ } else {
+ _fontPress = Game->_fontStorage->AddFont(Val->GetString());
+ Stack->PushBool(_fontPress != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetFocusedFont
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetFocusedFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (_fontFocus) Game->_fontStorage->RemoveFont(_fontFocus);
+ if (Val->IsNULL()) {
+ _fontFocus = NULL;
+ Stack->PushBool(true);
+ } else {
+ _fontFocus = Game->_fontStorage->AddFont(Val->GetString());
+ Stack->PushBool(_fontFocus != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetDisabledImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetDisabledImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete _imageDisable;
+ _imageDisable = new CBSprite(Game);
+ const char *Filename = Stack->Pop()->GetString();
+ if (!_imageDisable || FAILED(_imageDisable->LoadFile(Filename))) {
+ delete _imageDisable;
+ _imageDisable = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetDisabledImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetDisabledImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imageDisable || !_imageDisable->_filename) Stack->PushNULL();
+ else Stack->PushString(_imageDisable->_filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetDisabledImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetDisabledImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imageDisable) Stack->PushNULL();
+ else Stack->PushNative(_imageDisable, true);
+
+ return S_OK;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetHoverImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetHoverImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete _imageHover;
+ _imageHover = new CBSprite(Game);
+ const char *Filename = Stack->Pop()->GetString();
+ if (!_imageHover || FAILED(_imageHover->LoadFile(Filename))) {
+ delete _imageHover;
+ _imageHover = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetHoverImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetHoverImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imageHover || !_imageHover->_filename) Stack->PushNULL();
+ else Stack->PushString(_imageHover->_filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetHoverImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetHoverImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imageHover) Stack->PushNULL();
+ else Stack->PushNative(_imageHover, true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetPressedImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetPressedImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete _imagePress;
+ _imagePress = new CBSprite(Game);
+ const char *Filename = Stack->Pop()->GetString();
+ if (!_imagePress || FAILED(_imagePress->LoadFile(Filename))) {
+ delete _imagePress;
+ _imagePress = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetPressedImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetPressedImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imagePress || !_imagePress->_filename) Stack->PushNULL();
+ else Stack->PushString(_imagePress->_filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetPressedImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetPressedImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imagePress) Stack->PushNULL();
+ else Stack->PushNative(_imagePress, true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetFocusedImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetFocusedImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete _imageFocus;
+ _imageFocus = new CBSprite(Game);
+ const char *Filename = Stack->Pop()->GetString();
+ if (!_imageFocus || FAILED(_imageFocus->LoadFile(Filename))) {
+ delete _imageFocus;
+ _imageFocus = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetFocusedImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetFocusedImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imageFocus || !_imageFocus->_filename) Stack->PushNULL();
+ else Stack->PushString(_imageFocus->_filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetFocusedImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetFocusedImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imageFocus) Stack->PushNULL();
+ else Stack->PushNative(_imageFocus, true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Press
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Press") == 0) {
+ Stack->CorrectParams(0);
+
+ if (_visible && !_disable) {
+ _oneTimePress = true;
+ _oneTimePressTime = CBPlatform::GetTime();
+ }
+ Stack->PushNULL();
+
+ return S_OK;
+ }
+
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIButton::ScGetProperty(const char *Name) {
+ _scValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ _scValue->SetString("button");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextAlign
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "TextAlign") == 0) {
+ _scValue->SetInt(_align);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Focusable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Focusable") == 0) {
+ _scValue->SetBool(_canFocus);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Pressed
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Pressed") == 0) {
+ _scValue->SetBool(_stayPressed);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // PixelPerfect
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "PixelPerfect") == 0) {
+ _scValue->SetBool(_pixelPerfect);
+ return _scValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::ScSetProperty(const char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // TextAlign
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "TextAlign") == 0) {
+ int i = Value->GetInt();
+ if (i < 0 || i >= NUM_TEXT_ALIGN) i = 0;
+ _align = (TTextAlign)i;
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Focusable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Focusable") == 0) {
+ _canFocus = Value->GetBool();
+ return S_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Pressed
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Pressed") == 0) {
+ _stayPressed = Value->GetBool();
+ return S_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // PixelPerfect
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "PixelPerfect") == 0) {
+ _pixelPerfect = Value->GetBool();
+ return S_OK;
+ }
+
+ else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *CUIButton::ScToString() {
+ return "[button]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIButton::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER_INT(_align));
+ PersistMgr->Transfer(TMEMBER(_backDisable));
+ PersistMgr->Transfer(TMEMBER(_backFocus));
+ PersistMgr->Transfer(TMEMBER(_backHover));
+ PersistMgr->Transfer(TMEMBER(_backPress));
+ PersistMgr->Transfer(TMEMBER(_centerImage));
+ PersistMgr->Transfer(TMEMBER(_fontDisable));
+ PersistMgr->Transfer(TMEMBER(_fontFocus));
+ PersistMgr->Transfer(TMEMBER(_fontHover));
+ PersistMgr->Transfer(TMEMBER(_fontPress));
+ PersistMgr->Transfer(TMEMBER(_hover));
+ PersistMgr->Transfer(TMEMBER(_image));
+ PersistMgr->Transfer(TMEMBER(_imageDisable));
+ PersistMgr->Transfer(TMEMBER(_imageFocus));
+ PersistMgr->Transfer(TMEMBER(_imageHover));
+ PersistMgr->Transfer(TMEMBER(_imagePress));
+ PersistMgr->Transfer(TMEMBER(_pixelPerfect));
+ PersistMgr->Transfer(TMEMBER(_press));
+ PersistMgr->Transfer(TMEMBER(_stayPressed));
+
+ if (!PersistMgr->_saving) {
+ _oneTimePress = false;
+ _oneTimePressTime = 0;
+ }
+
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UI/UIButton.h b/engines/wintermute/UI/UIButton.h
new file mode 100644
index 0000000000..75133e2c0a
--- /dev/null
+++ b/engines/wintermute/UI/UIButton.h
@@ -0,0 +1,79 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIBUTTON_H
+#define WINTERMUTE_UIBUTTON_H
+
+
+#include "UIObject.h"
+#include "engines/wintermute/dctypes.h" // Added by ClassView
+
+namespace WinterMute {
+
+class CUIButton : public CUIObject {
+public:
+ bool _pixelPerfect;
+ bool _stayPressed;
+ bool _centerImage;
+ bool _oneTimePress;
+ uint32 _oneTimePressTime;
+ DECLARE_PERSISTENT(CUIButton, CUIObject)
+ void Press();
+ virtual HRESULT Display(int OffsetX = 0, int OffsetY = 0);
+ bool _press;
+ bool _hover;
+ void CorrectSize();
+ TTextAlign _align;
+ CBSprite *_imageHover;
+ CBSprite *_imagePress;
+ CBSprite *_imageDisable;
+ CBSprite *_imageFocus;
+ CBFont *_fontDisable;
+ CBFont *_fontPress;
+ CBFont *_fontHover;
+ CBFont *_fontFocus;
+ CUITiledImage *_backPress;
+ CUITiledImage *_backHover;
+ CUITiledImage *_backDisable;
+ CUITiledImage *_backFocus;
+ CUIButton(CBGame *inGame = NULL);
+ virtual ~CUIButton();
+ HRESULT LoadFile(const char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(const char *Name);
+ virtual HRESULT ScSetProperty(const char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name);
+ virtual const char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UI/UIEdit.cpp b/engines/wintermute/UI/UIEdit.cpp
new file mode 100644
index 0000000000..3f2bc71996
--- /dev/null
+++ b/engines/wintermute/UI/UIEdit.cpp
@@ -0,0 +1,860 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/UI/UIEdit.h"
+#include "engines/wintermute/UI/UIObject.h"
+#include "engines/wintermute/UI/UITiledImage.h"
+#include "engines/wintermute/StringUtil.h"
+#include "engines/wintermute/Base/BActiveRect.h"
+#include "engines/wintermute/Base/BFileManager.h"
+#include "engines/wintermute/Base/BFont.h"
+#include "engines/wintermute/Base/BFontStorage.h"
+#include "engines/wintermute/Base/BKeyboardState.h"
+#include "engines/wintermute/Base/BDynBuffer.h"
+#include "engines/wintermute/Base/BParser.h"
+#include "engines/wintermute/Base/BSprite.h"
+#include "engines/wintermute/Base/BStringTable.h"
+#include "engines/wintermute/Base/BGame.h"
+#include "engines/wintermute/PlatformSDL.h"
+#include "engines/wintermute/Base/scriptables/ScValue.h"
+#include "engines/wintermute/Base/scriptables/ScStack.h"
+#include "engines/wintermute/Base/scriptables/ScScript.h"
+#include "engines/wintermute/utils.h"
+#include "common/util.h"
+#include "common/keyboard.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIEdit, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIEdit::CUIEdit(CBGame *inGame): CUIObject(inGame) {
+ _type = UI_EDIT;
+
+ _fontSelected = NULL;
+
+ _selStart = _selEnd = 10000;
+ _scrollOffset = 0;
+
+ _cursorChar = NULL;
+ SetCursorChar("|");
+
+#ifdef __WIN32__
+ _cursorBlinkRate = GetCaretBlinkTime();
+#else
+ _cursorBlinkRate = 600;
+#endif
+ _frameWidth = 0;
+
+ SetText("");
+
+ _lastBlinkTime = 0;
+ _cursorVisible = true;
+
+ _maxLength = -1;
+
+ _canFocus = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIEdit::~CUIEdit() {
+ if (!_sharedFonts) {
+ if (_fontSelected) Game->_fontStorage->RemoveFont(_fontSelected);
+ }
+
+ delete[] _cursorChar;
+ _cursorChar = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::LoadFile(const char *Filename) {
+ byte *Buffer = Game->_fileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIEdit::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ _filename = new char [strlen(Filename) + 1];
+ strcpy(_filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing EDIT file '%s'", Filename);
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(BACK)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(FONT_SELECTED)
+TOKEN_DEF(FONT)
+TOKEN_DEF(TEXT)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(WIDTH)
+TOKEN_DEF(HEIGHT)
+TOKEN_DEF(CURSOR_BLINK_RATE)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(FRAME_WIDTH)
+TOKEN_DEF(NAME)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(PARENT_NOTIFY)
+TOKEN_DEF(MAX_LENGTH)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF(EDIT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(BACK)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(FONT_SELECTED)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TEXT)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(WIDTH)
+ TOKEN_TABLE(HEIGHT)
+ TOKEN_TABLE(CURSOR_BLINK_RATE)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(FRAME_WIDTH)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(PARENT_NOTIFY)
+ TOKEN_TABLE(MAX_LENGTH)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE(EDIT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_EDIT) {
+ Game->LOG(0, "'EDIT' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_BACK:
+ delete _back;
+ _back = new CUITiledImage(Game);
+ if (!_back || FAILED(_back->LoadFile((char *)params))) {
+ delete _back;
+ _back = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE:
+ delete _image;
+ _image = new CBSprite(Game);
+ if (!_image || FAILED(_image->LoadFile((char *)params))) {
+ delete _image;
+ _image = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_FONT:
+ if (_font) Game->_fontStorage->RemoveFont(_font);
+ _font = Game->_fontStorage->AddFont((char *)params);
+ if (!_font) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_SELECTED:
+ if (_fontSelected) Game->_fontStorage->RemoveFont(_fontSelected);
+ _fontSelected = Game->_fontStorage->AddFont((char *)params);
+ if (!_fontSelected) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_TEXT:
+ SetText((char *)params);
+ Game->_stringTable->Expand(&_text);
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &_posX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &_posY);
+ break;
+
+ case TOKEN_WIDTH:
+ parser.ScanStr((char *)params, "%d", &_width);
+ break;
+
+ case TOKEN_HEIGHT:
+ parser.ScanStr((char *)params, "%d", &_height);
+ break;
+
+ case TOKEN_MAX_LENGTH:
+ parser.ScanStr((char *)params, "%d", &_maxLength);
+ break;
+
+ case TOKEN_CAPTION:
+ SetCaption((char *)params);
+ break;
+
+ case TOKEN_CURSOR:
+ delete _cursor;
+ _cursor = new CBSprite(Game);
+ if (!_cursor || FAILED(_cursor->LoadFile((char *)params))) {
+ delete _cursor;
+ _cursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_CURSOR_BLINK_RATE:
+ parser.ScanStr((char *)params, "%d", &_cursorBlinkRate);
+ break;
+
+ case TOKEN_FRAME_WIDTH:
+ parser.ScanStr((char *)params, "%d", &_frameWidth);
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_PARENT_NOTIFY:
+ parser.ScanStr((char *)params, "%b", &_parentNotify);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &_disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &_visible);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in EDIT definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading EDIT definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "EDIT\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", _name);
+ Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption());
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (_back && _back->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK=\"%s\"\n", _back->_filename);
+
+ if (_image && _image->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", _image->_filename);
+
+ if (_font && _font->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT=\"%s\"\n", _font->_filename);
+ if (_fontSelected && _fontSelected->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_SELECTED=\"%s\"\n", _fontSelected->_filename);
+
+ if (_cursor && _cursor->_filename)
+ Buffer->PutTextIndent(Indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (_text)
+ Buffer->PutTextIndent(Indent + 2, "TEXT=\"%s\"\n", _text);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", _posX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", _posY);
+ Buffer->PutTextIndent(Indent + 2, "WIDTH=%d\n", _width);
+ Buffer->PutTextIndent(Indent + 2, "HEIGHT=%d\n", _height);
+ Buffer->PutTextIndent(Indent + 2, "MAX_LENGTH=%d\n", _maxLength);
+ Buffer->PutTextIndent(Indent + 2, "CURSOR_BLINK_RATE=%d\n", _cursorBlinkRate);
+ Buffer->PutTextIndent(Indent + 2, "FRAME_WIDTH=%d\n", _frameWidth);
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE");
+
+ // scripts
+ for (int i = 0; i < _scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetSelectedFont
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SetSelectedFont") == 0) {
+ Stack->CorrectParams(1);
+
+ if (_fontSelected) Game->_fontStorage->RemoveFont(_fontSelected);
+ _fontSelected = Game->_fontStorage->AddFont(Stack->Pop()->GetString());
+ Stack->PushBool(_fontSelected != NULL);
+
+ return S_OK;
+ }
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIEdit::ScGetProperty(const char *Name) {
+ _scValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ _scValue->SetString("editor");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SelStart
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SelStart") == 0) {
+ _scValue->SetInt(_selStart);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SelEnd
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SelEnd") == 0) {
+ _scValue->SetInt(_selEnd);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorBlinkRate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CursorBlinkRate") == 0) {
+ _scValue->SetInt(_cursorBlinkRate);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorChar
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CursorChar") == 0) {
+ _scValue->SetString(_cursorChar);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FrameWidth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "FrameWidth") == 0) {
+ _scValue->SetInt(_frameWidth);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MaxLength
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MaxLength") == 0) {
+ _scValue->SetInt(_maxLength);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Text") == 0) {
+ if (Game->_textEncoding == TEXT_UTF8) {
+ WideString wstr = StringUtil::AnsiToWide(_text);
+ _scValue->SetString(StringUtil::WideToUtf8(wstr).c_str());
+ } else {
+ _scValue->SetString(_text);
+ }
+ return _scValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::ScSetProperty(const char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // SelStart
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SelStart") == 0) {
+ _selStart = Value->GetInt();
+ _selStart = MAX(_selStart, 0);
+ _selStart = MIN((size_t)_selStart, strlen(_text));
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SelEnd
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SelEnd") == 0) {
+ _selEnd = Value->GetInt();
+ _selEnd = MAX(_selEnd, 0);
+ _selEnd = MIN((size_t)_selEnd, strlen(_text));
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorBlinkRate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CursorBlinkRate") == 0) {
+ _cursorBlinkRate = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorChar
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CursorChar") == 0) {
+ SetCursorChar(Value->GetString());
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FrameWidth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "FrameWidth") == 0) {
+ _frameWidth = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MaxLength
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MaxLength") == 0) {
+ _maxLength = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Text") == 0) {
+ if (Game->_textEncoding == TEXT_UTF8) {
+ WideString wstr = StringUtil::Utf8ToWide(Value->GetString());
+ SetText(StringUtil::WideToAnsi(wstr).c_str());
+ } else {
+ SetText(Value->GetString());
+ }
+ return S_OK;
+ }
+
+ else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *CUIEdit::ScToString() {
+ return "[edit]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIEdit::SetCursorChar(const char *Char) {
+ if (!Char) return;
+ delete[] _cursorChar;
+ _cursorChar = new char [strlen(Char) + 1];
+ if (_cursorChar) strcpy(_cursorChar, Char);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::Display(int OffsetX, int OffsetY) {
+ if (!_visible) return S_OK;
+
+
+ // hack!
+ TTextEncoding OrigEncoding = Game->_textEncoding;
+ Game->_textEncoding = TEXT_ANSI;
+
+ if (_back) _back->Display(OffsetX + _posX, OffsetY + _posY, _width, _height);
+ if (_image) _image->Draw(OffsetX + _posX, OffsetY + _posY, NULL);
+
+ // prepare fonts
+ CBFont *font;
+ CBFont *sfont;
+
+ if (_font) font = _font;
+ else font = Game->_systemFont;
+
+ if (_fontSelected) sfont = _fontSelected;
+ else sfont = font;
+
+ bool focused = IsFocused();
+
+ _selStart = MAX(_selStart, 0);
+ _selEnd = MAX(_selEnd, 0);
+
+ _selStart = MIN((size_t)_selStart, strlen(_text));
+ _selEnd = MIN((size_t)_selEnd, strlen(_text));
+
+ //int CursorWidth = font->GetCharWidth(_cursorChar[0]);
+ int CursorWidth = font->GetTextWidth((byte *)_cursorChar);
+
+ int s1, s2;
+ bool CurFirst;
+ // modify scroll offset
+ if (_selStart >= _selEnd) {
+ while (font->GetTextWidth((byte *)_text + _scrollOffset, MAX(0, _selEnd - _scrollOffset)) > _width - CursorWidth - 2 * _frameWidth) {
+ _scrollOffset++;
+ if (_scrollOffset >= strlen(_text)) break;
+ }
+
+ _scrollOffset = MIN(_scrollOffset, _selEnd);
+
+ s1 = _selEnd;
+ s2 = _selStart;
+ CurFirst = true;
+ } else {
+ while (font->GetTextWidth((byte *)_text + _scrollOffset, MAX(0, _selStart - _scrollOffset)) +
+ sfont->GetTextWidth((byte *)(_text + MAX(_scrollOffset, _selStart)), _selEnd - MAX(_scrollOffset, _selStart))
+
+ > _width - CursorWidth - 2 * _frameWidth) {
+ _scrollOffset++;
+ if (_scrollOffset >= strlen(_text)) break;
+ }
+
+ _scrollOffset = MIN(_scrollOffset, _selEnd);
+
+ s1 = _selStart;
+ s2 = _selEnd;
+ CurFirst = false;
+ }
+
+
+ int AlignOffset = 0;
+
+ for (int Count = 0; Count < 2; Count++) {
+ // draw text
+ int xxx, yyy, width, height;
+
+ xxx = _posX + _frameWidth + OffsetX;
+ yyy = _posY + _frameWidth + OffsetY;
+
+ width = _posX + _width + OffsetX - _frameWidth;
+ height = MAX(font->GetLetterHeight(), sfont->GetLetterHeight());
+
+ if (Game->_textRTL) xxx += AlignOffset;
+
+ TTextAlign Align = TAL_LEFT;
+
+
+ // unselected 1
+ if (s1 > _scrollOffset) {
+ if (Count) font->DrawText((byte *)_text + _scrollOffset, xxx, yyy, width - xxx, Align, height, s1 - _scrollOffset);
+ xxx += font->GetTextWidth((byte *)_text + _scrollOffset, s1 - _scrollOffset);
+ AlignOffset += font->GetTextWidth((byte *)_text + _scrollOffset, s1 - _scrollOffset);
+ }
+
+ // cursor
+ if (focused && CurFirst) {
+ if (Count) {
+ if (CBPlatform::GetTime() - _lastBlinkTime >= _cursorBlinkRate) {
+ _lastBlinkTime = CBPlatform::GetTime();
+ _cursorVisible = !_cursorVisible;
+ }
+ if (_cursorVisible)
+ font->DrawText((byte *)_cursorChar, xxx, yyy, width - xxx, Align, height, 1);
+ }
+ xxx += CursorWidth;
+ AlignOffset += CursorWidth;
+ }
+
+ // selected
+ int s3 = MAX(s1, _scrollOffset);
+
+ if (s2 - s3 > 0) {
+ if (Count) sfont->DrawText((byte *)_text + s3, xxx, yyy, width - xxx, Align, height, s2 - s3);
+ xxx += sfont->GetTextWidth((byte *)_text + s3, s2 - s3);
+ AlignOffset += sfont->GetTextWidth((byte *)_text + s3, s2 - s3);
+ }
+
+ // cursor
+ if (focused && !CurFirst) {
+ if (Count) {
+ if (CBPlatform::GetTime() - _lastBlinkTime >= _cursorBlinkRate) {
+ _lastBlinkTime = CBPlatform::GetTime();
+ _cursorVisible = !_cursorVisible;
+ }
+ if (_cursorVisible)
+ font->DrawText((byte *)_cursorChar, xxx, yyy, width - xxx, Align, height, 1);
+ }
+ xxx += CursorWidth;
+ AlignOffset += CursorWidth;
+ }
+
+ // unselected 2
+ if (Count) font->DrawText((byte *)_text + s2, xxx, yyy, width - xxx, Align, height);
+ AlignOffset += font->GetTextWidth((byte *)_text + s2);
+
+ AlignOffset = (_width - 2 * _frameWidth) - AlignOffset;
+ if (AlignOffset < 0) AlignOffset = 0;
+ }
+
+
+ Game->_renderer->_rectList.Add(new CBActiveRect(Game, this, NULL, OffsetX + _posX, OffsetY + _posY, _width, _height, 100, 100, false));
+
+
+ Game->_textEncoding = OrigEncoding;
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CUIEdit::HandleKeypress(Common::Event *event) {
+ bool Handled = false;
+
+ if (event->type == Common::EVENT_KEYDOWN) {
+ switch (event->kbd.keycode) {
+ case Common::KEYCODE_ESCAPE:
+ case Common::KEYCODE_TAB:
+ case Common::KEYCODE_RETURN:
+ return false;
+
+ // ctrl+A
+ case Common::KEYCODE_a:
+ if (CBKeyboardState::IsControlDown()) {
+ _selStart = 0;
+ _selEnd = strlen(_text);
+ Handled = true;
+ }
+ break;
+
+ case Common::KEYCODE_BACKSPACE:
+ if (_selStart == _selEnd) {
+ if (Game->_textRTL) DeleteChars(_selStart, _selStart + 1);
+ else DeleteChars(_selStart - 1, _selStart);
+ } else DeleteChars(_selStart, _selEnd);
+ if (_selEnd >= _selStart) _selEnd -= MAX(1, _selEnd - _selStart);
+ _selStart = _selEnd;
+
+ Handled = true;
+ break;
+
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_UP:
+ _selEnd--;
+ if (!CBKeyboardState::IsShiftDown()) _selStart = _selEnd;
+ Handled = true;
+ break;
+
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_DOWN:
+ _selEnd++;
+ if (!CBKeyboardState::IsShiftDown()) _selStart = _selEnd;
+ Handled = true;
+ break;
+
+ case Common::KEYCODE_HOME:
+ if (Game->_textRTL) {
+ _selEnd = strlen(_text);
+ if (!CBKeyboardState::IsShiftDown()) _selStart = _selEnd;
+ } else {
+ _selEnd = 0;
+ if (!CBKeyboardState::IsShiftDown()) _selStart = _selEnd;
+ }
+ Handled = true;
+ break;
+
+ case Common::KEYCODE_END:
+ if (Game->_textRTL) {
+ _selEnd = 0;
+ if (!CBKeyboardState::IsShiftDown()) _selStart = _selEnd;
+ } else {
+ _selEnd = strlen(_text);
+ if (!CBKeyboardState::IsShiftDown()) _selStart = _selEnd;
+ }
+ Handled = true;
+ break;
+
+ case Common::KEYCODE_DELETE:
+ if (_selStart == _selEnd) {
+ if (Game->_textRTL) {
+ DeleteChars(_selStart - 1, _selStart);
+ _selEnd--;
+ if (_selEnd < 0) _selEnd = 0;
+ } else DeleteChars(_selStart, _selStart + 1);
+ } else DeleteChars(_selStart, _selEnd);
+ if (_selEnd > _selStart) _selEnd -= (_selEnd - _selStart);
+
+ _selStart = _selEnd;
+ Handled = true;
+ break;
+ default:
+ break;
+ }
+ return Handled;
+ }
+#if 0
+ else if (event->type == SDL_TEXTINPUT) {
+ if (_selStart != _selEnd) DeleteChars(_selStart, _selEnd);
+
+ WideString wstr = StringUtil::Utf8ToWide(event->text.text);
+ _selEnd += InsertChars(_selEnd, (byte *)StringUtil::WideToAnsi(wstr).c_str(), 1);
+
+ if (Game->_textRTL) _selEnd = _selStart;
+ else _selStart = _selEnd;
+
+ return true;
+ }
+#endif
+ return false;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+int CUIEdit::DeleteChars(int Start, int End) {
+ if (Start > End) CBUtils::Swap(&Start, &End);
+
+ Start = MAX(Start, (int)0);
+ End = MIN((size_t)End, strlen(_text));
+
+ char *str = new char[strlen(_text) - (End - Start) + 1];
+ if (str) {
+ if (Start > 0) memcpy(str, _text, Start);
+ memcpy(str + MAX(0, Start), _text + End, strlen(_text) - End + 1);
+
+ delete[] _text;
+ _text = str;
+ }
+ if (_parentNotify && _parent) _parent->ApplyEvent(_name);
+
+ return End - Start;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int CUIEdit::InsertChars(int Pos, byte *Chars, int Num) {
+ if (strlen(_text) + Num > _maxLength) {
+ Num -= (strlen(_text) + Num - _maxLength);
+ }
+
+ Pos = MAX(Pos, (int)0);
+ Pos = MIN((size_t)Pos, strlen(_text));
+
+ char *str = new char[strlen(_text) + Num + 1];
+ if (str) {
+ if (Pos > 0) memcpy(str, _text, Pos);
+ memcpy(str + Pos + Num, _text + Pos, strlen(_text) - Pos + 1);
+
+ memcpy(str + Pos, Chars, Num);
+
+ delete[] _text;
+ _text = str;
+ }
+ if (_parentNotify && _parent) _parent->ApplyEvent(_name);
+
+ return Num;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEdit::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(_cursorBlinkRate));
+ PersistMgr->Transfer(TMEMBER(_cursorChar));
+ PersistMgr->Transfer(TMEMBER(_fontSelected));
+ PersistMgr->Transfer(TMEMBER(_frameWidth));
+ PersistMgr->Transfer(TMEMBER(_maxLength));
+ PersistMgr->Transfer(TMEMBER(_scrollOffset));
+ PersistMgr->Transfer(TMEMBER(_selEnd));
+ PersistMgr->Transfer(TMEMBER(_selStart));
+
+ if (!PersistMgr->_saving) {
+ _cursorVisible = false;
+ _lastBlinkTime = 0;
+ }
+
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UI/UIEdit.h b/engines/wintermute/UI/UIEdit.h
new file mode 100644
index 0000000000..3b8698d55d
--- /dev/null
+++ b/engines/wintermute/UI/UIEdit.h
@@ -0,0 +1,72 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIEDIT_H
+#define WINTERMUTE_UIEDIT_H
+
+#include "engines/wintermute/persistent.h"
+#include "UIObject.h"
+#include "common/events.h"
+
+namespace WinterMute {
+class CBFont;
+class CUIEdit : public CUIObject {
+public:
+ DECLARE_PERSISTENT(CUIEdit, CUIObject)
+ int _maxLength;
+ int InsertChars(int Pos, byte *Chars, int Num);
+ int DeleteChars(int Start, int End);
+ bool _cursorVisible;
+ uint32 _lastBlinkTime;
+ virtual HRESULT Display(int OffsetX, int OffsetY);
+ virtual bool HandleKeypress(Common::Event *event);
+ int _scrollOffset;
+ int _frameWidth;
+ uint32 _cursorBlinkRate;
+ void SetCursorChar(const char *Char);
+ char *_cursorChar;
+ int _selEnd;
+ int _selStart;
+ CBFont *_fontSelected;
+ CUIEdit(CBGame *inGame);
+ virtual ~CUIEdit();
+
+ HRESULT LoadFile(const char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(const char *Name);
+ virtual HRESULT ScSetProperty(const char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name);
+ virtual const char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UI/UIEntity.cpp b/engines/wintermute/UI/UIEntity.cpp
new file mode 100644
index 0000000000..97565603f3
--- /dev/null
+++ b/engines/wintermute/UI/UIEntity.cpp
@@ -0,0 +1,339 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/Ad/AdEntity.h"
+#include "engines/wintermute/Base/BGame.h"
+#include "engines/wintermute/Base/BFileManager.h"
+#include "engines/wintermute/UI/UIEntity.h"
+#include "engines/wintermute/Base/BParser.h"
+#include "engines/wintermute/Base/BDynBuffer.h"
+#include "engines/wintermute/Base/scriptables/ScValue.h"
+#include "engines/wintermute/Base/scriptables/ScScript.h"
+#include "engines/wintermute/Base/scriptables/ScStack.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIEntity, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIEntity::CUIEntity(CBGame *inGame): CUIObject(inGame) {
+ _type = UI_CUSTOM;
+ _entity = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIEntity::~CUIEntity() {
+ if (_entity) Game->UnregisterObject(_entity);
+ _entity = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::LoadFile(const char *Filename) {
+ byte *Buffer = Game->_fileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIEntity::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ _filename = new char [strlen(Filename) + 1];
+ strcpy(_filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing ENTITY container file '%s'", Filename);
+
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(ENTITY_CONTAINER)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(NAME)
+TOKEN_DEF(ENTITY)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(ENTITY_CONTAINER)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(ENTITY)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_ENTITY_CONTAINER) {
+ Game->LOG(0, "'ENTITY_CONTAINER' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &_posX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &_posY);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &_disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &_visible);
+ break;
+
+ case TOKEN_ENTITY:
+ if (FAILED(SetEntity((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in ENTITY_CONTAINER definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading ENTITY_CONTAINER definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ if (Game->_editorMode) {
+ _width = 50;
+ _height = 50;
+ }
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "ENTITY_CONTAINER\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", _name);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", _posX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", _posY);
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE");
+
+ if (_entity && _entity->_filename)
+ Buffer->PutTextIndent(Indent + 2, "ENTITY=\"%s\"\n", _entity->_filename);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // scripts
+ for (int i = 0; i < _scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::SetEntity(const char *Filename) {
+ if (_entity) Game->UnregisterObject(_entity);
+ _entity = new CAdEntity(Game);
+ if (!_entity || FAILED(_entity->LoadFile(Filename))) {
+ delete _entity;
+ _entity = NULL;
+ return E_FAIL;
+ } else {
+ _entity->_nonIntMouseEvents = true;
+ _entity->_sceneIndependent = true;
+ _entity->MakeFreezable(false);
+ Game->RegisterObject(_entity);
+ }
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::Display(int OffsetX, int OffsetY) {
+ if (!_visible) return S_OK;
+
+ if (_entity) {
+ _entity->_posX = OffsetX + _posX;
+ _entity->_posY = OffsetY + _posY;
+ if (_entity->_scale < 0) _entity->_zoomable = false;
+ _entity->_shadowable = false;
+
+ _entity->Update();
+
+ bool OrigReg = _entity->_registrable;
+
+ if (_entity->_registrable && _disable) _entity->_registrable = false;
+
+ _entity->Display();
+ _entity->_registrable = OrigReg;
+ }
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // GetEntity
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "GetEntity") == 0) {
+ Stack->CorrectParams(0);
+
+ if (_entity) Stack->PushNative(_entity, true);
+ else Stack->PushNULL();
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetEntity
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetEntity") == 0) {
+ Stack->CorrectParams(1);
+
+ const char *Filename = Stack->Pop()->GetString();
+
+ if (SUCCEEDED(SetEntity(Filename)))
+ Stack->PushBool(true);
+ else
+ Stack->PushBool(false);
+
+ return S_OK;
+ }
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIEntity::ScGetProperty(const char *Name) {
+ _scValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ _scValue->SetString("entity container");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Freezable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Freezable") == 0) {
+ if (_entity) _scValue->SetBool(_entity->_freezable);
+ else _scValue->SetBool(false);
+ return _scValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::ScSetProperty(const char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Freezable
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Freezable") == 0) {
+ if (_entity) _entity->MakeFreezable(Value->GetBool());
+ return S_OK;
+ } else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *CUIEntity::ScToString() {
+ return "[entity container]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIEntity::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(_entity));
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UI/UIEntity.h b/engines/wintermute/UI/UIEntity.h
new file mode 100644
index 0000000000..c18fd952dc
--- /dev/null
+++ b/engines/wintermute/UI/UIEntity.h
@@ -0,0 +1,58 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIENTITY_H
+#define WINTERMUTE_UIENTITY_H
+
+#include "UIObject.h"
+
+namespace WinterMute {
+class CAdEntity;
+class CUIEntity : public CUIObject {
+public:
+ DECLARE_PERSISTENT(CUIEntity, CUIObject)
+ CUIEntity(CBGame *inGame);
+ virtual ~CUIEntity();
+ HRESULT LoadFile(const char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ virtual HRESULT Display(int OffsetX = 0, int OffsetY = 0);
+ CAdEntity *_entity;
+ HRESULT SetEntity(const char *Filename);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(const char *Name);
+ virtual HRESULT ScSetProperty(const char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name);
+ virtual const char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UI/UIObject.cpp b/engines/wintermute/UI/UIObject.cpp
new file mode 100644
index 0000000000..20a89c5897
--- /dev/null
+++ b/engines/wintermute/UI/UIObject.cpp
@@ -0,0 +1,589 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/Base/BGame.h"
+#include "engines/wintermute/Base/BSprite.h"
+#include "engines/wintermute/UI/UIObject.h"
+#include "engines/wintermute/UI/UITiledImage.h"
+#include "engines/wintermute/UI/UIWindow.h"
+#include "engines/wintermute/PlatformSDL.h"
+#include "engines/wintermute/Base/scriptables/ScValue.h"
+#include "engines/wintermute/Base/scriptables/ScStack.h"
+#include "engines/wintermute/Base/BFontStorage.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIObject, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIObject::CUIObject(CBGame *inGame): CBObject(inGame) {
+ _back = NULL;
+ _image = NULL;
+ _font = NULL;
+ _text = NULL;
+ _sharedFonts = _sharedImages = false;
+
+ _width = _height = 0;
+
+ _listenerObject = NULL;
+ _listenerParamObject = NULL;
+ _listenerParamDWORD = 0;
+
+ _disable = false;
+ _visible = true;
+
+ _type = UI_UNKNOWN;
+ _parent = NULL;
+
+ _parentNotify = false;
+
+ _focusedWidget = NULL;
+
+ _canFocus = false;
+ _nonIntMouseEvents = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIObject::~CUIObject() {
+ if (!Game->_loadInProgress) CSysClassRegistry::GetInstance()->EnumInstances(CBGame::InvalidateValues, "CScValue", (void *)this);
+
+ if (_back) delete _back;
+ if (_font && !_sharedFonts) Game->_fontStorage->RemoveFont(_font);
+
+ if (_image && !_sharedImages) delete _image;
+
+ if (_text) delete [] _text;
+
+ _focusedWidget = NULL; // ref only
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIObject::SetText(const char *Text) {
+ if (_text) delete [] _text;
+ _text = new char [strlen(Text) + 1];
+ if (_text) {
+ strcpy(_text, Text);
+ for (int i = 0; i < strlen(_text); i++) {
+ if (_text[i] == '|') _text[i] = '\n';
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::Display(int OffsetX, int OffsetY) {
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIObject::SetListener(CBScriptHolder *Object, CBScriptHolder *ListenerObject, uint32 ListenerParam) {
+ _listenerObject = Object;
+ _listenerParamObject = ListenerObject;
+ _listenerParamDWORD = ListenerParam;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIObject::CorrectSize() {
+ RECT rect;
+
+ if (_width <= 0) {
+ if (_image) {
+ _image->GetBoundingRect(&rect, 0, 0);
+ _width = rect.right - rect.left;
+ } else _width = 100;
+ }
+
+ if (_height <= 0) {
+ if (_image) {
+ _image->GetBoundingRect(&rect, 0, 0);
+ _height = rect.bottom - rect.top;
+ }
+ }
+
+ if (_back) _back->CorrectSize(&_width, &_height);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetFont
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SetFont") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ if (_font) Game->_fontStorage->RemoveFont(_font);
+ if (Val->IsNULL()) {
+ _font = NULL;
+ Stack->PushBool(true);
+ } else {
+ _font = Game->_fontStorage->AddFont(Val->GetString());
+ Stack->PushBool(_font != NULL);
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetImage") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ const char *Filename = Val->GetString();
+
+ delete _image;
+ _image = NULL;
+ if (Val->IsNULL()) {
+ Stack->PushBool(true);
+ return S_OK;
+ }
+
+ _image = new CBSprite(Game);
+ if (!_image || FAILED(_image->LoadFile(Val->GetString()))) {
+ delete _image;
+ _image = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!_image || !_image->_filename) Stack->PushNULL();
+ else Stack->PushString(_image->_filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!_image) Stack->PushNULL();
+ else Stack->PushNative(_image, true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Focus
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Focus") == 0) {
+ Stack->CorrectParams(0);
+ Focus();
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveAfter / MoveBefore
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MoveAfter") == 0 || strcmp(Name, "MoveBefore") == 0) {
+ Stack->CorrectParams(1);
+
+ if (_parent && _parent->_type == UI_WINDOW) {
+ CUIWindow *win = (CUIWindow *)_parent;
+
+ int i;
+ bool found = false;
+ CScValue *val = Stack->Pop();
+ // find directly
+ if (val->IsNative()) {
+ CUIObject *widget = (CUIObject *)val->GetNative();
+ for (i = 0; i < win->_widgets.GetSize(); i++) {
+ if (win->_widgets[i] == widget) {
+ found = true;
+ break;
+ }
+ }
+ }
+ // find by name
+ else {
+ const char *name = val->GetString();
+ for (i = 0; i < win->_widgets.GetSize(); i++) {
+ if (scumm_stricmp(win->_widgets[i]->_name, name) == 0) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ bool done = false;
+ for (int j = 0; j < win->_widgets.GetSize(); j++) {
+ if (win->_widgets[j] == this) {
+ if (strcmp(Name, "MoveAfter") == 0) i++;
+ if (j >= i) j++;
+
+ win->_widgets.InsertAt(i, this);
+ win->_widgets.RemoveAt(j);
+
+ done = true;
+ Stack->PushBool(true);
+ break;
+ }
+ }
+ if (!done) Stack->PushBool(false);
+ } else Stack->PushBool(false);
+
+ } else Stack->PushBool(false);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveToBottom
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MoveToBottom") == 0) {
+ Stack->CorrectParams(0);
+
+ if (_parent && _parent->_type == UI_WINDOW) {
+ CUIWindow *win = (CUIWindow *)_parent;
+ for (int i = 0; i < win->_widgets.GetSize(); i++) {
+ if (win->_widgets[i] == this) {
+ win->_widgets.RemoveAt(i);
+ win->_widgets.InsertAt(0, this);
+ break;
+ }
+ }
+ Stack->PushBool(true);
+ } else Stack->PushBool(false);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveToTop
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "MoveToTop") == 0) {
+ Stack->CorrectParams(0);
+
+ if (_parent && _parent->_type == UI_WINDOW) {
+ CUIWindow *win = (CUIWindow *)_parent;
+ for (int i = 0; i < win->_widgets.GetSize(); i++) {
+ if (win->_widgets[i] == this) {
+ win->_widgets.RemoveAt(i);
+ win->_widgets.Add(this);
+ break;
+ }
+ }
+ Stack->PushBool(true);
+ } else Stack->PushBool(false);
+
+ return S_OK;
+ }
+
+ else return CBObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIObject::ScGetProperty(const char *Name) {
+ _scValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ _scValue->SetString("ui_object");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Name") == 0) {
+ _scValue->SetString(_name);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Parent (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Parent") == 0) {
+ _scValue->SetNative(_parent, true);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ParentNotify
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "ParentNotify") == 0) {
+ _scValue->SetBool(_parentNotify);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Width
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Width") == 0) {
+ _scValue->SetInt(_width);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Height
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Height") == 0) {
+ _scValue->SetInt(_height);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Visible
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Visible") == 0) {
+ _scValue->SetBool(_visible);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Disabled
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Disabled") == 0) {
+ _scValue->SetBool(_disable);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Text") == 0) {
+ _scValue->SetString(_text);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NextSibling (RO) / PrevSibling (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "NextSibling") == 0 || strcmp(Name, "PrevSibling") == 0) {
+ _scValue->SetNULL();
+ if (_parent && _parent->_type == UI_WINDOW) {
+ CUIWindow *win = (CUIWindow *)_parent;
+ for (int i = 0; i < win->_widgets.GetSize(); i++) {
+ if (win->_widgets[i] == this) {
+ if (strcmp(Name, "NextSibling") == 0) {
+ if (i < win->_widgets.GetSize() - 1) _scValue->SetNative(win->_widgets[i + 1], true);
+ } else {
+ if (i > 0) _scValue->SetNative(win->_widgets[i - 1], true);
+ }
+ break;
+ }
+ }
+ }
+ return _scValue;
+ }
+
+ else return CBObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::ScSetProperty(const char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Name") == 0) {
+ SetName(Value->GetString());
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ParentNotify
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "ParentNotify") == 0) {
+ _parentNotify = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Width
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Width") == 0) {
+ _width = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Height
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Height") == 0) {
+ _height = Value->GetInt();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Visible
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Visible") == 0) {
+ _visible = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Disabled
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Disabled") == 0) {
+ _disable = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Text
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Text") == 0) {
+ SetText(Value->GetString());
+ return S_OK;
+ }
+
+ else return CBObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *CUIObject::ScToString() {
+ return "[ui_object]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CUIObject::IsFocused() {
+ if (!Game->_focusedWindow) return false;
+ if (Game->_focusedWindow == this) return true;
+
+ CUIObject *obj = Game->_focusedWindow;
+ while (obj) {
+ if (obj == this) return true;
+ else obj = obj->_focusedWidget;
+ }
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::HandleMouse(TMouseEvent Event, TMouseButton Button) {
+ // handle focus change
+ if (Event == MOUSE_CLICK && Button == MOUSE_BUTTON_LEFT) {
+ Focus();
+ }
+ return CBObject::HandleMouse(Event, Button);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::Focus() {
+ CUIObject *obj = this;
+ bool disabled = false;
+ while (obj) {
+ if (obj->_disable && obj->_type == UI_WINDOW) {
+ disabled = true;
+ break;
+ }
+ obj = obj->_parent;
+ }
+ if (!disabled) {
+ obj = this;
+ while (obj) {
+ if (obj->_parent) {
+ if (!obj->_disable && obj->_canFocus) obj->_parent->_focusedWidget = obj;
+ } else {
+ if (obj->_type == UI_WINDOW) Game->FocusWindow((CUIWindow *)obj);
+ }
+
+ obj = obj->_parent;
+ }
+ }
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::GetTotalOffset(int *OffsetX, int *OffsetY) {
+ int OffX = 0, OffY = 0;
+
+ CUIObject *obj = _parent;
+ while (obj) {
+ OffX += obj->_posX;
+ OffY += obj->_posY;
+
+ obj = obj->_parent;
+ }
+ if (OffsetX) *OffsetX = OffX;
+ if (OffsetY) *OffsetY = OffY;
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::Persist(CBPersistMgr *PersistMgr) {
+
+ CBObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(_back));
+ PersistMgr->Transfer(TMEMBER(_canFocus));
+ PersistMgr->Transfer(TMEMBER(_disable));
+ PersistMgr->Transfer(TMEMBER(_focusedWidget));
+ PersistMgr->Transfer(TMEMBER(_font));
+ PersistMgr->Transfer(TMEMBER(_height));
+ PersistMgr->Transfer(TMEMBER(_image));
+ PersistMgr->Transfer(TMEMBER(_listenerObject));
+ PersistMgr->Transfer(TMEMBER(_listenerParamObject));
+ PersistMgr->Transfer(TMEMBER(_listenerParamDWORD));
+ PersistMgr->Transfer(TMEMBER(_parent));
+ PersistMgr->Transfer(TMEMBER(_parentNotify));
+ PersistMgr->Transfer(TMEMBER(_sharedFonts));
+ PersistMgr->Transfer(TMEMBER(_sharedImages));
+ PersistMgr->Transfer(TMEMBER(_text));
+ PersistMgr->Transfer(TMEMBER_INT(_type));
+ PersistMgr->Transfer(TMEMBER(_visible));
+ PersistMgr->Transfer(TMEMBER(_width));
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIObject::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ return E_FAIL;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UI/UIObject.h b/engines/wintermute/UI/UIObject.h
new file mode 100644
index 0000000000..7d6dfb41f5
--- /dev/null
+++ b/engines/wintermute/UI/UIObject.h
@@ -0,0 +1,83 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIOBJECT_H
+#define WINTERMUTE_UIOBJECT_H
+
+
+#include "engines/wintermute/Base/BObject.h"
+#include "engines/wintermute/dctypes.h" // Added by ClassView
+
+namespace WinterMute {
+
+class CUITiledImage;
+class CBFont;
+class CUIObject : public CBObject {
+public:
+
+ HRESULT GetTotalOffset(int *OffsetX, int *OffsetY);
+ bool _canFocus;
+ HRESULT Focus();
+ virtual HRESULT HandleMouse(TMouseEvent Event, TMouseButton Button);
+ bool IsFocused();
+ bool _parentNotify;
+ DECLARE_PERSISTENT(CUIObject, CBObject)
+ CUIObject *_parent;
+ virtual HRESULT Display(int OffsetX = 0, int OffsetY = 0);
+ virtual void CorrectSize();
+ bool _sharedFonts;
+ bool _sharedImages;
+ void SetText(const char *Text);
+ char *_text;
+ CBFont *_font;
+ bool _visible;
+ CUITiledImage *_back;
+ bool _disable;
+ CUIObject(CBGame *inGame = NULL);
+ virtual ~CUIObject();
+ int _width;
+ int _height;
+ TUIObjectType _type;
+ CBSprite *_image;
+ void SetListener(CBScriptHolder *Object, CBScriptHolder *ListenerObject, uint32 ListenerParam);
+ CBScriptHolder *_listenerParamObject;
+ uint32 _listenerParamDWORD;
+ CBScriptHolder *_listenerObject;
+ CUIObject *_focusedWidget;
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(const char *Name);
+ virtual HRESULT ScSetProperty(const char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name);
+ virtual const char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UI/UIText.cpp b/engines/wintermute/UI/UIText.cpp
new file mode 100644
index 0000000000..c2888e7393
--- /dev/null
+++ b/engines/wintermute/UI/UIText.cpp
@@ -0,0 +1,489 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/Base/BDynBuffer.h"
+#include "engines/wintermute/UI/UIText.h"
+#include "engines/wintermute/UI/UITiledImage.h"
+#include "engines/wintermute/Base/BGame.h"
+#include "engines/wintermute/Base/BParser.h"
+#include "engines/wintermute/Base/scriptables/ScValue.h"
+#include "engines/wintermute/Base/BFont.h"
+#include "engines/wintermute/Base/BFontStorage.h"
+#include "engines/wintermute/Base/BStringTable.h"
+#include "engines/wintermute/Base/scriptables/ScScript.h"
+#include "engines/wintermute/Base/scriptables/ScStack.h"
+#include "engines/wintermute/Base/BSprite.h"
+#include "engines/wintermute/Base/BFileManager.h"
+#include "engines/wintermute/PlatformSDL.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIText, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIText::CUIText(CBGame *inGame): CUIObject(inGame) {
+ _textAlign = TAL_LEFT;
+ _verticalAlign = VAL_CENTER;
+ _type = UI_STATIC;
+ _canFocus = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIText::~CUIText() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::Display(int OffsetX, int OffsetY) {
+ if (!_visible) return S_OK;
+
+
+ CBFont *font = _font;
+ if (!font) font = Game->_systemFont;
+
+ if (_back) _back->Display(OffsetX + _posX, OffsetY + _posY, _width, _height);
+ if (_image) _image->Draw(OffsetX + _posX, OffsetY + _posY, NULL);
+
+ if (font && _text) {
+ int text_offset;
+ switch (_verticalAlign) {
+ case VAL_TOP:
+ text_offset = 0;
+ break;
+ case VAL_BOTTOM:
+ text_offset = _height - font->GetTextHeight((byte *)_text, _width);
+ break;
+ default:
+ text_offset = (_height - font->GetTextHeight((byte *)_text, _width)) / 2;
+ }
+ font->DrawText((byte *)_text, OffsetX + _posX, OffsetY + _posY + text_offset, _width, _textAlign, _height);
+ }
+
+ //Game->_renderer->_rectList.Add(new CBActiveRect(Game, this, NULL, OffsetX + _posX, OffsetY + _posY, _width, _height, 100, 100, false));
+
+ return S_OK;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::LoadFile(const char *Filename) {
+ byte *Buffer = Game->_fileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIText::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ _filename = new char [strlen(Filename) + 1];
+ strcpy(_filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing STATIC file '%s'", Filename);
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(STATIC)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(BACK)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(FONT)
+TOKEN_DEF(TEXT_ALIGN)
+TOKEN_DEF(VERTICAL_ALIGN)
+TOKEN_DEF(TEXT)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(WIDTH)
+TOKEN_DEF(HEIGHT)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(NAME)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF(PARENT_NOTIFY)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(STATIC)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(BACK)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TEXT_ALIGN)
+ TOKEN_TABLE(VERTICAL_ALIGN)
+ TOKEN_TABLE(TEXT)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(WIDTH)
+ TOKEN_TABLE(HEIGHT)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE(PARENT_NOTIFY)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_STATIC) {
+ Game->LOG(0, "'STATIC' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd > 0 && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_CAPTION:
+ SetCaption((char *)params);
+ break;
+
+ case TOKEN_BACK:
+ delete _back;
+ _back = new CUITiledImage(Game);
+ if (!_back || FAILED(_back->LoadFile((char *)params))) {
+ delete _back;
+ _back = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE:
+ delete _image;
+ _image = new CBSprite(Game);
+ if (!_image || FAILED(_image->LoadFile((char *)params))) {
+ delete _image;
+ _image = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_FONT:
+ if (_font) Game->_fontStorage->RemoveFont(_font);
+ _font = Game->_fontStorage->AddFont((char *)params);
+ if (!_font) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_TEXT:
+ SetText((char *)params);
+ Game->_stringTable->Expand(&_text);
+ break;
+
+ case TOKEN_TEXT_ALIGN:
+ if (scumm_stricmp((char *)params, "left") == 0) _textAlign = TAL_LEFT;
+ else if (scumm_stricmp((char *)params, "right") == 0) _textAlign = TAL_RIGHT;
+ else _textAlign = TAL_CENTER;
+ break;
+
+ case TOKEN_VERTICAL_ALIGN:
+ if (scumm_stricmp((char *)params, "top") == 0) _verticalAlign = VAL_TOP;
+ else if (scumm_stricmp((char *)params, "bottom") == 0) _verticalAlign = VAL_BOTTOM;
+ else _verticalAlign = VAL_CENTER;
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &_posX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &_posY);
+ break;
+
+ case TOKEN_WIDTH:
+ parser.ScanStr((char *)params, "%d", &_width);
+ break;
+
+ case TOKEN_HEIGHT:
+ parser.ScanStr((char *)params, "%d", &_height);
+ break;
+
+ case TOKEN_CURSOR:
+ delete _cursor;
+ _cursor = new CBSprite(Game);
+ if (!_cursor || FAILED(_cursor->LoadFile((char *)params))) {
+ delete _cursor;
+ _cursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_PARENT_NOTIFY:
+ parser.ScanStr((char *)params, "%b", &_parentNotify);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &_disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &_visible);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in STATIC definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading STATIC definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "STATIC\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", _name);
+ Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption());
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (_back && _back->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK=\"%s\"\n", _back->_filename);
+
+ if (_image && _image->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", _image->_filename);
+
+ if (_font && _font->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT=\"%s\"\n", _font->_filename);
+
+ if (_cursor && _cursor->_filename)
+ Buffer->PutTextIndent(Indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename);
+
+ if (_text)
+ Buffer->PutTextIndent(Indent + 2, "TEXT=\"%s\"\n", _text);
+
+ switch (_textAlign) {
+ case TAL_LEFT:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "left");
+ break;
+ case TAL_RIGHT:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "right");
+ break;
+ case TAL_CENTER:
+ Buffer->PutTextIndent(Indent + 2, "TEXT_ALIGN=\"%s\"\n", "center");
+ break;
+ default:
+ error("CUIText::SaveAsText - Unhandled enum");
+ break;
+ }
+
+ switch (_verticalAlign) {
+ case VAL_TOP:
+ Buffer->PutTextIndent(Indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "top");
+ break;
+ case VAL_BOTTOM:
+ Buffer->PutTextIndent(Indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "bottom");
+ break;
+ case VAL_CENTER:
+ Buffer->PutTextIndent(Indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "center");
+ break;
+ default:
+ error("UIText::SaveAsText - Unhandled enum value: NUM_VERTICAL_ALIGN");
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", _posX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", _posY);
+ Buffer->PutTextIndent(Indent + 2, "WIDTH=%d\n", _width);
+ Buffer->PutTextIndent(Indent + 2, "HEIGHT=%d\n", _height);
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE");
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // scripts
+ for (int i = 0; i < _scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SizeToFit
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "SizeToFit") == 0) {
+ Stack->CorrectParams(0);
+ SizeToFit();
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HeightToFit
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "HeightToFit") == 0) {
+ Stack->CorrectParams(0);
+ if (_font && _text) _height = _font->GetTextHeight((byte *)_text, _width);
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIText::ScGetProperty(const char *Name) {
+ _scValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ _scValue->SetString("static");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextAlign
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "TextAlign") == 0) {
+ _scValue->SetInt(_textAlign);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // VerticalAlign
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "VerticalAlign") == 0) {
+ _scValue->SetInt(_verticalAlign);
+ return _scValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::ScSetProperty(const char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // TextAlign
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "TextAlign") == 0) {
+ int i = Value->GetInt();
+ if (i < 0 || i >= NUM_TEXT_ALIGN) i = 0;
+ _textAlign = (TTextAlign)i;
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // VerticalAlign
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "VerticalAlign") == 0) {
+ int i = Value->GetInt();
+ if (i < 0 || i >= NUM_VERTICAL_ALIGN) i = 0;
+ _verticalAlign = (TVerticalAlign)i;
+ return S_OK;
+ }
+
+ else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *CUIText::ScToString() {
+ return "[static]";
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+ PersistMgr->Transfer(TMEMBER_INT(_textAlign));
+ PersistMgr->Transfer(TMEMBER_INT(_verticalAlign));
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIText::SizeToFit() {
+ if (_font && _text) {
+ _width = _font->GetTextWidth((byte *)_text);
+ _height = _font->GetTextHeight((byte *)_text, _width);
+ }
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UI/UIText.h b/engines/wintermute/UI/UIText.h
new file mode 100644
index 0000000000..756834fd5c
--- /dev/null
+++ b/engines/wintermute/UI/UIText.h
@@ -0,0 +1,59 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UITEXT_H
+#define WINTERMUTE_UITEXT_H
+
+
+#include "UIObject.h"
+
+namespace WinterMute {
+
+class CUIText : public CUIObject {
+public:
+ HRESULT SizeToFit();
+ virtual HRESULT Display(int OffsetX, int OffsetY);
+ DECLARE_PERSISTENT(CUIText, CUIObject)
+ CUIText(CBGame *inGame = NULL);
+ virtual ~CUIText();
+ TTextAlign _textAlign;
+ TVerticalAlign _verticalAlign;
+ HRESULT LoadFile(const char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(const char *Name);
+ virtual HRESULT ScSetProperty(const char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name);
+ virtual const char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UI/UITiledImage.cpp b/engines/wintermute/UI/UITiledImage.cpp
new file mode 100644
index 0000000000..9965ed5128
--- /dev/null
+++ b/engines/wintermute/UI/UITiledImage.cpp
@@ -0,0 +1,370 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/UI/UITiledImage.h"
+#include "engines/wintermute/Base/BSurface.h"
+#include "engines/wintermute/Base/BDynBuffer.h"
+#include "engines/wintermute/Base/BParser.h"
+#include "engines/wintermute/Base/BGame.h"
+#include "engines/wintermute/Base/BSubFrame.h"
+#include "engines/wintermute/Base/BFileManager.h"
+#include "engines/wintermute/PlatformSDL.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUITiledImage, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUITiledImage::CUITiledImage(CBGame *inGame): CBObject(inGame) {
+ _image = NULL;
+
+ CBPlatform::SetRectEmpty(&_upLeft);
+ CBPlatform::SetRectEmpty(&_upMiddle);
+ CBPlatform::SetRectEmpty(&_upRight);
+ CBPlatform::SetRectEmpty(&_middleLeft);
+ CBPlatform::SetRectEmpty(&_middleMiddle);
+ CBPlatform::SetRectEmpty(&_middleRight);
+ CBPlatform::SetRectEmpty(&_downLeft);
+ CBPlatform::SetRectEmpty(&_downMiddle);
+ CBPlatform::SetRectEmpty(&_downRight);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUITiledImage::~CUITiledImage() {
+ delete _image;
+ _image = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::Display(int X, int Y, int Width, int Height) {
+ if (!_image) return E_FAIL;
+
+ int tile_width = _middleMiddle.right - _middleMiddle.left;
+ int tile_height = _middleMiddle.bottom - _middleMiddle.top;
+
+ int nu_columns = (Width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tile_width;
+ int nu_rows = (Height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tile_height;
+
+ int col, row;
+
+ Game->_renderer->StartSpriteBatch();
+
+ // top left/right
+ _image->_surface->DisplayTrans(X, Y, _upLeft);
+ _image->_surface->DisplayTrans(X + (_upLeft.right - _upLeft.left) + nu_columns * tile_width, Y, _upRight);
+
+ // bottom left/right
+ _image->_surface->DisplayTrans(X, Y + (_upMiddle.bottom - _upMiddle.top) + nu_rows * tile_height, _downLeft);
+ _image->_surface->DisplayTrans(X + (_upLeft.right - _upLeft.left) + nu_columns * tile_width, Y + (_upMiddle.bottom - _upMiddle.top) + nu_rows * tile_height, _downRight);
+
+ // left/right
+ int yyy = Y + (_upMiddle.bottom - _upMiddle.top);
+ for (row = 0; row < nu_rows; row++) {
+ _image->_surface->DisplayTrans(X, yyy, _middleLeft);
+ _image->_surface->DisplayTrans(X + (_middleLeft.right - _middleLeft.left) + nu_columns * tile_width, yyy, _middleRight);
+ yyy += tile_width;
+ }
+
+ // top/bottom
+ int xxx = X + (_upLeft.right - _upLeft.left);
+ for (col = 0; col < nu_columns; col++) {
+ _image->_surface->DisplayTrans(xxx, Y, _upMiddle);
+ _image->_surface->DisplayTrans(xxx, Y + (_upMiddle.bottom - _upMiddle.top) + nu_rows * tile_height, _downMiddle);
+ xxx += tile_width;
+ }
+
+ // tiles
+ yyy = Y + (_upMiddle.bottom - _upMiddle.top);
+ for (row = 0; row < nu_rows; row++) {
+ xxx = X + (_upLeft.right - _upLeft.left);
+ for (col = 0; col < nu_columns; col++) {
+ _image->_surface->DisplayTrans(xxx, yyy, _middleMiddle);
+ xxx += tile_width;
+ }
+ yyy += tile_width;
+ }
+
+ Game->_renderer->EndSpriteBatch();
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::LoadFile(const char *Filename) {
+ byte *Buffer = Game->_fileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUITiledImage::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ _filename = new char [strlen(Filename) + 1];
+ strcpy(_filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing TILED_IMAGE file '%s'", Filename);
+
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(TILED_IMAGE)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(UP_LEFT)
+TOKEN_DEF(UP_RIGHT)
+TOKEN_DEF(UP_MIDDLE)
+TOKEN_DEF(DOWN_LEFT)
+TOKEN_DEF(DOWN_RIGHT)
+TOKEN_DEF(DOWN_MIDDLE)
+TOKEN_DEF(MIDDLE_LEFT)
+TOKEN_DEF(MIDDLE_RIGHT)
+TOKEN_DEF(MIDDLE_MIDDLE)
+TOKEN_DEF(VERTICAL_TILES)
+TOKEN_DEF(HORIZONTAL_TILES)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(TILED_IMAGE)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(UP_LEFT)
+ TOKEN_TABLE(UP_RIGHT)
+ TOKEN_TABLE(UP_MIDDLE)
+ TOKEN_TABLE(DOWN_LEFT)
+ TOKEN_TABLE(DOWN_RIGHT)
+ TOKEN_TABLE(DOWN_MIDDLE)
+ TOKEN_TABLE(MIDDLE_LEFT)
+ TOKEN_TABLE(MIDDLE_RIGHT)
+ TOKEN_TABLE(MIDDLE_MIDDLE)
+ TOKEN_TABLE(VERTICAL_TILES)
+ TOKEN_TABLE(HORIZONTAL_TILES)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd;
+ CBParser parser(Game);
+ bool HTiles = false, VTiles = false;
+ int H1 = 0, H2 = 0, H3 = 0;
+ int V1 = 0, V2 = 0, V3 = 0;
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_TILED_IMAGE) {
+ Game->LOG(0, "'TILED_IMAGE' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_IMAGE:
+ delete _image;
+ _image = new CBSubFrame(Game);
+ if (!_image || FAILED(_image->SetSurface((char *)params))) {
+ delete _image;
+ _image = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_UP_LEFT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_upLeft.left, &_upLeft.top, &_upLeft.right, &_upLeft.bottom);
+ break;
+
+ case TOKEN_UP_RIGHT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_upRight.left, &_upRight.top, &_upRight.right, &_upRight.bottom);
+ break;
+
+ case TOKEN_UP_MIDDLE:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_upMiddle.left, &_upMiddle.top, &_upMiddle.right, &_upMiddle.bottom);
+ break;
+
+ case TOKEN_DOWN_LEFT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_downLeft.left, &_downLeft.top, &_downLeft.right, &_downLeft.bottom);
+ break;
+
+ case TOKEN_DOWN_RIGHT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_downRight.left, &_downRight.top, &_downRight.right, &_downRight.bottom);
+ break;
+
+ case TOKEN_DOWN_MIDDLE:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_downMiddle.left, &_downMiddle.top, &_downMiddle.right, &_downMiddle.bottom);
+ break;
+
+ case TOKEN_MIDDLE_LEFT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_middleLeft.left, &_middleLeft.top, &_middleLeft.right, &_middleLeft.bottom);
+ break;
+
+ case TOKEN_MIDDLE_RIGHT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_middleRight.left, &_middleRight.top, &_middleRight.right, &_middleRight.bottom);
+ break;
+
+ case TOKEN_MIDDLE_MIDDLE:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_middleMiddle.left, &_middleMiddle.top, &_middleMiddle.right, &_middleMiddle.bottom);
+ break;
+
+ case TOKEN_HORIZONTAL_TILES:
+ parser.ScanStr((char *)params, "%d,%d,%d", &H1, &H2, &H3);
+ HTiles = true;
+ break;
+
+ case TOKEN_VERTICAL_TILES:
+ parser.ScanStr((char *)params, "%d,%d,%d", &V1, &V2, &V3);
+ VTiles = true;
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in TILED_IMAGE definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading TILED_IMAGE definition");
+ return E_FAIL;
+ }
+
+ if (VTiles && HTiles) {
+ // up row
+ CBPlatform::SetRect(&_upLeft, 0, 0, H1, V1);
+ CBPlatform::SetRect(&_upMiddle, H1, 0, H1 + H2, V1);
+ CBPlatform::SetRect(&_upRight, H1 + H2, 0, H1 + H2 + H3, V1);
+
+ // middle row
+ CBPlatform::SetRect(&_middleLeft, 0, V1, H1, V1 + V2);
+ CBPlatform::SetRect(&_middleMiddle, H1, V1, H1 + H2, V1 + V2);
+ CBPlatform::SetRect(&_middleRight, H1 + H2, V1, H1 + H2 + H3, V1 + V2);
+
+ // down row
+ CBPlatform::SetRect(&_downLeft, 0, V1 + V2, H1, V1 + V2 + V3);
+ CBPlatform::SetRect(&_downMiddle, H1, V1 + V2, H1 + H2, V1 + V2 + V3);
+ CBPlatform::SetRect(&_downRight, H1 + H2, V1 + V2, H1 + H2 + H3, V1 + V2 + V3);
+ }
+
+ // default
+ if (_image && _image->_surface) {
+ int Width = _image->_surface->GetWidth() / 3;
+ int Height = _image->_surface->GetHeight() / 3;
+
+ if (CBPlatform::IsRectEmpty(&_upLeft)) CBPlatform::SetRect(&_upLeft, 0, 0, Width, Height);
+ if (CBPlatform::IsRectEmpty(&_upMiddle)) CBPlatform::SetRect(&_upMiddle, Width, 0, 2 * Width, Height);
+ if (CBPlatform::IsRectEmpty(&_upRight)) CBPlatform::SetRect(&_upRight, 2 * Width, 0, 3 * Width, Height);
+
+ if (CBPlatform::IsRectEmpty(&_middleLeft)) CBPlatform::SetRect(&_middleLeft, 0, Height, Width, 2 * Height);
+ if (CBPlatform::IsRectEmpty(&_middleMiddle)) CBPlatform::SetRect(&_middleMiddle, Width, Height, 2 * Width, 2 * Height);
+ if (CBPlatform::IsRectEmpty(&_middleRight)) CBPlatform::SetRect(&_middleRight, 2 * Width, Height, 3 * Width, 2 * Height);
+
+ if (CBPlatform::IsRectEmpty(&_downLeft)) CBPlatform::SetRect(&_downLeft, 0, 2 * Height, Width, 3 * Height);
+ if (CBPlatform::IsRectEmpty(&_downMiddle)) CBPlatform::SetRect(&_downMiddle, Width, 2 * Height, 2 * Width, 3 * Height);
+ if (CBPlatform::IsRectEmpty(&_downRight)) CBPlatform::SetRect(&_downRight, 2 * Width, 2 * Height, 3 * Width, 3 * Height);
+ }
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "TILED_IMAGE\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ if (_image && _image->_surfaceFilename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", _image->_surfaceFilename);
+
+ int H1, H2, H3;
+ int V1, V2, V3;
+
+ H1 = _upLeft.right;
+ H2 = _upMiddle.right - _upMiddle.left;
+ H3 = _upRight.right - _upRight.left;
+
+ V1 = _upLeft.bottom;
+ V2 = _middleLeft.bottom - _middleLeft.top;
+ V3 = _downLeft.bottom - _downLeft.top;
+
+
+ Buffer->PutTextIndent(Indent + 2, "VERTICAL_TILES { %d, %d, %d }\n", V1, V2, V3);
+ Buffer->PutTextIndent(Indent + 2, "HORIZONTAL_TILES { %d, %d, %d }\n", H1, H2, H3);
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CUITiledImage::CorrectSize(int *Width, int *Height) {
+ int tile_width = _middleMiddle.right - _middleMiddle.left;
+ int tile_height = _middleMiddle.bottom - _middleMiddle.top;
+
+ int nu_columns = (*Width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tile_width;
+ int nu_rows = (*Height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tile_height;
+
+ *Width = (_middleLeft.right - _middleLeft.left) + (_middleRight.right - _middleRight.left) + nu_columns * tile_width;
+ *Height = (_upMiddle.bottom - _upMiddle.top) + (_downMiddle.bottom - _downMiddle.top) + nu_rows * tile_height;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUITiledImage::Persist(CBPersistMgr *PersistMgr) {
+ CBObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(_downLeft));
+ PersistMgr->Transfer(TMEMBER(_downMiddle));
+ PersistMgr->Transfer(TMEMBER(_downRight));
+ PersistMgr->Transfer(TMEMBER(_image));
+ PersistMgr->Transfer(TMEMBER(_middleLeft));
+ PersistMgr->Transfer(TMEMBER(_middleMiddle));
+ PersistMgr->Transfer(TMEMBER(_middleRight));
+ PersistMgr->Transfer(TMEMBER(_upLeft));
+ PersistMgr->Transfer(TMEMBER(_upMiddle));
+ PersistMgr->Transfer(TMEMBER(_upRight));
+
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UI/UITiledImage.h b/engines/wintermute/UI/UITiledImage.h
new file mode 100644
index 0000000000..03d15a0daa
--- /dev/null
+++ b/engines/wintermute/UI/UITiledImage.h
@@ -0,0 +1,62 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UITILEDIMAGE_H
+#define WINTERMUTE_UITILEDIMAGE_H
+
+
+#include "UIObject.h"
+
+namespace WinterMute {
+class CBSubFrame;
+class CUITiledImage : public CBObject {
+public:
+ DECLARE_PERSISTENT(CUITiledImage, CBObject)
+ void CorrectSize(int *Width, int *Height);
+ HRESULT LoadFile(const char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ HRESULT Display(int X, int Y, int Width, int Height);
+ CUITiledImage(CBGame *inGame = NULL);
+ virtual ~CUITiledImage();
+ CBSubFrame *_image;
+ RECT _upLeft;
+ RECT _upMiddle;
+ RECT _upRight;
+ RECT _middleLeft;
+ RECT _middleMiddle;
+ RECT _middleRight;
+ RECT _downLeft;
+ RECT _downMiddle;
+ RECT _downRight;
+};
+
+} // end of namespace WinterMute
+
+#endif
diff --git a/engines/wintermute/UI/UIWindow.cpp b/engines/wintermute/UI/UIWindow.cpp
new file mode 100644
index 0000000000..d364b27740
--- /dev/null
+++ b/engines/wintermute/UI/UIWindow.cpp
@@ -0,0 +1,1321 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/UI/UIWindow.h"
+#include "engines/wintermute/Base/BGame.h"
+#include "engines/wintermute/Base/BParser.h"
+#include "engines/wintermute/Base/BActiveRect.h"
+#include "engines/wintermute/Base/BDynBuffer.h"
+#include "engines/wintermute/Base/BKeyboardState.h"
+#include "engines/wintermute/Base/scriptables/ScValue.h"
+#include "engines/wintermute/UI/UIButton.h"
+#include "engines/wintermute/UI/UIEdit.h"
+#include "engines/wintermute/UI/UIText.h"
+#include "engines/wintermute/UI/UITiledImage.h"
+#include "engines/wintermute/Base/BViewport.h"
+#include "engines/wintermute/Base/BFontStorage.h"
+#include "engines/wintermute/Base/BFont.h"
+#include "engines/wintermute/Base/BStringTable.h"
+#include "engines/wintermute/Base/scriptables/ScScript.h"
+#include "engines/wintermute/Base/scriptables/ScStack.h"
+#include "engines/wintermute/Base/BSprite.h"
+#include "engines/wintermute/Base/BFileManager.h"
+#include "engines/wintermute/PlatformSDL.h"
+
+namespace WinterMute {
+
+IMPLEMENT_PERSISTENT(CUIWindow, false)
+
+//////////////////////////////////////////////////////////////////////////
+CUIWindow::CUIWindow(CBGame *inGame): CUIObject(inGame) {
+ CBPlatform::SetRectEmpty(&_titleRect);
+ CBPlatform::SetRectEmpty(&_dragRect);
+ _titleAlign = TAL_LEFT;
+ _transparent = false;
+
+ _backInactive = NULL;
+ _fontInactive = NULL;
+ _imageInactive = NULL;
+
+ _type = UI_WINDOW;
+ _canFocus = true;
+
+ _dragging = false;
+ _dragFrom.x = _dragFrom.y = 0;
+
+ _mode = WINDOW_NORMAL;
+ _shieldWindow = NULL;
+ _shieldButton = NULL;
+
+ _fadeColor = 0x00000000;
+ _fadeBackground = false;
+
+ _ready = true;
+ _isMenu = false;
+ _inGame = false;
+
+ _clipContents = false;
+ _viewport = NULL;
+
+ _pauseMusic = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CUIWindow::~CUIWindow() {
+ Close();
+ Cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIWindow::Cleanup() {
+ delete _shieldWindow;
+ delete _shieldButton;
+ delete _viewport;
+ _shieldWindow = NULL;
+ _shieldButton = NULL;
+ _viewport = NULL;
+
+ if (_backInactive) delete _backInactive;
+ if (!_sharedFonts && _fontInactive) Game->_fontStorage->RemoveFont(_fontInactive);
+ if (!_sharedImages && _imageInactive) delete _imageInactive;
+
+ for (int i = 0; i < _widgets.GetSize(); i++) delete _widgets[i];
+ _widgets.RemoveAll();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::Display(int OffsetX, int OffsetY) {
+ // go exclusive
+ if (_mode == WINDOW_EXCLUSIVE || _mode == WINDOW_SYSTEM_EXCLUSIVE) {
+ if (!_shieldWindow) _shieldWindow = new CUIWindow(Game);
+ if (_shieldWindow) {
+ _shieldWindow->_posX = _shieldWindow->_posY = 0;
+ _shieldWindow->_width = Game->_renderer->_width;
+ _shieldWindow->_height = Game->_renderer->_height;
+
+ _shieldWindow->Display();
+ }
+ } else if (_isMenu) {
+ if (!_shieldButton) {
+ _shieldButton = new CUIButton(Game);
+ _shieldButton->SetName("close");
+ _shieldButton->SetListener(this, _shieldButton, 0);
+ _shieldButton->_parent = this;
+ }
+ if (_shieldButton) {
+ _shieldButton->_posX = _shieldButton->_posY = 0;
+ _shieldButton->_width = Game->_renderer->_width;
+ _shieldButton->_height = Game->_renderer->_height;
+
+ _shieldButton->Display();
+ }
+ }
+
+ if (!_visible) return S_OK;
+
+ if (_fadeBackground) Game->_renderer->FadeToColor(_fadeColor);
+
+ if (_dragging) {
+ _posX += (Game->_mousePos.x - _dragFrom.x);
+ _posY += (Game->_mousePos.y - _dragFrom.y);
+
+ _dragFrom.x = Game->_mousePos.x;
+ _dragFrom.y = Game->_mousePos.y;
+ }
+
+ if (!_focusedWidget || (!_focusedWidget->_canFocus || _focusedWidget->_disable || !_focusedWidget->_visible)) {
+ MoveFocus();
+ }
+
+ bool PopViewport = false;
+ if (_clipContents) {
+ if (!_viewport) _viewport = new CBViewport(Game);
+ if (_viewport) {
+ _viewport->SetRect(_posX + OffsetX, _posY + OffsetY, _posX + _width + OffsetX, _posY + _height + OffsetY);
+ Game->PushViewport(_viewport);
+ PopViewport = true;
+ }
+ }
+
+
+ CUITiledImage *back = _back;
+ CBSprite *image = _image;
+ CBFont *font = _font;
+
+ if (!IsFocused()) {
+ if (_backInactive) back = _backInactive;
+ if (_imageInactive) image = _imageInactive;
+ if (_fontInactive) font = _fontInactive;
+ }
+
+ if (_alphaColor != 0) Game->_renderer->_forceAlphaColor = _alphaColor;
+ if (back) back->Display(_posX + OffsetX, _posY + OffsetY, _width, _height);
+ if (image) image->Draw(_posX + OffsetX, _posY + OffsetY, _transparent ? NULL : this);
+
+ if (!CBPlatform::IsRectEmpty(&_titleRect) && font && _text) {
+ font->DrawText((byte *)_text, _posX + OffsetX + _titleRect.left, _posY + OffsetY + _titleRect.top, _titleRect.right - _titleRect.left, _titleAlign, _titleRect.bottom - _titleRect.top);
+ }
+
+ if (!_transparent && !image) Game->_renderer->_rectList.Add(new CBActiveRect(Game, this, NULL, _posX + OffsetX, _posY + OffsetY, _width, _height, 100, 100, false));
+
+ for (int i = 0; i < _widgets.GetSize(); i++) {
+ _widgets[i]->Display(_posX + OffsetX, _posY + OffsetY);
+ }
+
+ if (_alphaColor != 0) Game->_renderer->_forceAlphaColor = 0;
+
+ if (PopViewport) Game->PopViewport();
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::LoadFile(const char *Filename) {
+ byte *Buffer = Game->_fileManager->ReadWholeFile(Filename);
+ if (Buffer == NULL) {
+ Game->LOG(0, "CUIWindow::LoadFile failed for file '%s'", Filename);
+ return E_FAIL;
+ }
+
+ HRESULT ret;
+
+ _filename = new char [strlen(Filename) + 1];
+ strcpy(_filename, Filename);
+
+ if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing WINDOW file '%s'", Filename);
+
+ delete [] Buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(WINDOW)
+TOKEN_DEF(ALPHA_COLOR)
+TOKEN_DEF(ALPHA)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(DISABLED)
+TOKEN_DEF(VISIBLE)
+TOKEN_DEF(BACK_INACTIVE)
+TOKEN_DEF(BACK)
+TOKEN_DEF(IMAGE_INACTIVE)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(FONT_INACTIVE)
+TOKEN_DEF(FONT)
+TOKEN_DEF(TITLE_ALIGN)
+TOKEN_DEF(TITLE_RECT)
+TOKEN_DEF(TITLE)
+TOKEN_DEF(DRAG_RECT)
+TOKEN_DEF(X)
+TOKEN_DEF(Y)
+TOKEN_DEF(WIDTH)
+TOKEN_DEF(HEIGHT)
+TOKEN_DEF(FADE_ALPHA)
+TOKEN_DEF(FADE_COLOR)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(NAME)
+TOKEN_DEF(BUTTON)
+TOKEN_DEF(STATIC)
+TOKEN_DEF(TRANSPARENT)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF(PARENT_NOTIFY)
+TOKEN_DEF(MENU)
+TOKEN_DEF(IN_GAME)
+TOKEN_DEF(CLIP_CONTENTS)
+TOKEN_DEF(PAUSE_MUSIC)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF(EDIT)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::LoadBuffer(byte *Buffer, bool Complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(WINDOW)
+ TOKEN_TABLE(ALPHA_COLOR)
+ TOKEN_TABLE(ALPHA)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(DISABLED)
+ TOKEN_TABLE(VISIBLE)
+ TOKEN_TABLE(BACK_INACTIVE)
+ TOKEN_TABLE(BACK)
+ TOKEN_TABLE(IMAGE_INACTIVE)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(FONT_INACTIVE)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TITLE_ALIGN)
+ TOKEN_TABLE(TITLE_RECT)
+ TOKEN_TABLE(TITLE)
+ TOKEN_TABLE(DRAG_RECT)
+ TOKEN_TABLE(X)
+ TOKEN_TABLE(Y)
+ TOKEN_TABLE(WIDTH)
+ TOKEN_TABLE(HEIGHT)
+ TOKEN_TABLE(FADE_ALPHA)
+ TOKEN_TABLE(FADE_COLOR)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(BUTTON)
+ TOKEN_TABLE(STATIC)
+ TOKEN_TABLE(TRANSPARENT)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE(PARENT_NOTIFY)
+ TOKEN_TABLE(MENU)
+ TOKEN_TABLE(IN_GAME)
+ TOKEN_TABLE(CLIP_CONTENTS)
+ TOKEN_TABLE(PAUSE_MUSIC)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE(EDIT)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd = 2;
+ CBParser parser(Game);
+
+ int FadeR = 0, FadeG = 0, FadeB = 0, FadeA = 0;
+ int ar = 0, ag = 0, ab = 0, alpha = 0;
+
+ if (Complete) {
+ if (parser.GetCommand((char **)&Buffer, commands, (char **)&params) != TOKEN_WINDOW) {
+ Game->LOG(0, "'WINDOW' keyword expected.");
+ return E_FAIL;
+ }
+ Buffer = params;
+ }
+
+ while (cmd >= PARSERR_TOKENNOTFOUND && (cmd = parser.GetCommand((char **)&Buffer, commands, (char **)&params)) >= PARSERR_TOKENNOTFOUND) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_NAME:
+ SetName((char *)params);
+ break;
+
+ case TOKEN_CAPTION:
+ SetCaption((char *)params);
+ break;
+
+ case TOKEN_BACK:
+ delete _back;
+ _back = new CUITiledImage(Game);
+ if (!_back || FAILED(_back->LoadFile((char *)params))) {
+ delete _back;
+ _back = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BACK_INACTIVE:
+ delete _backInactive;
+ _backInactive = new CUITiledImage(Game);
+ if (!_backInactive || FAILED(_backInactive->LoadFile((char *)params))) {
+ delete _backInactive;
+ _backInactive = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE:
+ delete _image;
+ _image = new CBSprite(Game);
+ if (!_image || FAILED(_image->LoadFile((char *)params))) {
+ delete _image;
+ _image = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_IMAGE_INACTIVE:
+ delete _imageInactive,
+ _imageInactive = new CBSprite(Game);
+ if (!_imageInactive || FAILED(_imageInactive->LoadFile((char *)params))) {
+ delete _imageInactive;
+ _imageInactive = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_FONT:
+ if (_font) Game->_fontStorage->RemoveFont(_font);
+ _font = Game->_fontStorage->AddFont((char *)params);
+ if (!_font) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_FONT_INACTIVE:
+ if (_fontInactive) Game->_fontStorage->RemoveFont(_fontInactive);
+ _fontInactive = Game->_fontStorage->AddFont((char *)params);
+ if (!_fontInactive) cmd = PARSERR_GENERIC;
+ break;
+
+ case TOKEN_TITLE:
+ SetText((char *)params);
+ Game->_stringTable->Expand(&_text);
+ break;
+
+ case TOKEN_TITLE_ALIGN:
+ if (scumm_stricmp((char *)params, "left") == 0) _titleAlign = TAL_LEFT;
+ else if (scumm_stricmp((char *)params, "right") == 0) _titleAlign = TAL_RIGHT;
+ else _titleAlign = TAL_CENTER;
+ break;
+
+ case TOKEN_TITLE_RECT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_titleRect.left, &_titleRect.top, &_titleRect.right, &_titleRect.bottom);
+ break;
+
+ case TOKEN_DRAG_RECT:
+ parser.ScanStr((char *)params, "%d,%d,%d,%d", &_dragRect.left, &_dragRect.top, &_dragRect.right, &_dragRect.bottom);
+ break;
+
+ case TOKEN_X:
+ parser.ScanStr((char *)params, "%d", &_posX);
+ break;
+
+ case TOKEN_Y:
+ parser.ScanStr((char *)params, "%d", &_posY);
+ break;
+
+ case TOKEN_WIDTH:
+ parser.ScanStr((char *)params, "%d", &_width);
+ break;
+
+ case TOKEN_HEIGHT:
+ parser.ScanStr((char *)params, "%d", &_height);
+ break;
+
+ case TOKEN_CURSOR:
+ delete _cursor;
+ _cursor = new CBSprite(Game);
+ if (!_cursor || FAILED(_cursor->LoadFile((char *)params))) {
+ delete _cursor;
+ _cursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_BUTTON: {
+ CUIButton *btn = new CUIButton(Game);
+ if (!btn || FAILED(btn->LoadBuffer(params, false))) {
+ delete btn;
+ btn = NULL;
+ cmd = PARSERR_GENERIC;
+ } else {
+ btn->_parent = this;
+ _widgets.Add(btn);
+ }
+ }
+ break;
+
+ case TOKEN_STATIC: {
+ CUIText *text = new CUIText(Game);
+ if (!text || FAILED(text->LoadBuffer(params, false))) {
+ delete text;
+ text = NULL;
+ cmd = PARSERR_GENERIC;
+ } else {
+ text->_parent = this;
+ _widgets.Add(text);
+ }
+ }
+ break;
+
+ case TOKEN_EDIT: {
+ CUIEdit *edit = new CUIEdit(Game);
+ if (!edit || FAILED(edit->LoadBuffer(params, false))) {
+ delete edit;
+ edit = NULL;
+ cmd = PARSERR_GENERIC;
+ } else {
+ edit->_parent = this;
+ _widgets.Add(edit);
+ }
+ }
+ break;
+
+ case TOKEN_WINDOW: {
+ CUIWindow *win = new CUIWindow(Game);
+ if (!win || FAILED(win->LoadBuffer(params, false))) {
+ delete win;
+ win = NULL;
+ cmd = PARSERR_GENERIC;
+ } else {
+ win->_parent = this;
+ _widgets.Add(win);
+ }
+ }
+ break;
+
+
+ case TOKEN_TRANSPARENT:
+ parser.ScanStr((char *)params, "%b", &_transparent);
+ break;
+
+ case TOKEN_SCRIPT:
+ AddScript((char *)params);
+ break;
+
+ case TOKEN_PARENT_NOTIFY:
+ parser.ScanStr((char *)params, "%b", &_parentNotify);
+ break;
+
+ case TOKEN_PAUSE_MUSIC:
+ parser.ScanStr((char *)params, "%b", &_pauseMusic);
+ break;
+
+ case TOKEN_DISABLED:
+ parser.ScanStr((char *)params, "%b", &_disable);
+ break;
+
+ case TOKEN_VISIBLE:
+ parser.ScanStr((char *)params, "%b", &_visible);
+ break;
+
+ case TOKEN_MENU:
+ parser.ScanStr((char *)params, "%b", &_isMenu);
+ break;
+
+ case TOKEN_IN_GAME:
+ parser.ScanStr((char *)params, "%b", &_inGame);
+ break;
+
+ case TOKEN_CLIP_CONTENTS:
+ parser.ScanStr((char *)params, "%b", &_clipContents);
+ break;
+
+ case TOKEN_FADE_COLOR:
+ parser.ScanStr((char *)params, "%d,%d,%d", &FadeR, &FadeG, &FadeB);
+ _fadeBackground = true;
+ break;
+
+ case TOKEN_FADE_ALPHA:
+ parser.ScanStr((char *)params, "%d", &FadeA);
+ _fadeBackground = true;
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ ParseEditorProperty(params, false);
+ break;
+
+ case TOKEN_ALPHA_COLOR:
+ parser.ScanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab);
+ break;
+
+ case TOKEN_ALPHA:
+ parser.ScanStr((char *)params, "%d", &alpha);
+ break;
+
+
+ default:
+ if (FAILED(Game->WindowLoadHook(this, (char **)&Buffer, (char **)params))) {
+ cmd = PARSERR_GENERIC;
+ }
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ Game->LOG(0, "Syntax error in WINDOW definition");
+ return E_FAIL;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ Game->LOG(0, "Error loading WINDOW definition");
+ return E_FAIL;
+ }
+
+ CorrectSize();
+
+ if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) {
+ ar = ag = ab = 255;
+ }
+ _alphaColor = DRGBA(ar, ag, ab, alpha);
+
+ if (_fadeBackground) _fadeColor = DRGBA(FadeR, FadeG, FadeB, FadeA);
+
+ _focusedWidget = NULL;
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::SaveAsText(CBDynBuffer *Buffer, int Indent) {
+ Buffer->PutTextIndent(Indent, "WINDOW\n");
+ Buffer->PutTextIndent(Indent, "{\n");
+
+ Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", _name);
+ Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption());
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (_back && _back->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK=\"%s\"\n", _back->_filename);
+ if (_backInactive && _backInactive->_filename)
+ Buffer->PutTextIndent(Indent + 2, "BACK_INACTIVE=\"%s\"\n", _backInactive->_filename);
+
+ if (_image && _image->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE=\"%s\"\n", _image->_filename);
+ if (_imageInactive && _imageInactive->_filename)
+ Buffer->PutTextIndent(Indent + 2, "IMAGE_INACTIVE=\"%s\"\n", _imageInactive->_filename);
+
+ if (_font && _font->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT=\"%s\"\n", _font->_filename);
+ if (_fontInactive && _fontInactive->_filename)
+ Buffer->PutTextIndent(Indent + 2, "FONT_INACTIVE=\"%s\"\n", _fontInactive->_filename);
+
+ if (_cursor && _cursor->_filename)
+ Buffer->PutTextIndent(Indent + 2, "CURSOR=\"%s\"\n", _cursor->_filename);
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (_text)
+ Buffer->PutTextIndent(Indent + 2, "TITLE=\"%s\"\n", _text);
+
+ switch (_titleAlign) {
+ case TAL_LEFT:
+ Buffer->PutTextIndent(Indent + 2, "TITLE_ALIGN=\"%s\"\n", "left");
+ break;
+ case TAL_RIGHT:
+ Buffer->PutTextIndent(Indent + 2, "TITLE_ALIGN=\"%s\"\n", "right");
+ break;
+ case TAL_CENTER:
+ Buffer->PutTextIndent(Indent + 2, "TITLE_ALIGN=\"%s\"\n", "center");
+ break;
+ default:
+ error("UIWindow::SaveAsText - Unhandled enum-value NUM_TEXT_ALIGN");
+ }
+
+ if (!CBPlatform::IsRectEmpty(&_titleRect)) {
+ Buffer->PutTextIndent(Indent + 2, "TITLE_RECT { %d, %d, %d, %d }\n", _titleRect.left, _titleRect.top, _titleRect.right, _titleRect.bottom);
+ }
+
+ if (!CBPlatform::IsRectEmpty(&_dragRect)) {
+ Buffer->PutTextIndent(Indent + 2, "DRAG_RECT { %d, %d, %d, %d }\n", _dragRect.left, _dragRect.top, _dragRect.right, _dragRect.bottom);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ Buffer->PutTextIndent(Indent + 2, "X=%d\n", _posX);
+ Buffer->PutTextIndent(Indent + 2, "Y=%d\n", _posY);
+ Buffer->PutTextIndent(Indent + 2, "WIDTH=%d\n", _width);
+ Buffer->PutTextIndent(Indent + 2, "HEIGHT=%d\n", _height);
+
+ Buffer->PutTextIndent(Indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE");
+
+ Buffer->PutTextIndent(Indent + 2, "TRANSPARENT=%s\n", _transparent ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "PAUSE_MUSIC=%s\n", _pauseMusic ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "MENU=%s\n", _isMenu ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "IN_GAME=%s\n", _inGame ? "TRUE" : "FALSE");
+ Buffer->PutTextIndent(Indent + 2, "CLIP_CONTENTS=%s\n", _clipContents ? "TRUE" : "FALSE");
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ if (_fadeBackground) {
+ Buffer->PutTextIndent(Indent + 2, "FADE_COLOR { %d, %d, %d }\n", D3DCOLGetR(_fadeColor), D3DCOLGetG(_fadeColor), D3DCOLGetB(_fadeColor));
+ Buffer->PutTextIndent(Indent + 2, "FADE_ALPHA=%d\n", D3DCOLGetA(_fadeColor));
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "ALPHA_COLOR { %d, %d, %d }\n", D3DCOLGetR(_alphaColor), D3DCOLGetG(_alphaColor), D3DCOLGetB(_alphaColor));
+ Buffer->PutTextIndent(Indent + 2, "ALPHA=%d\n", D3DCOLGetA(_alphaColor));
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // scripts
+ for (int i = 0; i < _scripts.GetSize(); i++) {
+ Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
+ }
+
+ Buffer->PutTextIndent(Indent + 2, "\n");
+
+ // editor properties
+ CBBase::SaveAsText(Buffer, Indent + 2);
+
+ // controls
+ for (int i = 0; i < _widgets.GetSize(); i++)
+ _widgets[i]->SaveAsText(Buffer, Indent + 2);
+
+
+ Buffer->PutTextIndent(Indent, "}\n");
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::EnableWidget(const char *Name, bool Enable) {
+ for (int i = 0; i < _widgets.GetSize(); i++) {
+ if (scumm_stricmp(_widgets[i]->_name, Name) == 0) _widgets[i]->_disable = !Enable;
+ }
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::ShowWidget(const char *Name, bool Visible) {
+ for (int i = 0; i < _widgets.GetSize(); i++) {
+ if (scumm_stricmp(_widgets[i]->_name, Name) == 0) _widgets[i]->_visible = Visible;
+ }
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name) {
+ //////////////////////////////////////////////////////////////////////////
+ // GetWidget / GetControl
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "GetWidget") == 0 || strcmp(Name, "GetControl") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *val = Stack->Pop();
+ if (val->GetType() == VAL_INT) {
+ int widget = val->GetInt();
+ if (widget < 0 || widget >= _widgets.GetSize()) Stack->PushNULL();
+ else Stack->PushNative(_widgets[widget], true);
+ } else {
+ for (int i = 0; i < _widgets.GetSize(); i++) {
+ if (scumm_stricmp(_widgets[i]->_name, val->GetString()) == 0) {
+ Stack->PushNative(_widgets[i], true);
+ return S_OK;
+ }
+ }
+ Stack->PushNULL();
+ }
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetInactiveFont
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetInactiveFont") == 0) {
+ Stack->CorrectParams(1);
+
+ if (_fontInactive) Game->_fontStorage->RemoveFont(_fontInactive);
+ _fontInactive = Game->_fontStorage->AddFont(Stack->Pop()->GetString());
+ Stack->PushBool(_fontInactive != NULL);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetInactiveImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SetInactiveImage") == 0) {
+ Stack->CorrectParams(1);
+
+ delete _imageInactive;
+ _imageInactive = new CBSprite(Game);
+ const char *Filename = Stack->Pop()->GetString();
+ if (!_imageInactive || FAILED(_imageInactive->LoadFile(Filename))) {
+ delete _imageInactive;
+ _imageInactive = NULL;
+ Stack->PushBool(false);
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetInactiveImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetInactiveImage") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imageInactive || !_imageInactive->_filename) Stack->PushNULL();
+ else Stack->PushString(_imageInactive->_filename);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetInactiveImageObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GetInactiveImageObject") == 0) {
+ Stack->CorrectParams(0);
+ if (!_imageInactive) Stack->PushNULL();
+ else Stack->PushNative(_imageInactive, true);
+
+ return S_OK;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Close
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Close") == 0) {
+ Stack->CorrectParams(0);
+ Stack->PushBool(SUCCEEDED(Close()));
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GoExclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GoExclusive") == 0) {
+ Stack->CorrectParams(0);
+ GoExclusive();
+ Script->WaitFor(this);
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GoSystemExclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "GoSystemExclusive") == 0) {
+ Stack->CorrectParams(0);
+ GoSystemExclusive();
+ Script->WaitFor(this);
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Center
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Center") == 0) {
+ Stack->CorrectParams(0);
+ _posX = (Game->_renderer->_width - _width) / 2;
+ _posY = (Game->_renderer->_height - _height) / 2;
+ Stack->PushNULL();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LoadFromFile
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "LoadFromFile") == 0) {
+ Stack->CorrectParams(1);
+
+ CScValue *Val = Stack->Pop();
+ Cleanup();
+ if (!Val->IsNULL()) {
+ Stack->PushBool(SUCCEEDED(LoadFile(Val->GetString())));
+ } else Stack->PushBool(true);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateButton
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CreateButton") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ CUIButton *Btn = new CUIButton(Game);
+ if (!Val->IsNULL()) Btn->SetName(Val->GetString());
+ Stack->PushNative(Btn, true);
+
+ Btn->_parent = this;
+ _widgets.Add(Btn);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateStatic
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CreateStatic") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ CUIText *Sta = new CUIText(Game);
+ if (!Val->IsNULL()) Sta->SetName(Val->GetString());
+ Stack->PushNative(Sta, true);
+
+ Sta->_parent = this;
+ _widgets.Add(Sta);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateEditor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CreateEditor") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ CUIEdit *Edi = new CUIEdit(Game);
+ if (!Val->IsNULL()) Edi->SetName(Val->GetString());
+ Stack->PushNative(Edi, true);
+
+ Edi->_parent = this;
+ _widgets.Add(Edi);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateWindow
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "CreateWindow") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *Val = Stack->Pop();
+
+ CUIWindow *Win = new CUIWindow(Game);
+ if (!Val->IsNULL()) Win->SetName(Val->GetString());
+ Stack->PushNative(Win, true);
+
+ Win->_parent = this;
+ _widgets.Add(Win);
+
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DeleteControl / DeleteButton / DeleteStatic / DeleteEditor / DeleteWindow
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "DeleteControl") == 0 || strcmp(Name, "DeleteButton") == 0 || strcmp(Name, "DeleteStatic") == 0 || strcmp(Name, "DeleteEditor") == 0 || strcmp(Name, "DeleteWindow") == 0) {
+ Stack->CorrectParams(1);
+ CScValue *val = Stack->Pop();
+ CUIObject *obj = (CUIObject *)val->GetNative();
+
+ for (int i = 0; i < _widgets.GetSize(); i++) {
+ if (_widgets[i] == obj) {
+ delete _widgets[i];
+ _widgets.RemoveAt(i);
+ if (val->GetType() == VAL_VARIABLE_REF) val->SetNULL();
+ }
+ }
+ Stack->PushNULL();
+ return S_OK;
+ } else if SUCCEEDED(Game->WindowScriptMethodHook(this, Script, Stack, Name)) return S_OK;
+
+ else return CUIObject::ScCallMethod(Script, Stack, ThisStack, Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+CScValue *CUIWindow::ScGetProperty(const char *Name) {
+ _scValue->SetNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Type") == 0) {
+ _scValue->SetString("window");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NumWidgets / NumControls (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "NumWidgets") == 0 || strcmp(Name, "NumControls") == 0) {
+ _scValue->SetInt(_widgets.GetSize());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Exclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Exclusive") == 0) {
+ _scValue->SetBool(_mode == WINDOW_EXCLUSIVE);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SystemExclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SystemExclusive") == 0) {
+ _scValue->SetBool(_mode == WINDOW_SYSTEM_EXCLUSIVE);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Menu
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Menu") == 0) {
+ _scValue->SetBool(_isMenu);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // InGame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "InGame") == 0) {
+ _scValue->SetBool(_inGame);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PauseMusic
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "PauseMusic") == 0) {
+ _scValue->SetBool(_pauseMusic);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ClipContents
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "ClipContents") == 0) {
+ _scValue->SetBool(_clipContents);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Transparent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Transparent") == 0) {
+ _scValue->SetBool(_transparent);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeColor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "FadeColor") == 0) {
+ _scValue->SetInt((int)_fadeColor);
+ return _scValue;
+ }
+
+ else return CUIObject::ScGetProperty(Name);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::ScSetProperty(const char *Name, CScValue *Value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(Name, "Name") == 0) {
+ SetName(Value->GetString());
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Menu
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Menu") == 0) {
+ _isMenu = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // InGame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "InGame") == 0) {
+ _inGame = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PauseMusic
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "PauseMusic") == 0) {
+ _pauseMusic = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ClipContents
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "ClipContents") == 0) {
+ _clipContents = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Transparent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Transparent") == 0) {
+ _transparent = Value->GetBool();
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeColor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "FadeColor") == 0) {
+ _fadeColor = (uint32)Value->GetInt();
+ _fadeBackground = (_fadeColor != 0);
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Exclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "Exclusive") == 0) {
+ if (Value->GetBool())
+ GoExclusive();
+ else {
+ Close();
+ _visible = true;
+ }
+ return S_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SystemExclusive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(Name, "SystemExclusive") == 0) {
+ if (Value->GetBool())
+ GoSystemExclusive();
+ else {
+ Close();
+ _visible = true;
+ }
+ return S_OK;
+ }
+
+ else return CUIObject::ScSetProperty(Name, Value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *CUIWindow::ScToString() {
+ return "[window]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CUIWindow::HandleKeypress(SDL_Event *event) {
+//TODO
+#if 0
+ if (event->type == SDL_KEYDOWN && event->key.keysym.scancode == SDL_SCANCODE_TAB) {
+ return SUCCEEDED(MoveFocus(!CBKeyboardState::IsShiftDown()));
+ } else {
+ if (_focusedWidget) return _focusedWidget->HandleKeypress(event);
+ else return false;
+ }
+#endif
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool CUIWindow::HandleMouseWheel(int Delta) {
+ if (_focusedWidget) return _focusedWidget->HandleMouseWheel(Delta);
+ else return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::HandleMouse(TMouseEvent Event, TMouseButton Button) {
+ HRESULT res = CUIObject::HandleMouse(Event, Button);
+
+ // handle window dragging
+ if (!CBPlatform::IsRectEmpty(&_dragRect)) {
+ // start drag
+ if (Event == MOUSE_CLICK && Button == MOUSE_BUTTON_LEFT) {
+ RECT DragRect = _dragRect;
+ int OffsetX, OffsetY;
+ GetTotalOffset(&OffsetX, &OffsetY);
+ CBPlatform::OffsetRect(&DragRect, _posX + OffsetX, _posY + OffsetY);
+
+ if (CBPlatform::PtInRect(&DragRect, Game->_mousePos)) {
+ _dragFrom.x = Game->_mousePos.x;
+ _dragFrom.y = Game->_mousePos.y;
+ _dragging = true;
+ }
+ }
+ // end drag
+ else if (_dragging && Event == MOUSE_RELEASE && Button == MOUSE_BUTTON_LEFT) {
+ _dragging = false;
+ }
+ }
+
+ return res;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::Persist(CBPersistMgr *PersistMgr) {
+
+ CUIObject::Persist(PersistMgr);
+
+ PersistMgr->Transfer(TMEMBER(_backInactive));
+ PersistMgr->Transfer(TMEMBER(_clipContents));
+ PersistMgr->Transfer(TMEMBER(_dragFrom));
+ PersistMgr->Transfer(TMEMBER(_dragging));
+ PersistMgr->Transfer(TMEMBER(_dragRect));
+ PersistMgr->Transfer(TMEMBER(_fadeBackground));
+ PersistMgr->Transfer(TMEMBER(_fadeColor));
+ PersistMgr->Transfer(TMEMBER(_fontInactive));
+ PersistMgr->Transfer(TMEMBER(_imageInactive));
+ PersistMgr->Transfer(TMEMBER(_inGame));
+ PersistMgr->Transfer(TMEMBER(_isMenu));
+ PersistMgr->Transfer(TMEMBER_INT(_mode));
+ PersistMgr->Transfer(TMEMBER(_shieldButton));
+ PersistMgr->Transfer(TMEMBER(_shieldWindow));
+ PersistMgr->Transfer(TMEMBER_INT(_titleAlign));
+ PersistMgr->Transfer(TMEMBER(_titleRect));
+ PersistMgr->Transfer(TMEMBER(_transparent));
+ PersistMgr->Transfer(TMEMBER(_viewport));
+ PersistMgr->Transfer(TMEMBER(_pauseMusic));
+
+ _widgets.Persist(PersistMgr);
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::MoveFocus(bool Forward) {
+ int i;
+ bool found = false;
+ for (i = 0; i < _widgets.GetSize(); i++) {
+ if (_widgets[i] == _focusedWidget) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) _focusedWidget = NULL;
+
+ if (!_focusedWidget) {
+ if (_widgets.GetSize() > 0) i = 0;
+ else return S_OK;
+ }
+
+ int NumTries = 0;
+ bool done = false;
+
+ while (NumTries <= _widgets.GetSize()) {
+ if (_widgets[i] != _focusedWidget && _widgets[i]->_canFocus && _widgets[i]->_visible && !_widgets[i]->_disable) {
+ _focusedWidget = _widgets[i];
+ done = true;
+ break;
+ }
+
+ if (Forward) {
+ i++;
+ if (i >= _widgets.GetSize()) i = 0;
+ } else {
+ i--;
+ if (i < 0) i = _widgets.GetSize() - 1;
+ }
+ NumTries++;
+ }
+
+ return done ? S_OK : E_FAIL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::GoExclusive() {
+ if (_mode == WINDOW_EXCLUSIVE) return S_OK;
+
+ if (_mode == WINDOW_NORMAL) {
+ _ready = false;
+ _mode = WINDOW_EXCLUSIVE;
+ _visible = true;
+ _disable = false;
+ Game->FocusWindow(this);
+ return S_OK;
+ } else return E_FAIL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::GoSystemExclusive() {
+ if (_mode == WINDOW_SYSTEM_EXCLUSIVE) return S_OK;
+
+ MakeFreezable(false);
+
+ _mode = WINDOW_SYSTEM_EXCLUSIVE;
+ _ready = false;
+ _visible = true;
+ _disable = false;
+ Game->FocusWindow(this);
+
+ Game->Freeze(_pauseMusic);
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::Close() {
+ if (_mode == WINDOW_SYSTEM_EXCLUSIVE) {
+ Game->Unfreeze();
+ }
+
+ _mode = WINDOW_NORMAL;
+ _visible = false;
+ _ready = true;
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::Listen(CBScriptHolder *param1, uint32 param2) {
+ CUIObject *obj = (CUIObject *)param1;
+
+ switch (obj->_type) {
+ case UI_BUTTON:
+ if (scumm_stricmp(obj->_name, "close") == 0) Close();
+ else return CBObject::Listen(param1, param2);
+ break;
+ default:
+ return CBObject::Listen(param1, param2);
+ }
+
+ return S_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CUIWindow::MakeFreezable(bool Freezable) {
+ for (int i = 0; i < _widgets.GetSize(); i++)
+ _widgets[i]->MakeFreezable(Freezable);
+
+ CBObject::MakeFreezable(Freezable);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CUIWindow::GetWindowObjects(CBArray<CUIObject *, CUIObject *> &Objects, bool InteractiveOnly) {
+ for (int i = 0; i < _widgets.GetSize(); i++) {
+ CUIObject *Control = _widgets[i];
+ if (Control->_disable && InteractiveOnly) continue;
+
+ switch (Control->_type) {
+ case UI_WINDOW:
+ ((CUIWindow *)Control)->GetWindowObjects(Objects, InteractiveOnly);
+ break;
+
+ case UI_BUTTON:
+ case UI_EDIT:
+ Objects.Add(Control);
+ break;
+
+ default:
+ if (!InteractiveOnly) Objects.Add(Control);
+ }
+ }
+ return S_OK;
+}
+
+} // end of namespace WinterMute
diff --git a/engines/wintermute/UI/UIWindow.h b/engines/wintermute/UI/UIWindow.h
new file mode 100644
index 0000000000..510fc076b4
--- /dev/null
+++ b/engines/wintermute/UI/UIWindow.h
@@ -0,0 +1,92 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_UIWINDOW_H
+#define WINTERMUTE_UIWINDOW_H
+
+
+#include "UIObject.h"
+
+namespace WinterMute {
+
+class CUIButton;
+class CBViewport;
+class CUIWindow : public CUIObject {
+public:
+ HRESULT GetWindowObjects(CBArray<CUIObject *, CUIObject *> &Objects, bool InteractiveOnly);
+
+ bool _pauseMusic;
+ void Cleanup();
+ virtual void MakeFreezable(bool Freezable);
+ CBViewport *_viewport;
+ bool _clipContents;
+ bool _inGame;
+ bool _isMenu;
+ bool _fadeBackground;
+ uint32 _fadeColor;
+ virtual bool HandleMouseWheel(int Delta);
+ CUIWindow *_shieldWindow;
+ CUIButton *_shieldButton;
+ HRESULT Close();
+ HRESULT GoSystemExclusive();
+ HRESULT GoExclusive();
+ TWindowMode _mode;
+ HRESULT MoveFocus(bool Forward = true);
+ virtual HRESULT HandleMouse(TMouseEvent Event, TMouseButton Button);
+ POINT _dragFrom;
+ bool _dragging;
+ DECLARE_PERSISTENT(CUIWindow, CUIObject)
+ bool _transparent;
+ HRESULT ShowWidget(const char *Name, bool Visible = true);
+ HRESULT EnableWidget(const char *Name, bool Enable = true);
+ RECT _titleRect;
+ RECT _dragRect;
+ virtual HRESULT Display(int OffsetX = 0, int OffsetY = 0);
+ CUIWindow(CBGame *inGame);
+ virtual ~CUIWindow();
+ virtual bool HandleKeypress(SDL_Event *event);
+ CBArray<CUIObject *, CUIObject *> _widgets;
+ TTextAlign _titleAlign;
+ HRESULT LoadFile(const char *Filename);
+ HRESULT LoadBuffer(byte *Buffer, bool Complete = true);
+ CUITiledImage *_backInactive;
+ CBFont *_fontInactive;
+ CBSprite *_imageInactive;
+ virtual HRESULT Listen(CBScriptHolder *param1, uint32 param2);
+ virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent);
+
+ // scripting interface
+ virtual CScValue *ScGetProperty(const char *Name);
+ virtual HRESULT ScSetProperty(const char *Name, CScValue *Value);
+ virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, const char *Name);
+ virtual const char *ScToString();
+};
+
+} // end of namespace WinterMute
+
+#endif