diff --git a/src/libs/gui_tk/Doxyfile b/src/libs/gui_tk/Doxyfile
new file mode 100644
index 00000000..598d6fef
--- /dev/null
+++ b/src/libs/gui_tk/Doxyfile
@@ -0,0 +1,238 @@
+# Doxyfile 1.5.2
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = gui::tk
+PROJECT_NUMBER = "Version 1.0"
+OUTPUT_DIRECTORY =
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = .
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+BUILTIN_STL_SUPPORT = YES
+CPP_CLI_SUPPORT = NO
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = YES
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = NO
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = .
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS = gui_tk.h \
+ gui_tk.cpp
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE =
+HHC_LOCATION =
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED = TESTING SDL_MAJOR_VERSION
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE = DOSBox.tag
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = YES
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = YES
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = YES
+CALLER_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+DOT_TRANSPARENT = YES
+DOT_MULTI_TARGETS = YES
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/src/libs/gui_tk/Makefile.am b/src/libs/gui_tk/Makefile.am
new file mode 100644
index 00000000..de7764ed
--- /dev/null
+++ b/src/libs/gui_tk/Makefile.am
@@ -0,0 +1,4 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include
+
+noinst_LIBRARIES = libgui_tk.a
+libgui_tk_a_SOURCES = gui_tk.cpp gui_tk.h
diff --git a/src/libs/gui_tk/gui_tk.cpp b/src/libs/gui_tk/gui_tk.cpp
new file mode 100644
index 00000000..8cbe59d6
--- /dev/null
+++ b/src/libs/gui_tk/gui_tk.cpp
@@ -0,0 +1,1705 @@
+/*
+ * gui_tk - framework-agnostic GUI toolkit
+ * Copyright (C) 2005-2007 Jörg Walter
+ *
+ * gui_tk 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gui_tk 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, see
+ */
+
+/* TODO:
+ - make menu a bufferedwindow with shadow
+*/
+/* $Id: gui_tk.cpp,v 1.1 2007-10-28 16:33:02 qbix79 Exp $ */
+
+/** \file
+ * \brief Implementation file for gui_tk.
+ *
+ * It contains implementations for all non-inlined class methods.
+ *
+ * Also contained is a small test program that demonstrates all features of
+ * gui_tk. It is enabled by defining the preprocessor macro TESTING.
+ */
+
+#include
+#include "gui_tk.h"
+
+namespace GUI {
+
+namespace Color {
+
+RGB Background3D = 0xffc0c0c0;
+
+RGB Light3D = 0xfffcfcfc;
+
+RGB Shadow3D = 0xff808080;
+
+RGB Border = 0xff000000;
+
+RGB Text = 0xff000000;
+
+RGB Background = 0xffc0c0c0;
+
+RGB SelectionBackground = 0xff000080;
+
+RGB SelectionForeground = 0xffffffff;
+
+RGB EditableBackground = 0xffffffff;
+
+RGB Titlebar = 0xff000080;
+
+RGB TitlebarText = 0xffffffff;
+
+}
+
+void Drawable::drawText(const String& text, bool interpret, Size start, Size len) {
+ if (interpret) {
+ if (len > text.size()-start) len = text.size()-start;
+ len += start;
+
+ Size wordstart = start;
+ int width = 0;
+
+ while (start < len) {
+ switch (font->toSpecial(text[start])) {
+ case Font::CR:
+ if (wordstart != start) {
+ drawText(text,false,wordstart,start-wordstart);
+ wordstart = start;
+ width = 0;
+ }
+ wordstart++;
+ gotoXY(0,y);
+ break;
+ case Font::LF:
+ if (wordstart != start) {
+ drawText(text,false,wordstart,start-wordstart);
+ wordstart = start;
+ width = 0;
+ }
+ wordstart++;
+ gotoXY(0,y+font->getHeight());
+ break;
+ case Font::BS:
+ if (wordstart != start) {
+ drawText(text,false,wordstart,start-wordstart);
+ wordstart = start;
+ width = 0;
+ }
+ wordstart++;
+ gotoXY(imax(0,x-font->getWidth()),y);
+ break;
+ case Font::Tab:
+ if (wordstart != start) {
+ drawText(text,false,wordstart,start-wordstart);
+ wordstart = start;
+ width = 0;
+ }
+ wordstart++;
+ gotoXY((((int)(x/font->getWidth()/8))+1)*8*font->getWidth(),y);
+ break;
+ case Font::Space:
+ if (wordstart != start) {
+ drawText(text,false,wordstart,start-wordstart);
+ wordstart = start;
+ width = 0;
+ }
+ wordstart++;
+ font->drawString(this,text,start,1);
+ break;
+ case Font::ESC: // ignore ANSI sequences except for colors
+ if (wordstart != start) {
+ drawText(text,false,wordstart,start-wordstart);
+ wordstart = start;
+ width = 0;
+ }
+ wordstart++;
+ do {
+ int seqstart = start+1;
+ Char c;
+ do {
+ start++;
+ wordstart++;
+ c = font->toSpecial(text[start]);
+ } while (start < len && ((c >= '0' && c <= '9') || c == ';' || c == '['));
+ if (c == 'm' && start < len) {
+ if (font->toSpecial(text[seqstart++]) != '[') break;
+ c = font->toSpecial(text[seqstart++]);
+ while (c != 'm') {
+ int param = 0;
+ if (c == ';') c = '0';
+ while (c != 'm' && c != ';') {
+ param = param * 10 + c-'0';
+ c = font->toSpecial(text[seqstart++]);
+ }
+ const RGB bright = 0x00808080;
+ const RGB intensity = (color&bright?~0:~bright);
+ switch (param) {
+ case 0: setColor(Color::Black); break;
+ case 1: setColor(color | 0x00808080); break;
+ case 30: setColor(Color::Black|bright & intensity); break;
+ case 31: setColor(Color::Red & intensity); break;
+ case 32: setColor(Color::Green & intensity); break;
+ case 33: setColor(Color::Yellow & intensity); break;
+ case 34: setColor(Color::Blue & intensity); break;
+ case 35: setColor(Color::Magenta & intensity); break;
+ case 36: setColor(Color::Cyan & intensity); break;
+ case 37: setColor(Color::White & intensity); break;
+ default: break;
+ }
+ }
+ }
+ } while (0);
+ default:
+ width += font->getWidth(text[start]);
+ if (x > 0 && x+width > cw) gotoXY(0,y+font->getHeight());
+ }
+ start++;
+ }
+ if (wordstart != start) drawText(text,false,wordstart,start-wordstart);
+ return;
+ }
+
+ font->drawString(this,text,start,len);
+}
+
+bool ToplevelWindow::mouseDown(int x, int y, MouseButton button) {
+ if (button == Left && x > 32 && x < width-6 && y > 4 && y < 31) {
+ dragx = x;
+ dragy = y;
+ mouseChild = NULL;
+ systemMenu->setVisible(false);
+ return true;
+ } else if (button == Left && x < 32 && x > 6 && y > 4 && y < 31) {
+ mouseChild = NULL;
+ raise();
+ systemMenu->setVisible(!systemMenu->isVisible());
+ return true;
+ }
+ systemMenu->setVisible(false);
+ BorderedWindow::mouseDown(x,y,button);
+ return true;
+}
+
+Drawable::Drawable(int w, int h, RGB clear) :
+ buffer(new RGB[w*h]),
+ width(w), height(h),
+ owner(true),
+ color(Color::Black),
+ font(NULL),
+ lineWidth(1),
+ tx(0), ty(0),
+ cx(0), cy(0),
+ cw(w), ch(h),
+ x(0), y(0)
+{
+ this->clear(clear);
+}
+
+Drawable::Drawable(Drawable &src, RGB clear) :
+ buffer(new RGB[src.cw*src.ch]),
+ width(src.cw), height(src.ch),
+ owner(true),
+ color(src.color),
+ font(src.font),
+ lineWidth(src.lineWidth),
+ tx(0), ty(0),
+ cx(0), cy(0),
+ cw(src.cw), ch(src.ch),
+ x(src.x), y(src.y)
+{
+ if (clear != 0) {
+ this->clear(clear);
+ } else {
+ for (int h = 0; h < src.ch; h++) {
+ memcpy(buffer+src.cw*h,src.buffer+src.width*(h+src.ty)+src.tx,4*src.cw);
+ }
+ }
+}
+
+Drawable::Drawable(Drawable &src, int x, int y, int w, int h) :
+ buffer(src.buffer),
+ width(src.width), height(src.height),
+ owner(false),
+ color(src.color),
+ font(src.font),
+ lineWidth(src.lineWidth),
+ tx(src.tx+x), ty(src.ty+y),
+ cx(imax(imax(-x,src.cx-x),0)), cy(imax(imax(-y,src.cy-y),0)),
+ cw(imax(0,imin(src.cw-x,w))), ch(imax(0,imin(src.ch-y,h))),
+ x(imax(0,imin(src.tx-tx,cw))), y(imax(0,imin(src.ty-ty,cw)))
+{
+}
+
+Drawable::~Drawable()
+{
+ if (owner) delete[] buffer;
+}
+
+void Drawable::clear(RGB clear)
+{
+ for (int y = cy; y < ch; y++) {
+ for (int x = cx; x < cw; x++) {
+ buffer[(y+ty)*width+x+tx] = clear;
+ }
+ }
+}
+
+void Drawable::drawLine(int x2, int y2)
+{
+ int x0 = x2, x1 = x, y0 = y2, y1 = y;
+ int dx = x2-x1, dy = y2-y1;
+ drawPixel();
+
+ if (abs(dx) > abs(dy)) {
+ if (x1 > x2) {
+ x = x2; x2 = x1; x1 = x;
+ y = y2; y2 = y1; y1 = y;
+ }
+ for (x = x1; x <= x2; x++) {
+ y = y1+(x-x1)*dy/dx-lineWidth/2;
+ for (int i = 0; i < lineWidth; i++, y++) {
+ drawPixel();
+ }
+ }
+ } else if (y1 != y2) {
+ if (y1 > y2) {
+ x = x2; x2 = x1; x1 = x;
+ y = y2; y2 = y1; y1 = y;
+ }
+ for (y = y1; y <= y2; y ++) {
+ x = x1+(y-y1)*dx/dy-lineWidth/2;
+ for (int i = 0; i < lineWidth; i++, x++) {
+ drawPixel();
+ }
+ }
+ }
+
+ drawPixel(x0,y0);
+}
+
+void Drawable::drawCircle(int d) {
+ int xo = 0, yo = d/2, rest = (d+1)/2-yo, x0 = x, y0 = y, rsq = d*d/4, lwo = lineWidth/2;
+
+ while (xo <= yo) {
+ while (xo*xo+(2*yo-1)*(2*yo-1)/4 > rsq) yo--;
+ for (int i = 0, yow = yo+lwo; i < lineWidth; i++, yow--) {
+ drawPixel(x0+xo,y0-yow-rest);
+ drawPixel(x0+yow,y0-xo-rest);
+ drawPixel(x0+yow,y0+xo);
+ drawPixel(x0+xo,y0+yow);
+
+ drawPixel(x0-xo-rest,y0-yow-rest);
+ drawPixel(x0-yow-rest,y0-xo-rest);
+ drawPixel(x0-yow-rest,y0+xo);
+ drawPixel(x0-xo-rest,y0+yow);
+ }
+
+ xo++;
+ }
+ gotoXY(x0,y0);
+}
+
+void Drawable::drawRect(int w, int h)
+{
+ gotoXY(x-lineWidth/2,y);
+ drawLine(x+w+lineWidth-1,y);
+ gotoXY(x-(lineWidth-1)/2,y);
+ drawLine(x,y+h);
+ gotoXY(x+(lineWidth-1)/2,y);
+ drawLine(x-w-lineWidth+1,y);
+ gotoXY(x+lineWidth/2,y);
+ drawLine(x,y-h);
+}
+
+void Drawable::fill()
+{
+ int x0 = x, xmin;
+ RGB color = getPixel();
+
+ if (color == this->color) return;
+
+ for (x--; x >= 0 && getPixel() == color; x--) drawPixel();
+ xmin = ++x;
+ for (x = x0; x < cw && getPixel() == color; x++) drawPixel();
+ y++;
+ for (x--; x >= xmin; x--) {
+ if (getPixel() == color) fill();
+ y -= 2;
+ if (getPixel() == color) fill();
+ y += 2;
+ }
+ y--;
+ x = x0;
+}
+
+void Drawable::fillCircle(int d)
+{
+ int xo = 0, yo = d/2, rest = (d+1)/2-yo, x0 = x, y0 = y, rsq = d*d/4;
+
+ while (xo <= yo) {
+ while (xo*xo+(2*yo-1)*(2*yo-1)/4 > rsq) yo--;
+ x = x0+xo;
+ for (y = y0-yo-rest; y <= y0+yo; y++) drawPixel();
+ x = x0-xo-rest;
+ for (y = y0-yo-rest; y <= y0+yo; y++) drawPixel();
+
+ y = y0-xo-rest;
+ for (x = x0-yo-rest; x <= x0+yo; x++) drawPixel();
+ y = y0+xo;
+ for (x = x0-yo-rest; x <= x0+yo; x++) drawPixel();
+
+ xo++;
+ }
+ gotoXY(x0,y0);
+}
+
+void Drawable::fillRect(int w, int h)
+{
+ int x0 = x, y0 = y, w0 = w;
+ for (; h > 0; h--, y++) {
+ for (x = x0, w = w0; w > 0; w--, x++) {
+ drawPixel();
+ }
+ }
+ gotoXY(x0,y0);
+}
+
+void Drawable::drawDrawable(Drawable &d, unsigned char alpha)
+{
+ int scw = d.cw, sch = d.ch, w, h;
+ RGB *src, *dest;
+
+ for (h = imax(d.cy,-ty-y); h < sch && y+h < ch; h++) {
+ src = d.buffer+d.width*(h+d.ty)+d.tx;
+ dest = buffer+width*(y+ty+h)+tx+x;
+ for (w = imax(d.cx,-tx-x); w < scw && x+w < cw; w++) {
+ RGB srcb = src[w], destb = dest[w];
+ unsigned int sop = Color::A(srcb)*((unsigned int)alpha)/255;
+ unsigned int rop = Color::A(destb) + sop - Color::A(destb)*sop/255;
+ if (rop == 0) {
+ dest[w] = Color::Transparent;
+ } else {
+ unsigned int dop = Color::A(destb)*(255-sop)/255;
+ unsigned int magval = ((destb&Color::MagentaMask)*dop+(srcb&Color::MagentaMask)*sop);
+ dest[w] = (((magval&0xffff)/rop)&Color::BlueMask) |
+ (((magval&0xffff0000)/rop)&Color::RedMask) |
+ ((((destb&Color::GreenMask)*dop+(srcb&Color::GreenMask)*sop)/rop)&Color::GreenMask) |
+ (rop<toSpecial(c)) {
+ case Font::CR: gotoXY(0,y); return;
+ case Font::LF: gotoXY(0,y+font->getHeight()); return;
+ case Font::BS: gotoXY(imax(0,x-font->getWidth()),y); return;
+ case Font::Tab: gotoXY((((int)(x/font->getWidth()/8))+1)*8*font->getWidth(),y); return;
+ default: break;
+ }
+ if (font->getWidth(c)+x > cw) gotoXY(0,y+font->getHeight());
+ }
+ font->drawChar(this,c);
+}
+
+#define move(x) (ptr += ((x)+bit)/8-(((x)+bit)<0), bit = ((x)+bit+(((x)+bit)<0?8:0))%8)
+void BitmapFont::drawChar(Drawable *d, const Char c) const {
+ const unsigned char *ptr = bitmap;
+ int bit = 0;
+
+ if (c > last) return;
+
+ if (char_position != NULL) {
+ ptr = char_position[c];
+ bit = 0;
+ } else {
+ move(character_step*c);
+ }
+
+ int rs = row_step;
+ int w = (widths != NULL?widths[c]:width);
+ int h = (ascents != NULL?ascents[c]:height);
+ Drawable out(*d,d->getX(),d->getY()-ascent,w,h);
+
+ if (rs == 0) rs = isign(col_step)*w;
+ if (rs < 0) move(-rs*(h-1));
+ if (col_step < 0) move(abs(rs)-1);
+
+ for (int row = height-h; row < height; row++, move(rs-w*col_step)) {
+ for (int col = 0; col < w; col++, move(col_step)) {
+ if (!background_set ^ !(*ptr&(1<gotoXY(d->getX()+w,d->getY());
+}
+#undef move
+
+std::map Font::registry;
+
+void Timer::check(unsigned int ticks)
+{
+ if (timers.empty()) return;
+
+ if (Timer::ticks > (Timer::ticks+ticks)) {
+ ticks -= -1-Timer::ticks;
+ check(-1-Timer::ticks);
+ }
+
+ std::multimap::iterator old, i = timers.lower_bound(Timer::ticks+1);
+ Timer::ticks += ticks;
+
+ while (i != timers.end() && (*i).first <= Timer::ticks) {
+ Timer_Callback *c = (*i).second;
+ unsigned int time = (*i).first;
+ old = i;
+ ++i;
+ timers.erase(old);
+ unsigned int next = c->timerExpired(time);
+ if (next) add(c, time+next-Timer::ticks);
+ }
+}
+
+void Timer::remove(const Timer_Callback *const timer)
+{
+ if (timers.empty()) return;
+
+ std::multimap::iterator old, i = timers.begin();
+
+ while (i != timers.end()) {
+ old = i;
+ ++i;
+ if ((*old).second == timer) timers.erase(old);
+ }
+}
+
+unsigned int Timer::next()
+{
+ if (timers.empty()) return 0;
+
+ std::multimap::iterator i = timers.upper_bound(ticks);
+
+ if (i == timers.end()) return 0;
+ return (*i).first-Timer::ticks;
+}
+
+std::multimap Timer::timers;
+unsigned int Timer::ticks = 0;
+
+BitmapFont::BitmapFont(const unsigned char *data, int height, int ascent, bool owner,
+ int width, bool background_set,
+ int col_step, int row_step, int character_step, Char last,
+ const int *widths, const int *ascents, const unsigned char *const* char_position,
+ const Font::SpecialChar *special) :
+ bitmap(data),
+ width(width), height(height), ascent(ascent), widths(widths), ascents(ascents),
+ background_set(background_set), col_step(col_step), row_step(row_step),
+ character_step(character_step?character_step:abs((row_step?row_step:width*col_step)*height)),
+ char_position(char_position), special(special), owner(owner), last(last)
+{
+}
+
+BitmapFont::~BitmapFont() {
+ if (owner) {
+ if (bitmap != NULL) delete bitmap;
+ if (ascents != NULL) delete ascents;
+ if (widths != NULL) delete widths;
+ if (special != NULL) delete special;
+ }
+}
+
+Window::Window(Window *parent, int x, int y, int w, int h) :
+ width(w), height(h),
+ x(x), y(y),
+ dirty(true),
+ visible(true),
+ parent(parent),
+ mouseChild(NULL)
+{
+ parent->addChild(this);
+}
+
+Window::Window() :
+ width(0), height(0),
+ x(0), y(0),
+ dirty(false),
+ visible(true),
+ parent(NULL),
+ mouseChild(NULL)
+{
+}
+
+
+Window::~Window()
+{
+ while (!children.empty()) delete children.front();
+ if (parent) parent->removeChild(this);
+ if (parent && parent->mouseChild == this) parent->mouseChild = NULL;
+}
+
+void Window::addChild(Window *child)
+{
+ children.push_back(child);
+ setDirty();
+}
+
+void Window::removeChild(Window *child)
+{
+ children.remove(child);
+ setDirty();
+}
+
+void Window::move(int x, int y)
+{
+ this->x = x;
+ this->y = y;
+ std::list::iterator i = movehandlers.begin();
+ bool end = (i == movehandlers.end());
+ while (!end) {
+ Window_Callback *c = *i;
+ ++i;
+ end = (i == movehandlers.end());
+ c->windowMoved(this,x,y);
+ }
+ parent->setDirty();
+}
+
+void Window::resize(int w, int h)
+{
+ this->width = w;
+ this->height = h;
+ setDirty();
+}
+
+void Window::paintAll(Drawable &d) const
+{
+ paint(d);
+ std::list::const_iterator i = children.begin();
+ while (i != children.end()) {
+ Window *child = *i;
+ ++i;
+ if (child->visible) {
+ Drawable *cd = new Drawable(d,child->x,child->y,child->width,child->height);
+ child->paintAll(*cd);
+ delete cd;
+ }
+ }
+}
+
+bool Window::keyDown(const Key &key)
+{
+ if (children.empty()) return false;
+ if ((*children.rbegin())->keyDown(key)) return true;
+ if (key.ctrl || key.alt || key.windows || key.special != Key::Tab) return false;
+
+ if (key.shift) {
+ std::list::reverse_iterator i = children.rbegin(), e = children.rend();
+ ++i;
+ while (i != e && !(*i)->raise()) ++i;
+ return i != e;
+ } else {
+ std::list::iterator i = children.begin(), e = children.end();
+ while (i != e && !(*i)->raise()) ++i;
+ return (i != e);
+ }
+}
+
+bool Window::keyUp(const Key &key)
+{
+ if (children.empty()) return false;
+ return (*children.rbegin())->keyUp(key);
+}
+
+bool Window::mouseMoved(int x, int y)
+{
+ std::list::reverse_iterator i = children.rbegin();
+ bool end = (i == children.rend());
+ while (!end) {
+ Window *w = *i;
+ i++;
+ end = (i == children.rend());
+ if (w->visible && x >= w->x && x <= w->x+w->width
+ && y >= w->y && y <= w->y+w->height
+ && w->mouseMoved(x-w->x, y-w->y)) return true;
+ }
+ return false;
+}
+
+bool Window::mouseDragged(int x, int y, MouseButton button)
+{
+ if (mouseChild == NULL) return false;
+ return mouseChild->mouseDragged(x-mouseChild->x, y-mouseChild->y, button);
+}
+
+bool Window::mouseDown(int x, int y, MouseButton button)
+{
+ Window *last = NULL;
+ std::list::reverse_iterator i = children.rbegin();
+ bool end = (i == children.rend());
+ while (!end) {
+ Window *w = *i;
+ i++;
+ end = (i == children.rend());
+ if (w->visible && x >= w->x && x <= w->x+w->width
+ && y >= w->y && y <= w->y+w->height
+ && (mouseChild = last = w)
+ && w->mouseDown(x-w->x, y-w->y, button)
+ && w->raise()) {
+ return true;
+ }
+ }
+ mouseChild = NULL;
+ if (last != NULL) last->raise();
+ return false;
+}
+
+bool Window::mouseUp(int x, int y, MouseButton button)
+{
+ if (mouseChild == NULL) return false;
+ return mouseChild->mouseUp(x-mouseChild->x, y-mouseChild->y, button);
+}
+
+bool Window::mouseClicked(int x, int y, MouseButton button)
+{
+ if (mouseChild == NULL) return false;
+ return mouseChild->mouseClicked(x-mouseChild->x, y-mouseChild->y, button);
+}
+
+bool Window::mouseDoubleClicked(int x, int y, MouseButton button)
+{
+ if (mouseChild == NULL) return false;
+ return mouseChild->mouseDoubleClicked(x-mouseChild->x, y-mouseChild->y, button);
+}
+
+bool BorderedWindow::mouseDown(int x, int y, MouseButton button)
+{
+ mouseChild = NULL;
+ if (x > width-border_right || y > width-border_bottom) return false;
+ x -= border_left; y -= border_top;
+ if (x < 0 || y < 0) return false;
+ return Window::mouseDown(x,y,button);
+}
+
+bool BorderedWindow::mouseMoved(int x, int y)
+{
+ if (x > width-border_right || y > width-border_bottom) return false;
+ x -= border_left; y -= border_top;
+ if (x < 0 || y < 0) return false;
+ return Window::mouseMoved(x,y);
+}
+
+bool BorderedWindow::mouseDragged(int x, int y, MouseButton button)
+{
+ if (x > width-border_right || y > width-border_bottom) return false;
+ x -= border_left; y -= border_top;
+ if (x < 0 || y < 0) return false;
+ return Window::mouseDragged(x,y,button);
+}
+
+void ToplevelWindow::paint(Drawable &d) const
+{
+ int mask = (systemMenu->isVisible()?Color::RedMask|Color::GreenMask|Color::BlueMask:0);
+ d.clear(Color::Background);
+
+ d.setColor(Color::Border);
+ d.drawLine(0,height-1,width-1,height-1);
+ d.drawLine(width-1,0,width-1,height-1);
+
+ d.setColor(Color::Shadow3D);
+ d.drawLine(0,0,width-2,0);
+ d.drawLine(0,0,0,height-2);
+ d.drawLine(0,height-2,width-2,height-2);
+ d.drawLine(width-2,0,width-2,height-2);
+
+ d.drawLine(5,4,width-7,4);
+ d.drawLine(5,4,5,30);
+
+ d.setColor(Color::Light3D);
+ d.drawLine(1,1,width-3,1);
+ d.drawLine(1,1,1,height-3);
+
+ d.drawLine(5,31,width-6,31);
+ d.drawLine(width-6,5,width-6,31);
+
+ d.setColor(Color::Background3D^mask);
+ d.fillRect(6,5,26,26);
+ d.setColor(Color::Grey50^mask);
+ d.fillRect(9,17,20,4);
+ d.setColor(Color::Black^mask);
+ d.fillRect(8,16,20,4);
+ d.setColor(Color::White^mask);
+ d.fillRect(9,17,18,2);
+
+ d.setColor(Color::Border);
+ d.drawLine(32,5,32,30);
+
+ d.setColor(Color::Titlebar);
+ d.fillRect(33,5,width-39,26);
+
+ const Font *font = Font::getFont("title");
+ d.setColor(Color::TitlebarText);
+ d.setFont(font);
+ d.drawText(31+(width-39-font->getWidth(title))/2,5+(26-font->getHeight())/2+font->getAscent(),title,false,0);
+}
+
+void Input::paint(Drawable &d) const
+{
+ d.clear(Color::EditableBackground);
+
+ d.setColor(Color::Shadow3D);
+ d.drawLine(0,0,width-2,0);
+ d.drawLine(0,0,0,height-2);
+
+ d.setColor(Color::Background3D);
+ d.drawLine(1,height-2,width-2,height-2);
+ d.drawLine(width-2,1,width-2,height-2);
+
+ d.setColor(Color::Text);
+ d.drawLine(1,1,width-3,1);
+ d.drawLine(1,1,1,height-3);
+
+ const Font *f = Font::getFont("input");
+ d.setFont(f);
+
+ Drawable d1(d,3,4,width-6,height-8);
+ Drawable dr(d1,(multi?0:-offset),(multi?-offset:0),width-6+(multi?0:offset),height-8+(multi?offset:0));
+
+ const Size start = imin(start_sel, end_sel), end = imax(start_sel, end_sel);
+ dr.drawText(0,f->getAscent()+1,text,multi,0,start);
+
+ int sx = dr.getX(), sy = dr.getY();
+ dr.drawText(text, multi, start, end-start);
+ int ex = dr.getX(), ey = dr.getY();
+
+ if (sx != ex || sy != ey) {
+ dr.setColor(Color::SelectionBackground);
+ if (sy == ey) dr.fillRect(sx,sy-f->getAscent(),ex-sx,f->getHeight()+1);
+ else {
+ dr.fillRect(sx, sy-f->getAscent(), width-sx+offset, f->getHeight() );
+ dr.fillRect(0, sy-f->getAscent()+f->getHeight(), width+offset, ey-sy-f->getHeight());
+ dr.fillRect(0, ey-f->getAscent(), ex, f->getHeight() );
+ }
+ dr.setColor(Color::SelectionForeground);
+ dr.drawText(sx, sy, text, multi, start, end-start);
+ }
+
+ dr.setColor(Color::Text);
+
+ dr.drawText(text, multi, end);
+
+ if (blink && hasFocus()) {
+ if (insert) dr.drawLine(posx,posy,posx,posy+f->getHeight()+1);
+ else dr.fillRect(posx,posy,f->getWidth(text[pos]),f->getHeight()+1);
+ }
+}
+
+Size Input::findPos(int x, int y) {
+ const Font *f = Font::getFont("input");
+ if (multi) y += offset;
+ else x += offset;
+ y = (y-4) / f->getHeight();
+ int line = 0;
+ Size pos = 0;
+ while (line < y && pos < text.size()) if (f->toSpecial(text[pos++]) == Font::LF) line++;
+ Drawable d(width-6,1);
+ d.setFont(f);
+ while (pos <= text.size() && d.getY() == 0 && x > d.getX()) {
+ d.drawText(String(text), multi, pos, 1);
+ pos++;
+ }
+ if (pos > 0) pos--;
+ return pos;
+}
+
+bool Input::mouseDown(int x, int y, MouseButton button)
+{
+ if (button == Left || (button == Middle && start_sel == end_sel)) {
+ end_sel = start_sel = pos = findPos(x,y);
+ blink = true;
+ checkOffset();
+ }
+ if (button == Middle) keyDown(Key(0,Key::Insert,true,false,false,false));
+ return true;
+}
+
+bool Input::mouseDragged(int x, int y, MouseButton button)
+{
+ if (button == Left) {
+ end_sel = pos = findPos(x,y);
+ blink = true;
+ checkOffset();
+ }
+ return true;
+}
+
+bool Input::keyDown(const Key &key)
+{
+ const Font *f = Font::getFont("input");
+ switch (key.special) {
+ case Key::None:
+ if (key.ctrl) {
+ switch (key.character) {
+ case 1:
+ case 'a':
+ case 'A':
+ if (key.shift) {
+ start_sel = end_sel = pos;
+ } else {
+ start_sel = 0;
+ pos = end_sel = text.size();
+ }
+ break;
+ case 24:
+ case 'x':
+ case 'X':
+ cutSelection();
+ break;
+ case 3:
+ case 'c':
+ case 'C':
+ copySelection();
+ break;
+ case 22:
+ case 'v':
+ case 'V':
+ pasteSelection();
+ break;
+ default: printf("Ctrl-0x%x\n",key.character); break;
+ }
+ break;
+ }
+ if (start_sel != end_sel) clearSelection();
+ if (insert || pos >= text.size() ) text.insert(text.begin()+pos++,key.character);
+ else text[pos++] = key.character;
+ break;
+ case Key::Left:
+ if (pos > 0) pos--;
+ break;
+ case Key::Right:
+ if (pos < text.size()) pos++;
+ break;
+ case Key::Down:
+ if (multi) pos = findPos(posx+3, posy-offset+f->getHeight()+4);
+ break;
+ case Key::Up:
+ if (multi) pos = findPos(posx+3, posy-offset-f->getHeight()+4);
+ break;
+ case Key::Home:
+ if (multi) {
+ while (pos > 0 && f->toSpecial(text[pos-1]) != Font::LF) pos--;
+ } else pos = 0;
+ break;
+ case Key::End:
+ if (multi) {
+ while (pos < text.size() && f->toSpecial(text[pos]) != Font::LF) pos++;
+ } else pos = text.size();
+ break;
+ case Key::Backspace:
+ if (!key.shift && start_sel != end_sel) clearSelection();
+ else if (pos > 0) text.erase(text.begin()+ --pos);
+ break;
+ case Key::Delete:
+ if (key.shift) cutSelection();
+ else if (start_sel != end_sel) clearSelection();
+ else if (pos < text.size()) text.erase(text.begin()+pos);
+ break;
+ case Key::Insert:
+ if (key.ctrl) copySelection();
+ else if (key.shift) pasteSelection();
+ else insert = !insert;
+ break;
+ case Key::Enter:
+ if (multi) {
+ if (start_sel != end_sel) clearSelection();
+ if (insert || pos >= text.size() ) text.insert(text.begin()+pos++,f->fromSpecial(Font::LF));
+ else text[pos++] = f->fromSpecial(Font::LF);
+ } else executeAction(text);
+ break;
+ case Key::Tab:
+ if (multi) {
+ if (start_sel != end_sel) clearSelection();
+ if (insert || pos >= text.size() ) text.insert(text.begin()+pos++,f->fromSpecial(Font::Tab));
+ else text[pos++] = f->fromSpecial(Font::Tab);
+ } else return false;
+ break;
+ default:
+ return false;
+ }
+ if (!key.ctrl) {
+ if (!key.shift || key.special == Key::None) start_sel = end_sel = pos;
+ else end_sel = pos;
+ }
+ checkOffset();
+ blink = true;
+ return true;
+}
+
+void BorderedWindow::paintAll(Drawable &d) const
+{
+ this->paint(d);
+ Drawable dchild(d,border_left,border_top,width-border_left-border_right,height-border_top-border_bottom);
+ for (std::list::const_iterator i = children.begin(); i != children.end(); ++i) {
+ Window *child = *i;
+ if (child->isVisible()) {
+ Drawable cd(dchild,child->getX(),child->getY(),child->getWidth(),child->getHeight());
+ child->paintAll(cd);
+ }
+ }
+}
+
+void Button::paint(Drawable &d) const
+{
+ int offset = -1;
+
+ if (hasFocus()) {
+ offset = 0;
+ d.setColor(Color::Border);
+ d.drawLine(0,0,width,0);
+ d.drawLine(0,0,0,height);
+
+ d.drawLine(0,height-1,width,height-1);
+ d.drawLine(width-1,0,width-1,height);
+ }
+
+ d.setColor(Color::Background3D);
+ d.fillRect(2,2,width-4,height-4);
+
+ if (pressed) {
+ d.setColor(Color::Shadow3D);
+
+ d.drawLine(1+offset,1+offset,width-2-offset,1+offset);
+ d.drawLine(1+offset,1+offset,1+offset,height-2-offset);
+ } else {
+ d.setColor(Color::Background3D);
+
+ d.drawLine(1+offset,1+offset,width-3-offset,1+offset);
+ d.drawLine(1+offset,1+offset,1+offset,height-3-offset);
+
+ d.setColor(Color::Light3D);
+
+ d.drawLine(2+offset,2+offset,width-4-offset,2+offset);
+ d.drawLine(2+offset,2+offset,2+offset,height-4-offset);
+
+ d.setColor(Color::Shadow3D);
+
+ d.drawLine(2+offset,height-3-offset,width-2-offset,height-3-offset);
+ d.drawLine(width-3-offset,2+offset,width-3-offset,height-2-offset);
+
+ d.setColor(Color::Border);
+
+ d.drawLine(width-2-offset,1+offset,width-2-offset,height-2-offset);
+ d.drawLine(1+offset,height-2-offset,width-2-offset,height-2-offset);
+ }
+}
+
+bool Checkbox::keyDown(const Key &key)
+{
+ switch (key.special) {
+ case Key::None:
+ if (key.character != ' ') return false;
+ case Key::Enter:
+ break;
+ default: return false;
+ }
+ mouseDown(0,0,Left);
+ return true;
+}
+
+bool Checkbox::keyUp(const Key &key)
+{
+ if (key.ctrl || key.alt || key.windows || (key.character != ' ' && key.special != Key::Enter)) return false;
+ mouseUp(0,0,Left);
+ mouseClicked(0,0,Left);
+ return true;
+}
+
+void Checkbox::paint(Drawable &d) const
+{
+ d.setColor(Color::Background3D);
+ d.fillRect(2,(height/2)-7,14,14);
+
+ d.setColor(Color::Shadow3D);
+ d.drawLine(2,(height/2)-7,13,(height/2)-7);
+ d.drawLine(2,(height/2)-7,2,(height/2)+5);
+
+ d.setColor(Color::Light3D);
+ d.drawLine(2,(height/2)+5,14,(height/2)+5);
+ d.drawLine(14,(height/2)-7,14,(height/2)+5);
+
+ d.setColor(Color::EditableBackground);
+ d.fillRect(4,(height/2)-5,9,9);
+
+ d.setColor(Color::Border);
+ d.drawLine(3,(height/2)-6,12,(height/2)-6);
+ d.drawLine(3,(height/2)-6,3,(height/2)+4);
+
+ if (checked) {
+ d.setColor(Color::Text);
+ d.drawLine(5,(height/2)-2,7,(height/2) );
+ d.drawLine(11,(height/2)-4);
+ d.drawLine(5,(height/2)-1,7,(height/2)+1);
+ d.drawLine(11,(height/2)-3);
+ d.drawLine(5,(height/2) ,7,(height/2)+2);
+ d.drawLine(11,(height/2)-2);
+ }
+}
+
+Radiobox::Radiobox(Frame *parent, int x, int y, int w, int h) : BorderedWindow(static_cast(parent),x,y,w,h,16,0,0,0), ActionEventSource("GUI::Radiobox"), checked(0)
+{
+ addActionHandler(parent);
+}
+
+bool Radiobox::keyDown(const Key &key)
+{
+ switch (key.special) {
+ case Key::None:
+ if (key.character != ' ') return false;
+ case Key::Enter:
+ break;
+ default: return false;
+ }
+ mouseDown(0,0,Left);
+ return true;
+}
+
+bool Radiobox::keyUp(const Key &key)
+{
+ if (key.ctrl || key.alt || key.windows || (key.character != ' ' && key.special != Key::Enter)) return false;
+ mouseUp(0,0,Left);
+ mouseClicked(0,0,Left);
+ return true;
+}
+
+void Radiobox::paint(Drawable &d) const
+{
+ d.setColor(Color::Light3D);
+ d.drawLine(6,(height/2)+6,9,(height/2)+6);
+ d.drawLine(4,(height/2)+5,11,(height/2)+5);
+ d.drawLine(13,(height/2)-1,13,(height/2)+2);
+ d.drawLine(12,(height/2)-2,12,(height/2)+4);
+
+ d.setColor(Color::Background3D);
+ d.drawLine(6,(height/2)+5,9,(height/2)+5);
+ d.drawLine(4,(height/2)+4,11,(height/2)+4);
+ d.drawLine(12,(height/2)-1,12,(height/2)+2);
+ d.drawLine(11,(height/2)-2,11,(height/2)+4);
+
+ d.setColor(Color::Shadow3D);
+ d.drawLine(6,(height/2)-5,9,(height/2)-5);
+ d.drawLine(4,(height/2)-4,11,(height/2)-4);
+ d.drawLine(2,(height/2)-1,2,(height/2)+2);
+ d.drawLine(3,(height/2)-3,3,(height/2)+4);
+
+ d.setColor(Color::Border);
+ d.drawLine(6,(height/2)-4,9,(height/2)-4);
+ d.drawLine(4,(height/2)-3,11,(height/2)-3);
+ d.drawLine(3,(height/2)-1,3,(height/2)+2);
+ d.drawLine(4,(height/2)-3,4,(height/2)+3);
+
+ d.setColor(Color::EditableBackground);
+ d.fillRect(5,(height/2)-2,6,6);
+ d.fillRect(4,(height/2)-1,8,4);
+ d.fillRect(6,(height/2)-3,4,8);
+
+ if (checked) {
+ d.setColor(Color::Text);
+ d.fillRect(6,(height/2),4,2);
+ d.fillRect(7,(height/2)-1,2,4);
+ }
+}
+
+void Menu::paint(Drawable &d) const
+{
+ d.clear(Color::Background3D);
+
+ d.setColor(Color::Border);
+ d.drawLine(0,height-1,width-1,height-1);
+ d.drawLine(width-1,0,width-1,height-1);
+
+ d.setColor(Color::Shadow3D);
+ d.drawLine(0,0,width-2,0);
+ d.drawLine(0,0,0,height-2);
+ d.drawLine(0,height-2,width-2,height-2);
+ d.drawLine(width-2,0,width-2,height-2);
+
+ d.setColor(Color::Light3D);
+ d.drawLine(1,1,width-3,1);
+ d.drawLine(1,1,1,height-3);
+
+ d.setFont(Font::getFont("menu"));
+ const int asc = Font::getFont("menu")->getAscent()+1;
+ const int height = Font::getFont("menu")->getHeight()+2;
+ int y = asc+3;
+ int index = 0;
+ for (std::vector::const_iterator i = items.begin(); i != items.end(); ++i) {
+ if ((*i).empty()) {
+ d.setColor(Color::Shadow3D);
+ d.drawLine(4,y-asc+6,width-5,y-asc+6);
+ d.setColor(Color::Light3D);
+ d.drawLine(4,y-asc+7,width-5,y-asc+7);
+ y += 12;
+ } else {
+ if (index == selected && hasFocus()) {
+ d.setColor(Color::SelectionBackground);
+ d.fillRect(3,y-asc,width-6,height);
+ d.setColor(Color::SelectionForeground);
+ } else {
+ d.setColor(Color::Text);
+ }
+ d.drawText(20,y,(*i),false,0);
+ y += height;
+ }
+ index++;
+ }
+}
+
+void Menubar::paint(Drawable &d) const
+{
+ const Font *f = Font::getFont("menu");
+
+ d.setColor(Color::Light3D);
+ d.drawLine(0,height-1,width-1,height-1);
+ d.setColor(Color::Shadow3D);
+ d.drawLine(0,height-2,width-1,height-2);
+
+ d.gotoXY(7,f->getAscent()+2);
+
+ int index = 0;
+ for (std::vector