summaryrefslogtreecommitdiff
path: root/textscreen
diff options
context:
space:
mode:
authorSimon Howard2012-10-28 23:45:08 +0000
committerSimon Howard2012-10-28 23:45:08 +0000
commit993315afc4b1fddaf8952e7e55d1373b5052dd7c (patch)
tree94aa07d101ddced8404ceaa92ce051ed17fe2a88 /textscreen
parenta1b2ce54d02823aa85c7df6aa016c567185451ae (diff)
parentad11652dcd8e0923432ad272e6535276c51d39eb (diff)
downloadchocolate-doom-993315afc4b1fddaf8952e7e55d1373b5052dd7c.tar.gz
chocolate-doom-993315afc4b1fddaf8952e7e55d1373b5052dd7c.tar.bz2
chocolate-doom-993315afc4b1fddaf8952e7e55d1373b5052dd7c.zip
Merge from trunk.
Subversion-branch: /branches/v2-branch Subversion-revision: 2537
Diffstat (limited to 'textscreen')
-rw-r--r--textscreen/Makefile.am1
-rw-r--r--textscreen/examples/guitest.c4
-rw-r--r--textscreen/txt_button.c2
-rw-r--r--textscreen/txt_checkbox.c8
-rw-r--r--textscreen/txt_dropdown.c1
-rw-r--r--textscreen/txt_gui.c131
-rw-r--r--textscreen/txt_gui.h7
-rw-r--r--textscreen/txt_inputbox.c67
-rw-r--r--textscreen/txt_io.c106
-rw-r--r--textscreen/txt_io.h8
-rw-r--r--textscreen/txt_label.c33
-rw-r--r--textscreen/txt_label.h4
-rw-r--r--textscreen/txt_main.h30
-rw-r--r--textscreen/txt_radiobutton.c7
-rw-r--r--textscreen/txt_sdl.c12
-rw-r--r--textscreen/txt_separator.c1
-rw-r--r--textscreen/txt_spinctrl.c13
-rw-r--r--textscreen/txt_utf8.c160
-rw-r--r--textscreen/txt_utf8.h31
-rw-r--r--textscreen/txt_widget.c12
-rw-r--r--textscreen/txt_window.c14
-rw-r--r--textscreen/txt_window_action.c4
22 files changed, 488 insertions, 168 deletions
diff --git a/textscreen/Makefile.am b/textscreen/Makefile.am
index c1c6f392..ef1bfb59 100644
--- a/textscreen/Makefile.am
+++ b/textscreen/Makefile.am
@@ -30,6 +30,7 @@ libtextscreen_a_SOURCES = \
txt_smallfont.h \
txt_strut.c txt_strut.h \
txt_table.c txt_table.h \
+ txt_utf8.c txt_utf8.h \
txt_widget.c txt_widget.h \
txt_window.c txt_window.h \
txt_window_action.c txt_window_action.h \
diff --git a/textscreen/examples/guitest.c b/textscreen/examples/guitest.c
index df79be2d..a5aad93f 100644
--- a/textscreen/examples/guitest.c
+++ b/textscreen/examples/guitest.c
@@ -179,6 +179,10 @@ void Window2(void)
NULL);
TXT_AddWidget(unselectable_table, TXT_NewLabel("* Unselectable table *"));
+ TXT_AddWidget(unselectable_table, TXT_NewLabel(
+ "This is a UTF-8 string:\n"
+ "\xc3\x80 bient\xc3\xb4t na\xc3\xaet "
+ "\xc3\xa9v\xc3\xaaque \xc3\xa0 l'\xc5\x93uvre p\xc3\xa8re."));
TXT_AddWidget(window, TXT_NewSeparator("Input boxes"));
table = TXT_NewTable(2);
diff --git a/textscreen/txt_button.c b/textscreen/txt_button.c
index 989bd4fc..c8e3fc77 100644
--- a/textscreen/txt_button.c
+++ b/textscreen/txt_button.c
@@ -46,8 +46,6 @@ static void TXT_ButtonDrawer(TXT_UNCAST_ARG(button))
w = button->widget.w;
- TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
-
TXT_SetWidgetBG(button);
TXT_DrawString(button->label);
diff --git a/textscreen/txt_checkbox.c b/textscreen/txt_checkbox.c
index 8c3271cf..3bd0a054 100644
--- a/textscreen/txt_checkbox.c
+++ b/textscreen/txt_checkbox.c
@@ -43,12 +43,13 @@ static void TXT_CheckBoxSizeCalc(TXT_UNCAST_ARG(checkbox))
static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox))
{
TXT_CAST_ARG(txt_checkbox_t, checkbox);
+ txt_saved_colors_t colors;
int i;
int w;
w = checkbox->widget.w;
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
+ TXT_SaveColors(&colors);
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
TXT_DrawString("(");
@@ -67,11 +68,10 @@ static void TXT_CheckBoxDrawer(TXT_UNCAST_ARG(checkbox))
TXT_DrawString(") ");
+ TXT_RestoreColors(&colors);
TXT_SetWidgetBG(checkbox);
- TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
-
TXT_DrawString(checkbox->label);
-
+
for (i=strlen(checkbox->label); i < w-5; ++i)
{
TXT_DrawString(" ");
diff --git a/textscreen/txt_dropdown.c b/textscreen/txt_dropdown.c
index efc94683..652c9a36 100644
--- a/textscreen/txt_dropdown.c
+++ b/textscreen/txt_dropdown.c
@@ -230,7 +230,6 @@ static void TXT_DropdownListDrawer(TXT_UNCAST_ARG(list))
// Set bg/fg text colors.
TXT_SetWidgetBG(list);
- TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
// Select a string to draw from the list, if the current value is
// in range. Otherwise fall back to a default.
diff --git a/textscreen/txt_gui.c b/textscreen/txt_gui.c
index d00e3a65..09ba87ef 100644
--- a/textscreen/txt_gui.c
+++ b/textscreen/txt_gui.c
@@ -25,9 +25,55 @@
#include "txt_gui.h"
#include "txt_io.h"
#include "txt_main.h"
+#include "txt_utf8.h"
typedef struct txt_cliparea_s txt_cliparea_t;
+// Mapping table that converts from the Extended ASCII codes in the
+// CP437 codepage to Unicode character numbers.
+
+static const uint16_t cp437_unicode[] = {
+ 0x00c7, 0x00fc, 0x00e9, 0x00e2, // 80-8f
+ 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+ 0x00ea, 0x00eb, 0x00e8, 0x00ef,
+ 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+
+ 0x00c9, 0x00e6, 0x00c6, 0x00f4, // 90-9f
+ 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+ 0x00ff, 0x00d6, 0x00dc, 0x00a2,
+ 0x00a3, 0x00a5, 0x20a7, 0x0192,
+
+ 0x00e1, 0x00ed, 0x00f3, 0x00fa, // a0-af
+ 0x00f1, 0x00d1, 0x00aa, 0x00ba,
+ 0x00bf, 0x2310, 0x00ac, 0x00bd,
+ 0x00bc, 0x00a1, 0x00ab, 0x00bb,
+
+ 0x2591, 0x2592, 0x2593, 0x2502, // b0-bf
+ 0x2524, 0x2561, 0x2562, 0x2556,
+ 0x2555, 0x2563, 0x2551, 0x2557,
+ 0x255D, 0x255C, 0x255B, 0x2510,
+
+ 0x2514, 0x2534, 0x252C, 0x251C, // c0-cf
+ 0x2500, 0x253C, 0x255E, 0x255F,
+ 0x255A, 0x2554, 0x2569, 0x2566,
+ 0x2560, 0x2550, 0x256C, 0x2567,
+
+ 0x2568, 0x2564, 0x2565, 0x2559, // d0-df
+ 0x2558, 0x2552, 0x2553, 0x256B,
+ 0x256A, 0x2518, 0x250C, 0x2588,
+ 0x2584, 0x258C, 0x2590, 0x2580,
+
+ 0x03B1, 0x00DF, 0x0393, 0x03C0, // e0-ef
+ 0x03A3, 0x03C3, 0x00B5, 0x03C4,
+ 0x03A6, 0x0398, 0x03A9, 0x03B4,
+ 0x221E, 0x03C6, 0x03B5, 0x2229,
+
+ 0x2261, 0x00B1, 0x2265, 0x2264, // f0-ff
+ 0x2320, 0x2321, 0x00F7, 0x2248,
+ 0x00B0, 0x2219, 0x00B7, 0x221A,
+ 0x207F, 0x00B2, 0x25A0, 0x00A0,
+};
+
struct txt_cliparea_s
{
int x1, x2;
@@ -127,11 +173,12 @@ void TXT_DrawShadow(int x, int y, int w, int h)
void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h)
{
+ txt_saved_colors_t colors;
int x1, y1;
int bx, by;
+ TXT_SaveColors(&colors);
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
for (y1=y; y1<y+h; ++y1)
{
@@ -180,18 +227,21 @@ void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h)
TXT_DrawShadow(x + 2, y + h, w, 1);
TXT_DrawShadow(x + w, y + 1, 2, h);
+
+ TXT_RestoreColors(&colors);
}
void TXT_DrawSeparator(int x, int y, int w)
{
+ txt_saved_colors_t colors;
unsigned char *data;
int x1;
int b;
data = TXT_GetScreenData();
+ TXT_SaveColors(&colors);
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
if (!VALID_Y(y))
{
@@ -222,6 +272,8 @@ void TXT_DrawSeparator(int x, int y, int w)
data += 2;
}
+
+ TXT_RestoreColors(&colors);
}
void TXT_DrawString(const char *s)
@@ -251,8 +303,70 @@ void TXT_DrawString(const char *s)
TXT_GotoXY(x + strlen(s), y);
}
+static void PutUnicodeChar(unsigned int c)
+{
+ unsigned int i;
+
+ if (c < 128)
+ {
+ TXT_PutChar(c);
+ return;
+ }
+
+ // We can only display this character if it is in the CP437 codepage.
+
+ for (i = 0; i < 128; ++i)
+ {
+ if (cp437_unicode[i] == c)
+ {
+ TXT_PutChar(128 + i);
+ return;
+ }
+ }
+
+ // Otherwise, print a fallback character (inverted question mark):
+
+ TXT_PutChar('\xa8');
+}
+
+void TXT_DrawUTF8String(const char *s)
+{
+ int x, y;
+ int x1;
+ const char *p;
+ unsigned int c;
+
+ TXT_GetXY(&x, &y);
+
+ if (VALID_Y(y))
+ {
+ x1 = x;
+
+ for (p = s; *p != '\0'; )
+ {
+ c = TXT_DecodeUTF8(&p);
+
+ if (c == 0)
+ {
+ break;
+ }
+
+ if (VALID_X(x1))
+ {
+ TXT_GotoXY(x1, y);
+ PutUnicodeChar(c);
+ }
+
+ x1 += 1;
+ }
+ }
+
+ TXT_GotoXY(x + TXT_UTF8_Strlen(s), y);
+}
+
void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range)
{
+ txt_saved_colors_t colors;
int x1;
int cursor_x;
@@ -261,6 +375,7 @@ void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range)
return;
}
+ TXT_SaveColors(&colors);
TXT_FGColor(TXT_COLOR_BLACK);
TXT_BGColor(TXT_COLOR_GREY, 0);
@@ -269,9 +384,9 @@ void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range)
cursor_x = x + 1;
- if (range > 1)
+ if (range > 0)
{
- cursor_x += (cursor * (w - 3)) / (range - 1);
+ cursor_x += (cursor * (w - 3)) / range;
}
if (cursor_x > x + w - 2)
@@ -295,10 +410,12 @@ void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range)
}
TXT_PutChar('\x1a');
+ TXT_RestoreColors(&colors);
}
void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range)
{
+ txt_saved_colors_t colors;
int y1;
int cursor_y;
@@ -307,6 +424,7 @@ void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range)
return;
}
+ TXT_SaveColors(&colors);
TXT_FGColor(TXT_COLOR_BLACK);
TXT_BGColor(TXT_COLOR_GREY, 0);
@@ -320,9 +438,9 @@ void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range)
cursor_y = y + h - 2;
}
- if (range > 1)
+ if (range > 0)
{
- cursor_y += (cursor * (h - 3)) / (range - 1);
+ cursor_y += (cursor * (h - 3)) / range;
}
for (y1=y+1; y1<y+h-1; ++y1)
@@ -344,6 +462,7 @@ void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range)
TXT_GotoXY(x, y + h - 1);
TXT_PutChar('\x19');
+ TXT_RestoreColors(&colors);
}
void TXT_InitClipArea(void)
diff --git a/textscreen/txt_gui.h b/textscreen/txt_gui.h
index 06fc7a36..e4504af8 100644
--- a/textscreen/txt_gui.h
+++ b/textscreen/txt_gui.h
@@ -27,18 +27,19 @@
#ifndef TXT_GUI_H
#define TXT_GUI_H
-#define TXT_WINDOW_BACKGROUND TXT_COLOR_BLUE
-#define TXT_HOVER_BACKGROUND TXT_COLOR_CYAN
+#define TXT_INACTIVE_WINDOW_BACKGROUND TXT_COLOR_BLACK
+#define TXT_ACTIVE_WINDOW_BACKGROUND TXT_COLOR_BLUE
+#define TXT_HOVER_BACKGROUND TXT_COLOR_CYAN
void TXT_DrawDesktopBackground(const char *title);
void TXT_DrawWindowFrame(const char *title, int x, int y, int w, int h);
void TXT_DrawSeparator(int x, int y, int w);
void TXT_DrawString(const char *s);
+void TXT_DrawUTF8String(const char *s);
void TXT_DrawHorizScrollbar(int x, int y, int w, int cursor, int range);
void TXT_DrawVertScrollbar(int x, int y, int h, int cursor, int range);
-
void TXT_InitClipArea(void);
void TXT_PushClipArea(int x1, int x2, int y1, int y2);
void TXT_PopClipArea(void);
diff --git a/textscreen/txt_inputbox.c b/textscreen/txt_inputbox.c
index 2ba08ac6..0f2986cc 100644
--- a/textscreen/txt_inputbox.c
+++ b/textscreen/txt_inputbox.c
@@ -30,6 +30,7 @@
#include "txt_gui.h"
#include "txt_io.h"
#include "txt_main.h"
+#include "txt_utf8.h"
#include "txt_window.h"
extern txt_widget_class_t txt_inputbox_class;
@@ -131,8 +132,6 @@ static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox))
TXT_SetWidgetBG(inputbox);
}
- TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
-
if (!inputbox->editing)
{
// If not editing, use the current value from inputbox->value.
@@ -140,9 +139,9 @@ static void TXT_InputBoxDrawer(TXT_UNCAST_ARG(inputbox))
SetBufferFromValue(inputbox);
}
- TXT_DrawString(inputbox->buffer);
+ TXT_DrawUTF8String(inputbox->buffer);
- chars = strlen(inputbox->buffer);
+ chars = TXT_UTF8_Strlen(inputbox->buffer);
if (chars < w && inputbox->editing && focused)
{
@@ -166,26 +165,36 @@ static void TXT_InputBoxDestructor(TXT_UNCAST_ARG(inputbox))
static void Backspace(txt_inputbox_t *inputbox)
{
- if (strlen(inputbox->buffer) > 0)
+ unsigned int len;
+ char *p;
+
+ len = TXT_UTF8_Strlen(inputbox->buffer);
+
+ if (len > 0)
{
- inputbox->buffer[strlen(inputbox->buffer) - 1] = '\0';
+ p = TXT_UTF8_SkipChars(inputbox->buffer, len - 1);
+ *p = '\0';
}
}
static void AddCharacter(txt_inputbox_t *inputbox, int key)
{
- if (strlen(inputbox->buffer) < inputbox->size)
+ char *end, *p;
+
+ if (TXT_UTF8_Strlen(inputbox->buffer) < inputbox->size)
{
// Add character to the buffer
- inputbox->buffer[strlen(inputbox->buffer) + 1] = '\0';
- inputbox->buffer[strlen(inputbox->buffer)] = key;
+ end = inputbox->buffer + strlen(inputbox->buffer);
+ p = TXT_EncodeUTF8(end, key);
+ *p = '\0';
}
}
static int TXT_InputBoxKeyPress(TXT_UNCAST_ARG(inputbox), int key)
{
TXT_CAST_ARG(txt_inputbox_t, inputbox);
+ unsigned int c;
if (!inputbox->editing)
{
@@ -208,16 +217,18 @@ static int TXT_InputBoxKeyPress(TXT_UNCAST_ARG(inputbox), int key)
inputbox->editing = 0;
}
- if (isprint(key))
+ if (key == KEY_BACKSPACE)
{
- // Add character to the buffer
-
- AddCharacter(inputbox, key);
+ Backspace(inputbox);
}
- if (key == KEY_BACKSPACE)
+ c = TXT_KEY_TO_UNICODE(key);
+
+ if (c >= 128 || isprint(c))
{
- Backspace(inputbox);
+ // Add character to the buffer
+
+ AddCharacter(inputbox, c);
}
return 1;
@@ -277,32 +288,32 @@ txt_widget_class_t txt_int_inputbox_class =
TXT_InputBoxFocused,
};
-txt_inputbox_t *TXT_NewInputBox(char **value, int size)
+static txt_inputbox_t *NewInputBox(txt_widget_class_t *widget_class,
+ void *value, int size)
{
txt_inputbox_t *inputbox;
inputbox = malloc(sizeof(txt_inputbox_t));
- TXT_InitWidget(inputbox, &txt_inputbox_class);
+ TXT_InitWidget(inputbox, widget_class);
inputbox->value = value;
inputbox->size = size;
- inputbox->buffer = malloc(size + 1);
+ // 'size' is the maximum number of characters that can be entered,
+ // but for a UTF-8 string, each character can take up to four
+ // characters.
+ inputbox->buffer = malloc(size * 4 + 1);
inputbox->editing = 0;
return inputbox;
}
-txt_inputbox_t *TXT_NewIntInputBox(int *value, int size)
+txt_inputbox_t *TXT_NewInputBox(char **value, int size)
{
- txt_inputbox_t *inputbox;
-
- inputbox = malloc(sizeof(txt_inputbox_t));
+ return NewInputBox(&txt_inputbox_class, value, size);
+}
- TXT_InitWidget(inputbox, &txt_int_inputbox_class);
- inputbox->value = value;
- inputbox->size = size;
- inputbox->buffer = malloc(15);
- inputbox->editing = 0;
- return inputbox;
+txt_inputbox_t *TXT_NewIntInputBox(int *value, int size)
+{
+ return NewInputBox(&txt_int_inputbox_class, value, size);
}
diff --git a/textscreen/txt_io.c b/textscreen/txt_io.c
index 1ecc7bd6..f7c9a7a4 100644
--- a/textscreen/txt_io.c
+++ b/textscreen/txt_io.c
@@ -30,48 +30,10 @@
#include "txt_io.h"
#include "txt_main.h"
-static struct
-{
- txt_color_t color;
- const char *name;
-} colors[] = {
- {TXT_COLOR_BLACK, "black"},
- {TXT_COLOR_BLUE, "blue"},
- {TXT_COLOR_GREEN, "green"},
- {TXT_COLOR_CYAN, "cyan"},
- {TXT_COLOR_RED, "red"},
- {TXT_COLOR_MAGENTA, "magenta"},
- {TXT_COLOR_BROWN, "brown"},
- {TXT_COLOR_GREY, "grey"},
- {TXT_COLOR_DARK_GREY, "darkgrey"},
- {TXT_COLOR_BRIGHT_BLUE, "brightblue"},
- {TXT_COLOR_BRIGHT_GREEN, "brightgreen"},
- {TXT_COLOR_BRIGHT_CYAN, "brightcyan"},
- {TXT_COLOR_BRIGHT_RED, "brightred"},
- {TXT_COLOR_BRIGHT_MAGENTA, "brightmagenta"},
- {TXT_COLOR_YELLOW, "yellow"},
- {TXT_COLOR_BRIGHT_WHITE, "brightwhite"},
-};
-
static int cur_x = 0, cur_y = 0;
static txt_color_t fgcolor = TXT_COLOR_GREY;
static txt_color_t bgcolor = TXT_COLOR_BLACK;
-static int GetColorForName(char *s)
-{
- size_t i;
-
- for (i=0; i<sizeof(colors) / sizeof(*colors); ++i)
- {
- if (!strcmp(s, colors[i].name))
- {
- return colors[i].color;
- }
- }
-
- return -1;
-}
-
static void NewLine(unsigned char *screendata)
{
int i;
@@ -104,7 +66,7 @@ static void NewLine(unsigned char *screendata)
static void PutChar(unsigned char *screendata, int c)
{
unsigned char *p;
-
+
p = screendata + cur_y * TXT_SCREEN_W * 2 + cur_x * 2;
switch (c)
@@ -149,66 +111,14 @@ void TXT_PutChar(int c)
void TXT_Puts(const char *s)
{
- int previous_color = TXT_COLOR_BLACK;
unsigned char *screen;
const char *p;
- char colorname_buf[20];
- char *ending;
- int col;
screen = TXT_GetScreenData();
for (p=s; *p != '\0'; ++p)
{
- if (*p == '<')
- {
- ++p;
-
- if (*p == '<')
- {
- PutChar(screen, '<');
- }
- else
- {
- ending = strchr(p, '>');
-
- if (ending == NULL)
- {
- return;
- }
-
- strncpy(colorname_buf, p, 19);
- colorname_buf[ending-p] = '\0';
-
- if (!strcmp(colorname_buf, "/"))
- {
- // End of color block
-
- col = previous_color;
- }
- else
- {
- col = GetColorForName(colorname_buf);
-
- if (col < 0)
- {
- return;
- }
-
- // Save the color for the ending marker
-
- previous_color = fgcolor;
- }
-
- TXT_FGColor(col);
-
- p = ending;
- }
- }
- else
- {
- PutChar(screen, *p);
- }
+ PutChar(screen, *p);
}
PutChar(screen, '\n');
@@ -238,6 +148,18 @@ void TXT_BGColor(int color, int blinking)
bgcolor |= TXT_COLOR_BLINKING;
}
+void TXT_SaveColors(txt_saved_colors_t *save)
+{
+ save->bgcolor = bgcolor;
+ save->fgcolor = fgcolor;
+}
+
+void TXT_RestoreColors(txt_saved_colors_t *save)
+{
+ bgcolor = save->bgcolor;
+ fgcolor = save->fgcolor;
+}
+
void TXT_ClearScreen(void)
{
unsigned char *screen;
diff --git a/textscreen/txt_io.h b/textscreen/txt_io.h
index dc25aa93..004fa562 100644
--- a/textscreen/txt_io.h
+++ b/textscreen/txt_io.h
@@ -29,12 +29,20 @@
#include "txt_main.h"
+typedef struct
+{
+ int bgcolor;
+ int fgcolor;
+} txt_saved_colors_t;
+
void TXT_PutChar(int c);
void TXT_Puts(const char *s);
void TXT_GotoXY(int x, int y);
void TXT_GetXY(int *x, int *y);
void TXT_FGColor(txt_color_t color);
void TXT_BGColor(int color, int blinking);
+void TXT_SaveColors(txt_saved_colors_t *save);
+void TXT_RestoreColors(txt_saved_colors_t *save);
void TXT_ClearScreen(void);
#endif /* #ifndef TXT_IO_H */
diff --git a/textscreen/txt_label.c b/textscreen/txt_label.c
index a2afc13b..39ea0e16 100644
--- a/textscreen/txt_label.c
+++ b/textscreen/txt_label.c
@@ -26,6 +26,7 @@
#include "txt_gui.h"
#include "txt_io.h"
#include "txt_main.h"
+#include "txt_utf8.h"
#include "txt_window.h"
static void TXT_LabelSizeCalc(TXT_UNCAST_ARG(label))
@@ -46,8 +47,14 @@ static void TXT_LabelDrawer(TXT_UNCAST_ARG(label))
w = label->widget.w;
- TXT_BGColor(label->bgcolor, 0);
- TXT_FGColor(label->fgcolor);
+ if (label->bgcolor >= 0)
+ {
+ TXT_BGColor(label->bgcolor, 0);
+ }
+ if (label->fgcolor >= 0)
+ {
+ TXT_FGColor(label->fgcolor);
+ }
TXT_GetXY(&origin_x, &origin_y);
@@ -68,7 +75,7 @@ static void TXT_LabelDrawer(TXT_UNCAST_ARG(label))
align_indent = label->w - strlen(label->lines[y]);
break;
}
-
+
// Draw this line
TXT_GotoXY(origin_x, origin_y + y);
@@ -82,8 +89,8 @@ static void TXT_LabelDrawer(TXT_UNCAST_ARG(label))
// The string itself
- TXT_DrawString(label->lines[y]);
- x += strlen(label->lines[y]);
+ TXT_DrawUTF8String(label->lines[y]);
+ x += TXT_UTF8_Strlen(label->lines[y]);
// Gap at the end
@@ -123,7 +130,7 @@ void TXT_SetLabel(txt_label_t *label, char *value)
free(label->label);
free(label->lines);
- // Set the new value
+ // Set the new value
label->label = strdup(value);
@@ -144,7 +151,7 @@ void TXT_SetLabel(txt_label_t *label, char *value)
label->lines = malloc(sizeof(char *) * label->h);
label->lines[0] = label->label;
y = 1;
-
+
for (p = label->label; *p != '\0'; ++p)
{
if (*p == '\n')
@@ -159,8 +166,12 @@ void TXT_SetLabel(txt_label_t *label, char *value)
for (y=0; y<label->h; ++y)
{
- if (strlen(label->lines[y]) > label->w)
- label->w = strlen(label->lines[y]);
+ unsigned int line_len;
+
+ line_len = TXT_UTF8_Strlen(label->lines[y]);
+
+ if (line_len > label->w)
+ label->w = line_len;
}
}
@@ -176,8 +187,8 @@ txt_label_t *TXT_NewLabel(char *text)
// Default colors
- label->bgcolor = TXT_WINDOW_BACKGROUND;
- label->fgcolor = TXT_COLOR_BRIGHT_WHITE;
+ label->bgcolor = -1;
+ label->fgcolor = -1;
TXT_SetLabel(label, text);
diff --git a/textscreen/txt_label.h b/textscreen/txt_label.h
index 16395c93..c0a20bf2 100644
--- a/textscreen/txt_label.h
+++ b/textscreen/txt_label.h
@@ -45,8 +45,8 @@ struct txt_label_s
char *label;
char **lines;
unsigned int w, h;
- txt_color_t fgcolor;
- txt_color_t bgcolor;
+ int fgcolor;
+ int bgcolor;
};
/**
diff --git a/textscreen/txt_main.h b/textscreen/txt_main.h
index a415ee1b..a6dcc954 100644
--- a/textscreen/txt_main.h
+++ b/textscreen/txt_main.h
@@ -32,9 +32,21 @@
#include "txt_sdl.h"
+// textscreen key values:
+// Key values are difficult because we have to support multiple conflicting
+// address spaces.
+// First, Doom's key constants use 0-127 as ASCII and extra values from
+// 128-255 to represent special keys. Second, mouse buttons are represented
+// as buttons. Finally, we want to be able to support Unicode.
+//
+// So we define different ranges:
+// 0-255: Doom key constants, including ASCII.
+// 256-511: Mouse buttons and other reserved.
+// >=512: Unicode values greater than 127 are offset up into this range.
+
// Special keypress values that correspond to mouse button clicks
-#define TXT_MOUSE_BASE 0x10000
+#define TXT_MOUSE_BASE 256
#define TXT_MOUSE_LEFT (TXT_MOUSE_BASE + 0)
#define TXT_MOUSE_RIGHT (TXT_MOUSE_BASE + 1)
#define TXT_MOUSE_MIDDLE (TXT_MOUSE_BASE + 2)
@@ -42,6 +54,22 @@
#define TXT_MOUSE_SCROLLDOWN (TXT_MOUSE_BASE + 4)
#define TXT_MAX_MOUSE_BUTTONS 16
+#define TXT_KEY_TO_MOUSE_BUTTON(x) \
+ ( (x) >= TXT_MOUSE_BASE \
+ && (x) < TXT_MOUSE_BASE + TXT_MAX_MOUSE_BUTTONS ? \
+ (x) - TXT_MOUSE_BASE : -1 )
+
+// Unicode offset. Unicode values from 128 onwards are offset up into
+// this range, so TXT_UNICODE_BASE = Unicode character #128, and so on.
+
+#define TXT_UNICODE_BASE 512
+
+// Convert a key value to a Unicode character:
+
+#define TXT_KEY_TO_UNICODE(x) \
+ ( (x) < 128 ? (x) : \
+ (x) >= TXT_UNICODE_BASE ? ((x) - TXT_UNICODE_BASE + 128) : 0 )
+
// Screen size
#define TXT_SCREEN_W 80
diff --git a/textscreen/txt_radiobutton.c b/textscreen/txt_radiobutton.c
index 10f94ad3..fa722c13 100644
--- a/textscreen/txt_radiobutton.c
+++ b/textscreen/txt_radiobutton.c
@@ -43,12 +43,13 @@ static void TXT_RadioButtonSizeCalc(TXT_UNCAST_ARG(radiobutton))
static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton))
{
TXT_CAST_ARG(txt_radiobutton_t, radiobutton);
+ txt_saved_colors_t colors;
int i;
int w;
w = radiobutton->widget.w;
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
+ TXT_SaveColors(&colors);
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
TXT_DrawString("(");
@@ -67,11 +68,11 @@ static void TXT_RadioButtonDrawer(TXT_UNCAST_ARG(radiobutton))
TXT_DrawString(") ");
+ TXT_RestoreColors(&colors);
TXT_SetWidgetBG(radiobutton);
- TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
TXT_DrawString(radiobutton->label);
-
+
for (i=strlen(radiobutton->label); i < w-5; ++i)
{
TXT_DrawString(" ");
diff --git a/textscreen/txt_sdl.c b/textscreen/txt_sdl.c
index 8ad5bf74..40fb9ff8 100644
--- a/textscreen/txt_sdl.c
+++ b/textscreen/txt_sdl.c
@@ -436,7 +436,17 @@ static int TranslateKey(SDL_keysym *sym)
if (key_mapping)
{
- return sym->unicode;
+ // Unicode characters beyond the ASCII range need to be
+ // mapped up into textscreen's Unicode range.
+
+ if (sym->unicode < 128)
+ {
+ return sym->unicode;
+ }
+ else
+ {
+ return sym->unicode - 128 + TXT_UNICODE_BASE;
+ }
}
else
{
diff --git a/textscreen/txt_separator.c b/textscreen/txt_separator.c
index ce6e29ec..25d6f7bc 100644
--- a/textscreen/txt_separator.c
+++ b/textscreen/txt_separator.c
@@ -65,7 +65,6 @@ static void TXT_SeparatorDrawer(TXT_UNCAST_ARG(separator))
{
TXT_GotoXY(x, y);
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
TXT_FGColor(TXT_COLOR_BRIGHT_GREEN);
TXT_DrawString(" ");
TXT_DrawString(separator->label);
diff --git a/textscreen/txt_spinctrl.c b/textscreen/txt_spinctrl.c
index a4d20343..1015ece5 100644
--- a/textscreen/txt_spinctrl.c
+++ b/textscreen/txt_spinctrl.c
@@ -147,16 +147,17 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol))
TXT_CAST_ARG(txt_spincontrol_t, spincontrol);
unsigned int i;
unsigned int padding;
+ txt_saved_colors_t colors;
int focused;
focused = spincontrol->widget.focused;
- TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
+ TXT_SaveColors(&colors);
+ TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
TXT_DrawString("\x1b ");
-
- TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
+
+ TXT_RestoreColors(&colors);
// Choose background color
@@ -173,7 +174,7 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol))
{
SetBuffer(spincontrol);
}
-
+
i = 0;
padding = spincontrol->widget.w - strlen(spincontrol->buffer) - 4;
@@ -193,8 +194,8 @@ static void TXT_SpinControlDrawer(TXT_UNCAST_ARG(spincontrol))
++i;
}
+ TXT_RestoreColors(&colors);
TXT_FGColor(TXT_COLOR_BRIGHT_CYAN);
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
TXT_DrawString(" \x1a");
}
diff --git a/textscreen/txt_utf8.c b/textscreen/txt_utf8.c
new file mode 100644
index 00000000..1306f265
--- /dev/null
+++ b/textscreen/txt_utf8.c
@@ -0,0 +1,160 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2012 Simon Howard
+//
+// 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., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "txt_utf8.h"
+
+// Encode a Unicode character as UTF-8, storing it in the buffer 'p'
+// and returning the new, incremented position.
+
+char *TXT_EncodeUTF8(char *p, unsigned int c)
+{
+ if (c < 0x80) // 1 character (ASCII):
+ {
+ p[0] = c;
+ return p + 1;
+ }
+ else if (c < 0x800) // 2 character:
+ {
+ p[0] = 0xc0 | (c >> 6);
+ p[1] = 0x80 | (c & 0x3f);
+ return p + 2;
+ }
+ else if (c < 0x10000) // 3 chacater:
+ {
+ p[0] = 0xe0 | (c >> 12);
+ p[1] = 0x80 | ((c >> 6) & 0x3f);
+ p[2] = 0x80 | (c & 0x3f);
+ return p + 3;
+ }
+ else if (c < 0x200000) // 4 character:
+ {
+ p[0] = 0xf0 | (c >> 18);
+ p[1] = 0x80 | ((c >> 12) & 0x3f);
+ p[2] = 0x80 | ((c >> 6) & 0x3f);
+ p[3] = 0x80 | (c & 0x3f);
+ return p + 4;
+ }
+ else
+ {
+ // Too big!
+
+ return p;
+ }
+}
+
+// Decode UTF-8 character, incrementing *ptr over the decoded bytes.
+
+unsigned int TXT_DecodeUTF8(const char **ptr)
+{
+ const char *p = *ptr;
+ unsigned int c;
+
+ // UTF-8 decode.
+
+ if ((*p & 0x80) == 0) // 1 character (ASCII):
+ {
+ c = *p;
+ *ptr += 1;
+ }
+ else if ((p[0] & 0xe0) == 0xc0 // 2 character:
+ && (p[1] & 0xc0) == 0x80)
+ {
+ c = ((p[0] & 0x1f) << 6)
+ | (p[1] & 0x3f);
+ *ptr += 2;
+ }
+ else if ((p[0] & 0xf0) == 0xe0 // 3 character:
+ && (p[1] & 0xc0) == 0x80
+ && (p[2] & 0xc0) == 0x80)
+ {
+ c = ((p[0] & 0x0f) << 12)
+ | ((p[1] & 0x3f) << 6)
+ | (p[2] & 0x3f);
+ *ptr += 3;
+ }
+ else if ((p[0] & 0xf8) == 0xf0 // 4 character:
+ && (p[1] & 0xc0) == 0x80
+ && (p[2] & 0xc0) == 0x80
+ && (p[3] & 0xc0) == 0x80)
+ {
+ c = ((p[0] & 0x07) << 18)
+ | ((p[1] & 0x3f) << 12)
+ | ((p[2] & 0x3f) << 6)
+ | (p[3] & 0x3f);
+ *ptr += 4;
+ }
+ else
+ {
+ // Decode failure.
+ // Don't bother with 5/6 byte sequences.
+
+ c = 0;
+ }
+
+ return c;
+}
+
+// Count the number of characters in a UTF-8 string.
+
+unsigned int TXT_UTF8_Strlen(const char *s)
+{
+ const char *p;
+ unsigned int result = 0;
+ unsigned int c;
+
+ for (p = s; *p != '\0';)
+ {
+ c = TXT_DecodeUTF8(&p);
+
+ if (c == 0)
+ {
+ break;
+ }
+
+ ++result;
+ }
+
+ return result;
+}
+
+// Skip past the first n characters in a UTF-8 string.
+
+char *TXT_UTF8_SkipChars(const char *s, unsigned int n)
+{
+ unsigned int i;
+ const char *p;
+
+ p = s;
+
+ for (i = 0; i < n; ++i)
+ {
+ if (TXT_DecodeUTF8(&p) == 0)
+ {
+ break;
+ }
+ }
+
+ return (char *) p;
+}
+
diff --git a/textscreen/txt_utf8.h b/textscreen/txt_utf8.h
new file mode 100644
index 00000000..dc519032
--- /dev/null
+++ b/textscreen/txt_utf8.h
@@ -0,0 +1,31 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2012 Simon Howard
+//
+// 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., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+
+#ifndef TXT_UTF8_H
+#define TXT_UTF8_H
+
+char *TXT_EncodeUTF8(char *p, unsigned int c);
+unsigned int TXT_DecodeUTF8(const char **ptr);
+unsigned int TXT_UTF8_Strlen(const char *s);
+char *TXT_UTF8_SkipChars(const char *s, unsigned int n);
+
+#endif /* #ifndef TXT_UTF8_H */
+
diff --git a/textscreen/txt_widget.c b/textscreen/txt_widget.c
index 7d31ad68..e0303531 100644
--- a/textscreen/txt_widget.c
+++ b/textscreen/txt_widget.c
@@ -162,14 +162,22 @@ void TXT_CalcWidgetSize(TXT_UNCAST_ARG(widget))
void TXT_DrawWidget(TXT_UNCAST_ARG(widget))
{
TXT_CAST_ARG(txt_widget_t, widget);
+ txt_saved_colors_t colors;
+
+ // The drawing function might change the fg/bg colors,
+ // so make sure we restore them after it's done.
+
+ TXT_SaveColors(&colors);
// For convenience...
TXT_GotoXY(widget->x, widget->y);
// Call drawer method
-
+
widget->widget_class->drawer(widget);
+
+ TXT_RestoreColors(&colors);
}
void TXT_DestroyWidget(TXT_UNCAST_ARG(widget))
@@ -319,7 +327,7 @@ void TXT_SetWidgetBG(TXT_UNCAST_ARG(widget))
}
else
{
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
+ // Use normal window background.
}
}
diff --git a/textscreen/txt_window.c b/textscreen/txt_window.c
index 67543735..9ab6da9b 100644
--- a/textscreen/txt_window.c
+++ b/textscreen/txt_window.c
@@ -28,6 +28,7 @@
#include "txt_label.h"
#include "txt_desktop.h"
#include "txt_gui.h"
+#include "txt_io.h"
#include "txt_main.h"
#include "txt_separator.h"
#include "txt_window.h"
@@ -321,7 +322,18 @@ void TXT_DrawWindow(txt_window_t *window)
txt_widget_t *widgets;
TXT_LayoutWindow(window);
-
+
+ if (window->table.widget.focused)
+ {
+ TXT_BGColor(TXT_ACTIVE_WINDOW_BACKGROUND, 0);
+ }
+ else
+ {
+ TXT_BGColor(TXT_INACTIVE_WINDOW_BACKGROUND, 0);
+ }
+
+ TXT_FGColor(TXT_COLOR_BRIGHT_WHITE);
+
// Draw the window
TXT_DrawWindowFrame(window->title,
diff --git a/textscreen/txt_window_action.c b/textscreen/txt_window_action.c
index cf5ac4a7..f195f06f 100644
--- a/textscreen/txt_window_action.c
+++ b/textscreen/txt_window_action.c
@@ -55,10 +55,6 @@ static void TXT_WindowActionDrawer(TXT_UNCAST_ARG(action))
{
TXT_BGColor(TXT_COLOR_BLACK, 0);
}
- else
- {
- TXT_BGColor(TXT_WINDOW_BACKGROUND, 0);
- }
TXT_DrawString(" ");
TXT_FGColor(TXT_COLOR_BRIGHT_GREEN);