aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile12
-rw-r--r--gui.cpp476
-rw-r--r--gui.h75
3 files changed, 553 insertions, 10 deletions
diff --git a/Makefile b/Makefile
index c073f79cea..35030e14be 100644
--- a/Makefile
+++ b/Makefile
@@ -1,12 +1,4 @@
-# $Id$
-#
-# $Log$
-# Revision 1.10 2001/11/07 10:28:33 cmatsuoka
-# Using `sdl-config --libs` as LIBS, will override for cross-build.
-#
-# Revision 1.9 2001/11/06 22:59:59 cmatsuoka
-# Re-added changes to allow cygwin and beos cross-compilation.
-#
+# $Header$
CC = gcc
CFLAGS = -g -Wno-multichar
@@ -21,7 +13,7 @@ INCS = scumm.h scummsys.h stdafx.h
OBJS = actor.o boxes.o costume.o gfx.o object.o resource.o \
saveload.o script.o scummvm.o sound.o string.o \
- sys.o verbs.o sdl.o script_v1.o script_v2.o debug.o
+ sys.o verbs.o sdl.o script_v1.o script_v2.o debug.o gui.o
DISTFILES=actor.cpp boxes.cpp costume.cpp gfx.cpp object.cpp resource.cpp \
saveload.cpp script.cpp scummvm.cpp sound.cpp string.cpp \
diff --git a/gui.cpp b/gui.cpp
new file mode 100644
index 0000000000..4960781af2
--- /dev/null
+++ b/gui.cpp
@@ -0,0 +1,476 @@
+#include "stdafx.h"
+#include "scumm.h"
+#include "gui.h"
+
+void Gui::draw(int start,int end) {
+ int i;
+
+ if (end==-1)
+ end=start;
+
+ for (i=0; i<sizeof(_widgets) / sizeof(_widgets[0]); i++) {
+ const GuiWidget *w = _widgets[i];
+ if (w) {
+ _parentX = 0;
+ _parentY = 0;
+ while (w->_type != GUI_NONE) {
+ if (w->_id>=start && w->_id<=end && (w->_page&(1<<_cur_page)) ) {
+ drawWidget(w);
+ }
+ if (w->_flags & GWF_PARENT) {
+ _parentX += w->_x;
+ _parentY += w->_y;
+ }
+ w++;
+ }
+ }
+ }
+}
+
+const GuiWidget *Gui::widgetFromPos(int x, int y) {
+ int i;
+
+ for (i=sizeof(_widgets) / sizeof(_widgets[0])-1; i>=0; i--) {
+ const GuiWidget *w = _widgets[i];
+ if (w) {
+ while (w->_type != GUI_NONE) {
+ if ((w->_page&(1<<_cur_page)) && w->_id &&
+ (uint16)(x-w->_x) < w->_w && (uint16)(y-w->_y) < w->_h)
+ return w;
+ if (w->_flags & GWF_PARENT) {
+ x -= w->_x;
+ y -= w->_y;
+ }
+ w++;
+ }
+ }
+ }
+ return NULL;
+}
+
+void Gui::drawString(const char *str, int x, int y, int w, byte color, bool center) {
+ StringTab *st = &_s->string[5];
+ st->charset = 1;
+ st->center = center;
+ st->color = color;
+ st->xpos = x;
+ st->ypos = y;
+ st->right = x + w;
+ _s->_messagePtr = (byte*)str;
+ _s->drawString(5);
+}
+
+void Gui::drawWidget(const GuiWidget *w) {
+ const char *s;
+ int x,y;
+
+ x = w->_x;
+ y = w->_y;
+
+ if (w->_flags & GWF_CLEARBG)
+ widgetClear(w);
+
+ if (w->_flags & GWF_BORDER) {
+ widgetBorder(w);
+ x += 4;
+ y += 4;
+ }
+
+ switch(w->_type) {
+ case GUI_TEXT:
+ s = queryString(w->_string_number,w->_id);
+ if (s)
+ drawString(s, x+_parentX, y+_parentY, w->_w,
+ (_clickWidget && _clickWidget==w->_id) ? _textcolorhi : _textcolor,
+ false);
+ break;
+ case GUI_IMAGE:
+ ;
+ }
+}
+
+void Gui::widgetClear(const GuiWidget *wid) {
+ int x,y,w,h;
+ int i,j;
+
+ x = wid->_x;
+ y = wid->_y;
+ w = wid->_w;
+ h = wid->_h;
+
+ byte *ptr = getBasePtr(x,y);
+ if(ptr==NULL)
+ return;
+
+ _s->setVirtscreenDirty(_vs, x+_parentX, y+_parentY, x+_parentX+w, y+_parentY+h);
+
+ if (wid->_flags & GWF_BORDER) {
+ ptr += 320 + 1;
+ w-=2;
+ h-=2;
+ }
+
+ while (--h>=0) {
+ for(i=0; i<w; i++)
+ ptr[i] = _bgcolor;
+ ptr += 320;
+ }
+}
+
+void Gui::widgetBorder(const GuiWidget *w) {
+ int x = w->_x, y = w->_y;
+ int x2 = x + w->_w-1, y2 = y + w->_h-1;
+ int i;
+ byte tmp;
+
+ hline(x+1,y,x2-1);
+ hline(x,y+1,x2);
+ vline(x,y+1,y2-1);
+ vline(x+1,y,y2);
+
+ tmp = _color;
+ _color = _shadowcolor;
+
+ hline(x+1,y2-1,x2);
+ hline(x+1,y2,x2-1);
+ vline(x2,y+1,y2-1);
+ vline(x2-1,y+1,y2);
+
+ _color = tmp;
+}
+
+void Gui::hline(int x, int y, int x2) {
+ moveto(x,y);
+ lineto(x2,y);
+}
+
+void Gui::vline(int x, int y, int y2) {
+ moveto(x,y);
+ lineto(x,y2);
+}
+
+void Gui::moveto(int x, int y) {
+ _curX = x;
+ _curY = y;
+}
+
+byte *Gui::getBasePtr(int x, int y) {
+ x += _parentX;
+ y += _parentY;
+ _vs = _s->findVirtScreen(y);
+ if (_vs==NULL)
+ return NULL;
+ return _s->getResourceAddress(rtBuffer, _vs->number+1) + x + (y-_vs->topline)*320 + _s->_screenStartStrip*8;
+}
+
+void Gui::lineto(int x, int y) {
+ byte *ptr;
+ int x2 = _curX;
+ int y2 = _curY;
+
+ _curX = x;
+ _curY = y;
+
+ if (x2 < x)
+ x2^=x^=x2^=x;
+
+ if (y2 < y)
+ y2^=y^=y2^=y;
+
+ ptr = getBasePtr(x, y);
+ if (ptr==NULL)
+ return;
+
+ if (x==x2) {
+ /* vertical line */
+ while (y++ <= y2) {
+ *ptr = _color;
+ ptr += 320;
+ }
+ } else if (y==y2) {
+ /* horizontal line */
+ while (x++ <= x2) {
+ *ptr++ = _color;
+ }
+ }
+}
+
+void Gui::leftMouseClick(int x, int y) {
+ const GuiWidget *w = widgetFromPos(x,y);
+ int old;
+
+ _clickTimer = 0;
+
+ old = _clickWidget;
+ _clickWidget = w?w->_id : 0;
+
+ if (old)
+ draw(old);
+ if (_clickWidget) {
+ draw(_clickWidget);
+ if(w->_flags&GWF_DELAY)
+ _clickTimer = 5;
+ else
+ handleCommand(_clickWidget);
+ }
+}
+
+const GuiWidget save_load_dialog[] = {
+ {GUI_STAT,0xFF,GWF_DEFAULT|GWF_PARENT,30,20,260,120,0,NULL},
+ {GUI_TEXT,0x01,0,40,5,128,16,0,1}, /* How may I serve you? */
+ {GUI_TEXT,0x02,0,40,5,128,16,0,2}, /* Select a game to LOAD */
+ {GUI_TEXT,0x04,0,40,5,128,16,0,3}, /* Name your SAVE game */
+
+ {GUI_STAT,0xFF,GWF_DEFAULT,6,16,170,96,0,0},
+ {GUI_TEXT,0x01,GWF_DEFAULT,180,20,16,40,0,0},
+ {GUI_TEXT,0x01,GWF_DEFAULT,180,66,16,40,0,0},
+ {GUI_TEXT,0xFE,GWF_DEFAULT,180,20,16,40,1,0},
+ {GUI_TEXT,0xFE,GWF_DEFAULT,180,66,16,40,2,0},
+
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,20,160,10,20,0},
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,30,160,10,21,0},
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,40,160,10,22,0},
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,50,160,10,23,0},
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,60,160,10,24,0},
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,70,160,10,25,0},
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,80,160,10,26,0},
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,90,160,10,27,0},
+ {GUI_TEXT,0x06,GWF_CLEARBG,10,100,160,10,28,0},
+
+ {GUI_TEXT,0x01,GWF_BUTTON,200,25,54,16,3,4}, /* Save */
+ {GUI_TEXT,0x01,GWF_BUTTON,200,45,54,16,4,5}, /* Load */
+ {GUI_TEXT,0x01,GWF_BUTTON,200,65,54,16,5,6}, /* Play */
+ {GUI_TEXT,0x01,GWF_BUTTON,200,85,54,16,6,8}, /* Quit */
+
+ {GUI_TEXT,0x02,GWF_BUTTON,200,50,54,16,7,7}, /* Cancel */
+
+ {GUI_TEXT,0x04,GWF_BUTTON,200,45,54,16,8,9}, /* Ok */
+ {GUI_TEXT,0x04,GWF_BUTTON,200,65,54,16,7,7}, /* Cancel */
+
+ {0}
+};
+
+void Gui::handleCommand(int cmd) {
+ int lastEdit = _editString;
+ showCaret(false);
+
+ switch(cmd) {
+ case 1: /* up button */
+ if (_slotIndex==0)
+ return;
+ getSavegameNames(_slotIndex-9);
+ draw(20,28);
+ return;
+ case 2:
+ if (_slotIndex > 80)
+ return;
+ getSavegameNames(_slotIndex+9);
+ draw(20,28);
+ return;
+ case 3: /* save button */
+ _cur_page = 2;
+ getSavegameNames(0);
+ draw(0,100);
+ return;
+ case 4: /* load button */
+ _cur_page = 1;
+ getSavegameNames(0);
+ draw(0,100);
+ return;
+ case 5: /* play button */
+ close();
+ return;
+ case 6: /* quit button */
+ exit(1);
+ return;
+ case 7: /* cancel button */
+ _cur_page = 0;
+ draw(0,100);
+ return;
+ case 8:
+ if (lastEdit==-1 || game_names[lastEdit][0]==0)
+ return;
+ _s->_saveLoadSlot = lastEdit + _slotIndex;
+ _s->_saveLoadCompatible = false;
+ _s->_saveLoadFlag = 1;
+ memcpy(_s->_saveLoadName, game_names[lastEdit], sizeof(_s->_saveLoadName));
+ close();
+ return;
+ default:
+ if (cmd>=20 && cmd<=28) {
+ if(_cur_page==1) {
+ if (valid_games[cmd-20]) {
+ _s->_saveLoadSlot = cmd-20+_slotIndex;
+ _s->_saveLoadCompatible = false;
+ _s->_saveLoadFlag = 2;
+ close();
+ }
+ return;
+ } else if (_cur_page==2) {
+ _clickWidget = cmd;
+ editString(cmd - 20);
+ }
+ }
+ }
+
+}
+
+void Gui::getSavegameNames(int start) {
+ int i;
+ _slotIndex = start;
+ for(i=0; i<9; i++,start++) {
+ valid_games[i] = _s->getSavegameName(start, game_names[i]);
+ }
+}
+
+const byte string_map_table_v6[] = {
+ 117, /* How may I serve you? */
+ 109, /* Select a game to LOAD */
+ 108, /* Name your SAVE game */
+ 96, /* Save */
+ 97, /* Load */
+ 98, /* Play */
+ 99, /* Cancel */
+ 100, /* Quit */
+ 101, /* Ok */
+};
+
+const byte string_map_table_v5[] = {
+ 0, /* How may I serve you? */
+ 20, /* Select a game to LOAD */
+ 21, /* Name your SAVE game */
+ 7, /* Save */
+ 8, /* Load */
+ 9, /* Play */
+ 10, /* Cancel */
+ 11, /* Quit */
+ 12, /* Ok */
+};
+
+const char *Gui::queryString(int string, int id) {
+ static char namebuf[64];
+ if (id>=20 && id<=28) {
+ sprintf(namebuf, "%2d. %s", id-20+_slotIndex, game_names[id-20]);
+ return namebuf;
+ }
+
+ if (_s->_majorScummVersion==6) {
+ string = _s->_vars[string_map_table_v6[string-1]];
+ } else {
+ string = string_map_table_v5[string-1];
+ }
+
+ return (char*)_s->getStringAddress(string);
+}
+
+void Gui::showCaret(bool show) {
+ int i;
+ char *s;
+
+ if (_editString==-1)
+ return;
+
+ i = _editLen;
+ s = game_names[_editString];
+
+ if (show) {
+ if (i < 31) {
+ s[i] = '_';
+ s[i+1] = 0;
+ }
+ } else {
+ s[i] = 0;
+ }
+
+ draw(_editString + 20);
+
+ if (!show)
+ _editString = -1;
+}
+
+void Gui::editString(int i) {
+ char *s = game_names[i];
+ if(!valid_games[i]) {
+ valid_games[i] = true;
+ *s = 0;
+ }
+ _editString = i;
+ _editLen = strlen(s);
+ showCaret(true);
+}
+
+void Gui::addLetter(char letter) {
+ if (_editString==-1)
+ return;
+
+ if (letter==13) {
+ handleCommand(8);
+ return;
+ }
+
+ if (letter>=32 && letter<128 && _editLen < 31) {
+ game_names[_editString][_editLen++] = letter;
+ } else if (letter==8 && _editLen>0) {
+ _editLen--;
+ }
+ showCaret(true);
+}
+
+void Gui::saveLoadDialog() {
+ _widgets[0] = save_load_dialog;
+ _editString = -1;
+ _cur_page = 0;
+ _active = 1;
+}
+
+byte Gui::getDefaultColor(int color) {
+ if (_s->_majorScummVersion == 6) {
+ if (color==8) color=1;
+ return _s->readArray(110, 0, color);
+ } else {
+ return _s->getStringAddress(21)[color];
+ }
+}
+
+
+void Gui::init(Scumm *s) {
+ _s = s;
+ _bgcolor = getDefaultColor(0);
+ _color = getDefaultColor(1);
+ _textcolor = getDefaultColor(2);
+ _textcolorhi = getDefaultColor(6);
+ _shadowcolor = getDefaultColor(8);
+}
+
+void Gui::loop() {
+ if (_active==1) {
+ _active++;
+ draw(0,100);
+ _s->_cursorAnimate++;
+ _s->gdi._cursorActive = 1;
+ }
+
+ _s->getKeyInput(0);
+ if (_s->_mouseButStat&0x8000) {
+ leftMouseClick(_s->mouse.x, _s->mouse.y);
+ } else if (_s->_lastKeyHit) {
+ addLetter(_s->_lastKeyHit);
+ }
+
+ if (_clickTimer && !--_clickTimer) {
+ int old = _clickWidget;
+ _clickWidget = 0;
+ draw(old);
+ handleCommand(old);
+ }
+
+ _s->drawDirtyScreenParts();
+ _s->_mouseButStat = 0;
+}
+
+void Gui::close() {
+ _s->_fullRedraw = true;
+ _s->_completeScreenRedraw = true;
+ _s->_cursorAnimate--;
+ _active = false;
+}
diff --git a/gui.h b/gui.h
new file mode 100644
index 0000000000..75359d789f
--- /dev/null
+++ b/gui.h
@@ -0,0 +1,75 @@
+enum {
+ GUI_NONE = 0,
+ GUI_TEXT = 1,
+ GUI_IMAGE = 2,
+ GUI_STAT = 3,
+};
+
+enum {
+ GWF_BORDER = 1,
+ GWF_CLEARBG = 2,
+ GWF_PARENT = 4,
+ GWF_DELAY = 8,
+ GWF_DEFAULT = GWF_BORDER|GWF_CLEARBG,
+ GWF_BUTTON = GWF_BORDER|GWF_CLEARBG|GWF_DELAY,
+
+};
+
+struct GuiWidget {
+ byte _type;
+ byte _page;
+ byte _flags;
+ int16 _x,_y;
+ uint16 _w,_h;
+ uint16 _id;
+ byte _string_number;
+};
+
+struct Gui {
+ Scumm *_s;
+ const GuiWidget *_widgets[4];
+ int _curX, _curY;
+ VirtScreen *_vs;
+ byte _color,_shadowcolor;
+ byte _bgcolor;
+ byte _textcolor;
+ byte _textcolorhi;
+ int _parentX, _parentY;
+ byte _active;
+ byte _clickTimer;
+ byte _cur_page;
+ int _clickWidget;
+ char *_queryMess;
+
+ /* savedialog specifics */
+ int _slotIndex;
+ int _editString;
+ int _editLen;
+ bool valid_games[9];
+ char game_names[9][32];
+ void loop();
+ void init(Scumm *s);
+ void draw(int start, int end);
+ void draw(int item) { draw(item,-1); }
+ void drawWidget(const GuiWidget *w);
+ void moveto(int x, int y);
+ void lineto(int x, int y);
+ void hline(int x, int y, int x2);
+ void vline(int x, int y, int y2);
+ void drawString(const char *str, int x, int y, int w, byte color, bool center);
+ void widgetClear(const GuiWidget *w);
+ void widgetBorder(const GuiWidget *w);
+ byte *getBasePtr(int x, int y);
+ const GuiWidget *widgetFromPos(int x, int y);
+ void leftMouseClick(int x, int y);
+ void handleCommand(int cmd);
+ void close();
+ const char *queryString(int string, int id);
+ void getSavegameNames(int start);
+ void editString(int index);
+ void showCaret(bool show);
+ void addLetter(char letter);
+ void saveLoadDialog();
+ void queryMessage(const char *msg, const char *alts);
+ byte getDefaultColor(int color);
+};