diff options
Diffstat (limited to 'textscreen')
-rw-r--r-- | textscreen/Makefile.am | 1 | ||||
-rw-r--r-- | textscreen/examples/guitest.c | 4 | ||||
-rw-r--r-- | textscreen/txt_button.c | 2 | ||||
-rw-r--r-- | textscreen/txt_checkbox.c | 8 | ||||
-rw-r--r-- | textscreen/txt_dropdown.c | 1 | ||||
-rw-r--r-- | textscreen/txt_gui.c | 131 | ||||
-rw-r--r-- | textscreen/txt_gui.h | 7 | ||||
-rw-r--r-- | textscreen/txt_inputbox.c | 67 | ||||
-rw-r--r-- | textscreen/txt_io.c | 106 | ||||
-rw-r--r-- | textscreen/txt_io.h | 8 | ||||
-rw-r--r-- | textscreen/txt_label.c | 33 | ||||
-rw-r--r-- | textscreen/txt_label.h | 4 | ||||
-rw-r--r-- | textscreen/txt_main.h | 30 | ||||
-rw-r--r-- | textscreen/txt_radiobutton.c | 7 | ||||
-rw-r--r-- | textscreen/txt_sdl.c | 12 | ||||
-rw-r--r-- | textscreen/txt_separator.c | 1 | ||||
-rw-r--r-- | textscreen/txt_spinctrl.c | 13 | ||||
-rw-r--r-- | textscreen/txt_utf8.c | 160 | ||||
-rw-r--r-- | textscreen/txt_utf8.h | 31 | ||||
-rw-r--r-- | textscreen/txt_widget.c | 12 | ||||
-rw-r--r-- | textscreen/txt_window.c | 14 | ||||
-rw-r--r-- | textscreen/txt_window_action.c | 4 |
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); |