ref: 9d7126c11b5f1577b00987b8d5f0f7f761b012d7
parent: 2c4e3a7dbf89608355d1ce49c221d41b3e2fa7a8
author: Simon Howard <[email protected]>
date: Mon Jun 4 14:32:50 EDT 2007
Rename txt_main.c to txt_sdl.c; add txt_sdl.h for SDL-specific API functions, while keeping txt_main.h for the common API. Add TXT_SDL_SetEventCallback to allow programs to intercept SDL events in the textscreen main loop. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 892
--- a/textscreen/Makefile.am
+++ b/textscreen/Makefile.am
@@ -15,12 +15,13 @@
txt_gui.c txt_gui.h \
txt_inputbox.c txt_inputbox.h \
txt_io.c txt_io.h \
- txt_main.c txt_main.h \
+ txt_main.h \
txt_button.c txt_button.h \
txt_label.c txt_label.h \
txt_radiobutton.c txt_radiobutton.h \
txt_separator.c txt_separator.h \
txt_spinctrl.c txt_spinctrl.h \
+ txt_sdl.c txt_sdl.h \
txt_strut.c txt_strut.h \
txt_table.c txt_table.h \
txt_widget.c txt_widget.h \
--- a/textscreen/txt_desktop.c
+++ b/textscreen/txt_desktop.c
@@ -19,6 +19,7 @@
// 02111-1307, USA.
//
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
--- a/textscreen/txt_main.c
+++ /dev/null
@@ -1,525 +1,0 @@
-// Emacs style mode select -*- C++ -*-
-//-----------------------------------------------------------------------------
-//
-// Copyright(C) 2005,2006 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.
-//
-//-----------------------------------------------------------------------------
-//
-// Text mode emulation in SDL
-//
-//-----------------------------------------------------------------------------
-
-#include "SDL.h"
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "doomkeys.h"
-
-#include "txt_main.h"
-#include "txt_font.h"
-
-#define CHAR_W 8
-#define CHAR_H 16
-
-// Time between character blinks in ms
-
-#define BLINK_PERIOD 250
-
-static SDL_Surface *screen;
-static unsigned char *screendata;
-static int key_mapping = 1;
-
-//#define TANGO
-
-#ifndef TANGO
-
-static SDL_Color ega_colors[] =
-{
- {0x00, 0x00, 0x00, 0x00}, // 0: Black
- {0x00, 0x00, 0xa8, 0x00}, // 1: Blue
- {0x00, 0xa8, 0x00, 0x00}, // 2: Green
- {0x00, 0xa8, 0xa8, 0x00}, // 3: Cyan
- {0xa8, 0x00, 0x00, 0x00}, // 4: Red
- {0xa8, 0x00, 0xa8, 0x00}, // 5: Magenta
- {0xa8, 0x54, 0x00, 0x00}, // 6: Brown
- {0xa8, 0xa8, 0xa8, 0x00}, // 7: Grey
- {0x54, 0x54, 0x54, 0x00}, // 8: Dark grey
- {0x54, 0x54, 0xfe, 0x00}, // 9: Bright blue
- {0x54, 0xfe, 0x54, 0x00}, // 10: Bright green
- {0x54, 0xfe, 0xfe, 0x00}, // 11: Bright cyan
- {0xfe, 0x54, 0x54, 0x00}, // 12: Bright red
- {0xfe, 0x54, 0xfe, 0x00}, // 13: Bright magenta
- {0xfe, 0xfe, 0x54, 0x00}, // 14: Yellow
- {0xfe, 0xfe, 0xfe, 0x00}, // 15: Bright white
-};
-
-#else
-
-// Colors that fit the Tango desktop guidelines: see
-// http://tango.freedesktop.org/ also
-// http://uwstopia.nl/blog/2006/07/tango-terminal
-
-static SDL_Color ega_colors[] =
-{
- {0x2e, 0x34, 0x36, 0x00}, // 0: Black
- {0x34, 0x65, 0xa4, 0x00}, // 1: Blue
- {0x4e, 0x9a, 0x06, 0x00}, // 2: Green
- {0x06, 0x98, 0x9a, 0x00}, // 3: Cyan
- {0xcc, 0x00, 0x00, 0x00}, // 4: Red
- {0x75, 0x50, 0x7b, 0x00}, // 5: Magenta
- {0xc4, 0xa0, 0x00, 0x00}, // 6: Brown
- {0xd3, 0xd7, 0xcf, 0x00}, // 7: Grey
- {0x55, 0x57, 0x53, 0x00}, // 8: Dark grey
- {0x72, 0x9f, 0xcf, 0x00}, // 9: Bright blue
- {0x8a, 0xe2, 0x34, 0x00}, // 10: Bright green
- {0x34, 0xe2, 0xe2, 0x00}, // 11: Bright cyan
- {0xef, 0x29, 0x29, 0x00}, // 12: Bright red
- {0x34, 0xe2, 0xe2, 0x00}, // 13: Bright magenta
- {0xfc, 0xe9, 0x4f, 0x00}, // 14: Yellow
- {0xee, 0xee, 0xec, 0x00}, // 15: Bright white
-};
-
-#endif
-
-//
-// Initialise text mode screen
-//
-// Returns 1 if successful, 0 if an error occurred
-//
-
-int TXT_Init(void)
-{
- SDL_InitSubSystem(SDL_INIT_VIDEO);
-
- screen = SDL_SetVideoMode(TXT_SCREEN_W * CHAR_W, TXT_SCREEN_H * CHAR_H, 8, 0);
-
- if (screen == NULL)
- return 0;
-
- SDL_SetColors(screen, ega_colors, 0, 16);
- SDL_EnableUNICODE(1);
-
- screendata = malloc(TXT_SCREEN_W * TXT_SCREEN_H * 2);
- memset(screendata, 0, TXT_SCREEN_W * TXT_SCREEN_H * 2);
-
- // Ignore all mouse motion events
-
- SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
-
- // Repeat key presses so we can hold down arrows to scroll down the
- // menu, for example. This is what setup.exe does.
-
- SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-
- return 1;
-}
-
-void TXT_Shutdown(void)
-{
- free(screendata);
- SDL_QuitSubSystem(SDL_INIT_VIDEO);
-}
-
-unsigned char *TXT_GetScreenData(void)
-{
- return screendata;
-}
-
-static inline void UpdateCharacter(int x, int y)
-{
- unsigned char character;
- unsigned char *p;
- unsigned char *s, *s1;
- int bg, fg;
- int x1, y1;
-
- p = &screendata[(y * TXT_SCREEN_W + x) * 2];
- character = p[0];
-
- fg = p[1] & 0xf;
- bg = (p[1] >> 4) & 0xf;
-
- if (bg & 0x8)
- {
- // blinking
-
- bg &= ~0x8;
-
- if (((SDL_GetTicks() / BLINK_PERIOD) % 2) == 0)
- {
- fg = bg;
- }
- }
-
- p = &int10_font_16[character * CHAR_H];
-
- s = ((unsigned char *) screen->pixels)
- + (y * CHAR_H * screen->pitch) + (x * CHAR_W);
-
- for (y1=0; y1<CHAR_H; ++y1)
- {
- s1 = s;
-
- for (x1=0; x1<CHAR_W; ++x1)
- {
- if (*p & (1 << (7-x1)))
- {
- *s1++ = fg;
- }
- else
- {
- *s1++ = bg;
- }
- }
-
- ++p;
- s += screen->pitch;
- }
-}
-
-void TXT_UpdateScreenArea(int x, int y, int w, int h)
-{
- int x1, y1;
-
- for (y1=y; y1<y+h; ++y1)
- {
- for (x1=x; x1<x+w; ++x1)
- {
- UpdateCharacter(x1, y1);
- }
- }
-
- SDL_UpdateRect(screen, x * CHAR_W, y * CHAR_H, w * CHAR_W, h * CHAR_H);
-}
-
-void TXT_UpdateScreen(void)
-{
- TXT_UpdateScreenArea(0, 0, TXT_SCREEN_W, TXT_SCREEN_H);
-}
-
-void TXT_GetMousePosition(int *x, int *y)
-{
- SDL_GetMouseState(x, y);
-
- *x /= CHAR_W;
- *y /= CHAR_H;
-}
-
-//
-// Translates the SDL key
-//
-
-static int TranslateKey(SDL_keysym *sym)
-{
- switch(sym->sym)
- {
- case SDLK_LEFT: return KEY_LEFTARROW;
- case SDLK_RIGHT: return KEY_RIGHTARROW;
- case SDLK_DOWN: return KEY_DOWNARROW;
- case SDLK_UP: return KEY_UPARROW;
- case SDLK_ESCAPE: return KEY_ESCAPE;
- case SDLK_RETURN: return KEY_ENTER;
- case SDLK_TAB: return KEY_TAB;
- case SDLK_F1: return KEY_F1;
- case SDLK_F2: return KEY_F2;
- case SDLK_F3: return KEY_F3;
- case SDLK_F4: return KEY_F4;
- case SDLK_F5: return KEY_F5;
- case SDLK_F6: return KEY_F6;
- case SDLK_F7: return KEY_F7;
- case SDLK_F8: return KEY_F8;
- case SDLK_F9: return KEY_F9;
- case SDLK_F10: return KEY_F10;
- case SDLK_F11: return KEY_F11;
- case SDLK_F12: return KEY_F12;
-
- case SDLK_BACKSPACE: return KEY_BACKSPACE;
- case SDLK_DELETE: return KEY_DEL;
-
- case SDLK_PAUSE: return KEY_PAUSE;
-
- case SDLK_KP_EQUALS: return KEY_EQUALS;
-
- case SDLK_LSHIFT:
- case SDLK_RSHIFT:
- return KEY_RSHIFT;
-
- case SDLK_LCTRL:
- case SDLK_RCTRL:
- return KEY_RCTRL;
-
- case SDLK_LALT:
- case SDLK_LMETA:
- case SDLK_RALT:
- case SDLK_RMETA:
- return KEY_RALT;
-
- case SDLK_CAPSLOCK: return KEY_CAPSLOCK;
- case SDLK_SCROLLOCK: return KEY_SCRLCK;
-
- case SDLK_KP0: return KEYP_0;
- case SDLK_KP1: return KEYP_1;
- case SDLK_KP2: return KEYP_2;
- case SDLK_KP3: return KEYP_3;
- case SDLK_KP4: return KEYP_4;
- case SDLK_KP5: return KEYP_5;
- case SDLK_KP6: return KEYP_6;
- case SDLK_KP7: return KEYP_7;
- case SDLK_KP8: return KEYP_8;
- case SDLK_KP9: return KEYP_9;
-
- case SDLK_HOME: return KEY_HOME;
- case SDLK_INSERT: return KEY_INS;
- case SDLK_END: return KEY_END;
- case SDLK_PAGEUP: return KEY_PGUP;
- case SDLK_PAGEDOWN: return KEY_PGDN;
- case SDLK_KP_MULTIPLY: return KEYP_MULTIPLY;
- case SDLK_KP_PLUS: return KEYP_PLUS;
- case SDLK_KP_MINUS: return KEYP_MINUS;
- case SDLK_KP_DIVIDE: return KEYP_DIVIDE;
-
- default: break;
- }
-
- // Returned value is different, depending on whether key mapping is
- // enabled. Key mapping is preferable most of the time, for typing
- // in text, etc. However, when we want to read raw keyboard codes
- // for the setup keyboard configuration dialog, we want the raw
- // key code.
-
- if (key_mapping)
- {
- return sym->unicode;
- }
- else
- {
- return tolower(sym->sym);
- }
-}
-
-
-signed int TXT_GetChar(void)
-{
- SDL_Event ev;
-
- while (SDL_PollEvent(&ev))
- {
- switch (ev.type)
- {
- case SDL_MOUSEBUTTONDOWN:
- if (ev.button.button == SDL_BUTTON_LEFT)
- return TXT_MOUSE_LEFT;
- else if (ev.button.button == SDL_BUTTON_RIGHT)
- return TXT_MOUSE_RIGHT;
- else if (ev.button.button == SDL_BUTTON_MIDDLE)
- return TXT_MOUSE_MIDDLE;
- break;
-
- case SDL_KEYDOWN:
- return TranslateKey(&ev.key.keysym);
-
- case SDL_QUIT:
- // Quit = escape
- return 27;
-
- default:
- break;
- }
- }
-
- return -1;
-}
-
-static char *SpecialKeyName(int key)
-{
- switch (key)
- {
- case ' ': return "SPACE";
- case KEY_RIGHTARROW: return "RIGHT";
- case KEY_LEFTARROW: return "LEFT";
- case KEY_UPARROW: return "UP";
- case KEY_DOWNARROW: return "DOWN";
- case KEY_ESCAPE: return "ESC";
- case KEY_ENTER: return "ENTER";
- case KEY_TAB: return "TAB";
- case KEY_F1: return "F1";
- case KEY_F2: return "F2";
- case KEY_F3: return "F3";
- case KEY_F4: return "F4";
- case KEY_F5: return "F5";
- case KEY_F6: return "F6";
- case KEY_F7: return "F7";
- case KEY_F8: return "F8";
- case KEY_F9: return "F9";
- case KEY_F10: return "F10";
- case KEY_F11: return "F11";
- case KEY_F12: return "F12";
- case KEY_BACKSPACE: return "BKSP";
- case KEY_PAUSE: return "PAUSE";
- case KEY_EQUALS: return "EQUALS";
- case KEY_MINUS: return "MINUS";
- case KEY_RSHIFT: return "SHIFT";
- case KEY_RCTRL: return "CTRL";
- case KEY_RALT: return "ALT";
- case KEY_CAPSLOCK: return "CAPS";
- case KEY_SCRLCK: return "SCRLCK";
- case KEY_HOME: return "HOME";
- case KEY_END: return "END";
- case KEY_PGUP: return "PGUP";
- case KEY_PGDN: return "PGDN";
- case KEY_INS: return "INS";
- case KEY_DEL: return "DEL";
- /*
- case KEYP_0: return "PAD0";
- case KEYP_1: return "PAD1";
- case KEYP_2: return "PAD2";
- case KEYP_3: return "PAD3";
- case KEYP_4: return "PAD4";
- case KEYP_5: return "PAD5";
- case KEYP_6: return "PAD6";
- case KEYP_7: return "PAD7";
- case KEYP_8: return "PAD8";
- case KEYP_9: return "PAD9";
- case KEYP_UPARROW: return "PAD_U";
- case KEYP_DOWNARROW: return "PAD_D";
- case KEYP_LEFTARROW: return "PAD_L";
- case KEYP_RIGHTARROW: return "PAD_R";
- case KEYP_MULTIPLY: return "PAD*";
- case KEYP_PLUS: return "PAD+";
- case KEYP_MINUS: return "PAD-";
- case KEYP_DIVIDE: return "PAD/";
- */
- default: return NULL;
- }
-}
-
-void TXT_GetKeyDescription(int key, char *buf)
-{
- char *keyname;
-
- keyname = SpecialKeyName(key);
-
- if (keyname != NULL)
- {
- strcpy(buf, keyname);
- }
- else if (isprint(key))
- {
- sprintf(buf, "%c", toupper(key));
- }
- else
- {
- sprintf(buf, "??%i", key);
- }
-}
-
-// Searches the desktop screen buffer to determine whether there are any
-// blinking characters.
-
-int TXT_ScreenHasBlinkingChars(void)
-{
- int x, y;
- unsigned char *p;
-
- // Check all characters in screen buffer
-
- for (y=0; y<TXT_SCREEN_H; ++y)
- {
- for (x=0; x<TXT_SCREEN_W; ++x)
- {
- p = &screendata[(y * TXT_SCREEN_W + x) * 2];
-
- if (p[1] & 0x80)
- {
- // This character is blinking
-
- return 1;
- }
- }
- }
-
- // None found
-
- return 0;
-}
-
-// Sleeps until an event is received, the screen needs to be redrawn,
-// or until timeout expires (if timeout != 0)
-
-void TXT_Sleep(int timeout)
-{
- unsigned int start_time;
-
- if (TXT_ScreenHasBlinkingChars())
- {
- int time_to_next_blink;
-
- time_to_next_blink = BLINK_PERIOD - (SDL_GetTicks() % BLINK_PERIOD);
-
- // There are blinking characters on the screen, so we
- // must time out after a while
-
- if (timeout == 0 || timeout > time_to_next_blink)
- {
- // Add one so it is always positive
-
- timeout = time_to_next_blink + 1;
- }
- }
-
- if (timeout == 0)
- {
- // We can just wait forever until an event occurs
-
- SDL_WaitEvent(NULL);
- }
- else
- {
- // Sit in a busy loop until the timeout expires or we have to
- // redraw the blinking screen
-
- start_time = SDL_GetTicks();
-
- while (SDL_GetTicks() < start_time + timeout)
- {
- if (SDL_PollEvent(NULL) != 0)
- {
- // Received an event, so stop waiting
-
- break;
- }
-
- // Don't hog the CPU
-
- SDL_Delay(1);
- }
- }
-}
-
-void TXT_EnableKeyMapping(int enable)
-{
- key_mapping = enable;
-}
-
-void TXT_SetWindowTitle(char *title)
-{
- SDL_WM_SetCaption(title, NULL);
-}
-
--- a/textscreen/txt_main.h
+++ b/textscreen/txt_main.h
@@ -20,7 +20,7 @@
//
//-----------------------------------------------------------------------------
//
-// Text mode emulation in SDL
+// Base interface that abstracts the text mode screen.
//
//-----------------------------------------------------------------------------
@@ -27,10 +27,10 @@
#ifndef TXT_MAIN_H
#define TXT_MAIN_H
-// The textscreen API itself doesn't need SDL; however, SDL needs its
-// headers included where main() is defined.
+// For the moment, txt_sdl.c is the only implementation of the base
+// text mode screen API:
-#include "SDL.h"
+#include "txt_sdl.h"
// Special keypress values that correspond to mouse button clicks
//
--- /dev/null
+++ b/textscreen/txt_sdl.c
@@ -1,0 +1,548 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005,2006 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.
+//
+//-----------------------------------------------------------------------------
+//
+// Text mode emulation in SDL
+//
+//-----------------------------------------------------------------------------
+
+#include "SDL.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomkeys.h"
+
+#include "txt_main.h"
+#include "txt_sdl.h"
+#include "txt_font.h"
+
+#define CHAR_W 8
+#define CHAR_H 16
+
+// Time between character blinks in ms
+
+#define BLINK_PERIOD 250
+
+static SDL_Surface *screen;
+static unsigned char *screendata;
+static int key_mapping = 1;
+
+static TxtSDLEventCallbackFunc event_callback;
+static void *event_callback_data;
+
+//#define TANGO
+
+#ifndef TANGO
+
+static SDL_Color ega_colors[] =
+{
+ {0x00, 0x00, 0x00, 0x00}, // 0: Black
+ {0x00, 0x00, 0xa8, 0x00}, // 1: Blue
+ {0x00, 0xa8, 0x00, 0x00}, // 2: Green
+ {0x00, 0xa8, 0xa8, 0x00}, // 3: Cyan
+ {0xa8, 0x00, 0x00, 0x00}, // 4: Red
+ {0xa8, 0x00, 0xa8, 0x00}, // 5: Magenta
+ {0xa8, 0x54, 0x00, 0x00}, // 6: Brown
+ {0xa8, 0xa8, 0xa8, 0x00}, // 7: Grey
+ {0x54, 0x54, 0x54, 0x00}, // 8: Dark grey
+ {0x54, 0x54, 0xfe, 0x00}, // 9: Bright blue
+ {0x54, 0xfe, 0x54, 0x00}, // 10: Bright green
+ {0x54, 0xfe, 0xfe, 0x00}, // 11: Bright cyan
+ {0xfe, 0x54, 0x54, 0x00}, // 12: Bright red
+ {0xfe, 0x54, 0xfe, 0x00}, // 13: Bright magenta
+ {0xfe, 0xfe, 0x54, 0x00}, // 14: Yellow
+ {0xfe, 0xfe, 0xfe, 0x00}, // 15: Bright white
+};
+
+#else
+
+// Colors that fit the Tango desktop guidelines: see
+// http://tango.freedesktop.org/ also
+// http://uwstopia.nl/blog/2006/07/tango-terminal
+
+static SDL_Color ega_colors[] =
+{
+ {0x2e, 0x34, 0x36, 0x00}, // 0: Black
+ {0x34, 0x65, 0xa4, 0x00}, // 1: Blue
+ {0x4e, 0x9a, 0x06, 0x00}, // 2: Green
+ {0x06, 0x98, 0x9a, 0x00}, // 3: Cyan
+ {0xcc, 0x00, 0x00, 0x00}, // 4: Red
+ {0x75, 0x50, 0x7b, 0x00}, // 5: Magenta
+ {0xc4, 0xa0, 0x00, 0x00}, // 6: Brown
+ {0xd3, 0xd7, 0xcf, 0x00}, // 7: Grey
+ {0x55, 0x57, 0x53, 0x00}, // 8: Dark grey
+ {0x72, 0x9f, 0xcf, 0x00}, // 9: Bright blue
+ {0x8a, 0xe2, 0x34, 0x00}, // 10: Bright green
+ {0x34, 0xe2, 0xe2, 0x00}, // 11: Bright cyan
+ {0xef, 0x29, 0x29, 0x00}, // 12: Bright red
+ {0x34, 0xe2, 0xe2, 0x00}, // 13: Bright magenta
+ {0xfc, 0xe9, 0x4f, 0x00}, // 14: Yellow
+ {0xee, 0xee, 0xec, 0x00}, // 15: Bright white
+};
+
+#endif
+
+//
+// Initialise text mode screen
+//
+// Returns 1 if successful, 0 if an error occurred
+//
+
+int TXT_Init(void)
+{
+ SDL_InitSubSystem(SDL_INIT_VIDEO);
+
+ screen = SDL_SetVideoMode(TXT_SCREEN_W * CHAR_W, TXT_SCREEN_H * CHAR_H, 8, 0);
+
+ if (screen == NULL)
+ return 0;
+
+ SDL_SetColors(screen, ega_colors, 0, 16);
+ SDL_EnableUNICODE(1);
+
+ screendata = malloc(TXT_SCREEN_W * TXT_SCREEN_H * 2);
+ memset(screendata, 0, TXT_SCREEN_W * TXT_SCREEN_H * 2);
+
+ // Ignore all mouse motion events
+
+ SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
+
+ // Repeat key presses so we can hold down arrows to scroll down the
+ // menu, for example. This is what setup.exe does.
+
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+
+ return 1;
+}
+
+void TXT_Shutdown(void)
+{
+ free(screendata);
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+}
+
+unsigned char *TXT_GetScreenData(void)
+{
+ return screendata;
+}
+
+static inline void UpdateCharacter(int x, int y)
+{
+ unsigned char character;
+ unsigned char *p;
+ unsigned char *s, *s1;
+ int bg, fg;
+ int x1, y1;
+
+ p = &screendata[(y * TXT_SCREEN_W + x) * 2];
+ character = p[0];
+
+ fg = p[1] & 0xf;
+ bg = (p[1] >> 4) & 0xf;
+
+ if (bg & 0x8)
+ {
+ // blinking
+
+ bg &= ~0x8;
+
+ if (((SDL_GetTicks() / BLINK_PERIOD) % 2) == 0)
+ {
+ fg = bg;
+ }
+ }
+
+ p = &int10_font_16[character * CHAR_H];
+
+ s = ((unsigned char *) screen->pixels)
+ + (y * CHAR_H * screen->pitch) + (x * CHAR_W);
+
+ for (y1=0; y1<CHAR_H; ++y1)
+ {
+ s1 = s;
+
+ for (x1=0; x1<CHAR_W; ++x1)
+ {
+ if (*p & (1 << (7-x1)))
+ {
+ *s1++ = fg;
+ }
+ else
+ {
+ *s1++ = bg;
+ }
+ }
+
+ ++p;
+ s += screen->pitch;
+ }
+}
+
+void TXT_UpdateScreenArea(int x, int y, int w, int h)
+{
+ int x1, y1;
+
+ for (y1=y; y1<y+h; ++y1)
+ {
+ for (x1=x; x1<x+w; ++x1)
+ {
+ UpdateCharacter(x1, y1);
+ }
+ }
+
+ SDL_UpdateRect(screen, x * CHAR_W, y * CHAR_H, w * CHAR_W, h * CHAR_H);
+}
+
+void TXT_UpdateScreen(void)
+{
+ TXT_UpdateScreenArea(0, 0, TXT_SCREEN_W, TXT_SCREEN_H);
+}
+
+void TXT_GetMousePosition(int *x, int *y)
+{
+ SDL_GetMouseState(x, y);
+
+ *x /= CHAR_W;
+ *y /= CHAR_H;
+}
+
+//
+// Translates the SDL key
+//
+
+static int TranslateKey(SDL_keysym *sym)
+{
+ switch(sym->sym)
+ {
+ case SDLK_LEFT: return KEY_LEFTARROW;
+ case SDLK_RIGHT: return KEY_RIGHTARROW;
+ case SDLK_DOWN: return KEY_DOWNARROW;
+ case SDLK_UP: return KEY_UPARROW;
+ case SDLK_ESCAPE: return KEY_ESCAPE;
+ case SDLK_RETURN: return KEY_ENTER;
+ case SDLK_TAB: return KEY_TAB;
+ case SDLK_F1: return KEY_F1;
+ case SDLK_F2: return KEY_F2;
+ case SDLK_F3: return KEY_F3;
+ case SDLK_F4: return KEY_F4;
+ case SDLK_F5: return KEY_F5;
+ case SDLK_F6: return KEY_F6;
+ case SDLK_F7: return KEY_F7;
+ case SDLK_F8: return KEY_F8;
+ case SDLK_F9: return KEY_F9;
+ case SDLK_F10: return KEY_F10;
+ case SDLK_F11: return KEY_F11;
+ case SDLK_F12: return KEY_F12;
+
+ case SDLK_BACKSPACE: return KEY_BACKSPACE;
+ case SDLK_DELETE: return KEY_DEL;
+
+ case SDLK_PAUSE: return KEY_PAUSE;
+
+ case SDLK_KP_EQUALS: return KEY_EQUALS;
+
+ case SDLK_LSHIFT:
+ case SDLK_RSHIFT:
+ return KEY_RSHIFT;
+
+ case SDLK_LCTRL:
+ case SDLK_RCTRL:
+ return KEY_RCTRL;
+
+ case SDLK_LALT:
+ case SDLK_LMETA:
+ case SDLK_RALT:
+ case SDLK_RMETA:
+ return KEY_RALT;
+
+ case SDLK_CAPSLOCK: return KEY_CAPSLOCK;
+ case SDLK_SCROLLOCK: return KEY_SCRLCK;
+
+ case SDLK_KP0: return KEYP_0;
+ case SDLK_KP1: return KEYP_1;
+ case SDLK_KP2: return KEYP_2;
+ case SDLK_KP3: return KEYP_3;
+ case SDLK_KP4: return KEYP_4;
+ case SDLK_KP5: return KEYP_5;
+ case SDLK_KP6: return KEYP_6;
+ case SDLK_KP7: return KEYP_7;
+ case SDLK_KP8: return KEYP_8;
+ case SDLK_KP9: return KEYP_9;
+
+ case SDLK_HOME: return KEY_HOME;
+ case SDLK_INSERT: return KEY_INS;
+ case SDLK_END: return KEY_END;
+ case SDLK_PAGEUP: return KEY_PGUP;
+ case SDLK_PAGEDOWN: return KEY_PGDN;
+ case SDLK_KP_MULTIPLY: return KEYP_MULTIPLY;
+ case SDLK_KP_PLUS: return KEYP_PLUS;
+ case SDLK_KP_MINUS: return KEYP_MINUS;
+ case SDLK_KP_DIVIDE: return KEYP_DIVIDE;
+
+ default: break;
+ }
+
+ // Returned value is different, depending on whether key mapping is
+ // enabled. Key mapping is preferable most of the time, for typing
+ // in text, etc. However, when we want to read raw keyboard codes
+ // for the setup keyboard configuration dialog, we want the raw
+ // key code.
+
+ if (key_mapping)
+ {
+ return sym->unicode;
+ }
+ else
+ {
+ return tolower(sym->sym);
+ }
+}
+
+
+signed int TXT_GetChar(void)
+{
+ SDL_Event ev;
+
+ while (SDL_PollEvent(&ev))
+ {
+ // If there is an event callback, allow it to intercept this
+ // event.
+
+ if (event_callback != NULL)
+ {
+ if (event_callback(&ev, event_callback_data))
+ {
+ continue;
+ }
+ }
+
+ // Process the event.
+
+ switch (ev.type)
+ {
+ case SDL_MOUSEBUTTONDOWN:
+ if (ev.button.button == SDL_BUTTON_LEFT)
+ return TXT_MOUSE_LEFT;
+ else if (ev.button.button == SDL_BUTTON_RIGHT)
+ return TXT_MOUSE_RIGHT;
+ else if (ev.button.button == SDL_BUTTON_MIDDLE)
+ return TXT_MOUSE_MIDDLE;
+ break;
+
+ case SDL_KEYDOWN:
+ return TranslateKey(&ev.key.keysym);
+
+ case SDL_QUIT:
+ // Quit = escape
+ return 27;
+
+ default:
+ break;
+ }
+ }
+
+ return -1;
+}
+
+static char *SpecialKeyName(int key)
+{
+ switch (key)
+ {
+ case ' ': return "SPACE";
+ case KEY_RIGHTARROW: return "RIGHT";
+ case KEY_LEFTARROW: return "LEFT";
+ case KEY_UPARROW: return "UP";
+ case KEY_DOWNARROW: return "DOWN";
+ case KEY_ESCAPE: return "ESC";
+ case KEY_ENTER: return "ENTER";
+ case KEY_TAB: return "TAB";
+ case KEY_F1: return "F1";
+ case KEY_F2: return "F2";
+ case KEY_F3: return "F3";
+ case KEY_F4: return "F4";
+ case KEY_F5: return "F5";
+ case KEY_F6: return "F6";
+ case KEY_F7: return "F7";
+ case KEY_F8: return "F8";
+ case KEY_F9: return "F9";
+ case KEY_F10: return "F10";
+ case KEY_F11: return "F11";
+ case KEY_F12: return "F12";
+ case KEY_BACKSPACE: return "BKSP";
+ case KEY_PAUSE: return "PAUSE";
+ case KEY_EQUALS: return "EQUALS";
+ case KEY_MINUS: return "MINUS";
+ case KEY_RSHIFT: return "SHIFT";
+ case KEY_RCTRL: return "CTRL";
+ case KEY_RALT: return "ALT";
+ case KEY_CAPSLOCK: return "CAPS";
+ case KEY_SCRLCK: return "SCRLCK";
+ case KEY_HOME: return "HOME";
+ case KEY_END: return "END";
+ case KEY_PGUP: return "PGUP";
+ case KEY_PGDN: return "PGDN";
+ case KEY_INS: return "INS";
+ case KEY_DEL: return "DEL";
+ /*
+ case KEYP_0: return "PAD0";
+ case KEYP_1: return "PAD1";
+ case KEYP_2: return "PAD2";
+ case KEYP_3: return "PAD3";
+ case KEYP_4: return "PAD4";
+ case KEYP_5: return "PAD5";
+ case KEYP_6: return "PAD6";
+ case KEYP_7: return "PAD7";
+ case KEYP_8: return "PAD8";
+ case KEYP_9: return "PAD9";
+ case KEYP_UPARROW: return "PAD_U";
+ case KEYP_DOWNARROW: return "PAD_D";
+ case KEYP_LEFTARROW: return "PAD_L";
+ case KEYP_RIGHTARROW: return "PAD_R";
+ case KEYP_MULTIPLY: return "PAD*";
+ case KEYP_PLUS: return "PAD+";
+ case KEYP_MINUS: return "PAD-";
+ case KEYP_DIVIDE: return "PAD/";
+ */
+ default: return NULL;
+ }
+}
+
+void TXT_GetKeyDescription(int key, char *buf)
+{
+ char *keyname;
+
+ keyname = SpecialKeyName(key);
+
+ if (keyname != NULL)
+ {
+ strcpy(buf, keyname);
+ }
+ else if (isprint(key))
+ {
+ sprintf(buf, "%c", toupper(key));
+ }
+ else
+ {
+ sprintf(buf, "??%i", key);
+ }
+}
+
+// Searches the desktop screen buffer to determine whether there are any
+// blinking characters.
+
+int TXT_ScreenHasBlinkingChars(void)
+{
+ int x, y;
+ unsigned char *p;
+
+ // Check all characters in screen buffer
+
+ for (y=0; y<TXT_SCREEN_H; ++y)
+ {
+ for (x=0; x<TXT_SCREEN_W; ++x)
+ {
+ p = &screendata[(y * TXT_SCREEN_W + x) * 2];
+
+ if (p[1] & 0x80)
+ {
+ // This character is blinking
+
+ return 1;
+ }
+ }
+ }
+
+ // None found
+
+ return 0;
+}
+
+// Sleeps until an event is received, the screen needs to be redrawn,
+// or until timeout expires (if timeout != 0)
+
+void TXT_Sleep(int timeout)
+{
+ unsigned int start_time;
+
+ if (TXT_ScreenHasBlinkingChars())
+ {
+ int time_to_next_blink;
+
+ time_to_next_blink = BLINK_PERIOD - (SDL_GetTicks() % BLINK_PERIOD);
+
+ // There are blinking characters on the screen, so we
+ // must time out after a while
+
+ if (timeout == 0 || timeout > time_to_next_blink)
+ {
+ // Add one so it is always positive
+
+ timeout = time_to_next_blink + 1;
+ }
+ }
+
+ if (timeout == 0)
+ {
+ // We can just wait forever until an event occurs
+
+ SDL_WaitEvent(NULL);
+ }
+ else
+ {
+ // Sit in a busy loop until the timeout expires or we have to
+ // redraw the blinking screen
+
+ start_time = SDL_GetTicks();
+
+ while (SDL_GetTicks() < start_time + timeout)
+ {
+ if (SDL_PollEvent(NULL) != 0)
+ {
+ // Received an event, so stop waiting
+
+ break;
+ }
+
+ // Don't hog the CPU
+
+ SDL_Delay(1);
+ }
+ }
+}
+
+void TXT_EnableKeyMapping(int enable)
+{
+ key_mapping = enable;
+}
+
+void TXT_SetWindowTitle(char *title)
+{
+ SDL_WM_SetCaption(title, NULL);
+}
+
+void TXT_SDL_SetEventCallback(TxtSDLEventCallbackFunc callback, void *user_data)
+{
+ event_callback = callback;
+ event_callback_data = user_data;
+}
+
--- /dev/null
+++ b/textscreen/txt_sdl.h
@@ -1,0 +1,50 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005,2006 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.
+//
+//-----------------------------------------------------------------------------
+//
+// Text mode emulation in SDL
+//
+//-----------------------------------------------------------------------------
+
+#ifndef TXT_SDL_H
+#define TXT_SDL_H
+
+// The textscreen API itself doesn't need SDL; however, SDL needs its
+// headers included where main() is defined.
+
+#include "SDL.h"
+
+// Event callback function type: a function of this type can be used
+// to intercept events in the textscreen event processing loop.
+// Returning 1 will cause the event to be eaten; the textscreen code
+// will not see it.
+
+typedef int (*TxtSDLEventCallbackFunc)(SDL_Event *event, void *user_data);
+
+// Set a callback function to call in the SDL event loop. Useful for
+// intercepting events. Pass callback=NULL to clear an existing
+// callback function.
+// user_data is a void pointer to be passed to the callback function.
+
+void TXT_SDL_SetEventCallback(TxtSDLEventCallbackFunc callback, void *user_data);
+
+#endif /* #ifndef TXT_SDL_H */
+