From d865c55007321366d49b9b3d49eb0d61715dfc98 Mon Sep 17 00:00:00 2001 From: Darkvater Date: Mon, 21 Feb 2005 18:59:54 +0000 Subject: (svn r1894) - Codechange: cleaned up the console a bit, wholly unified handling of text with that of editboxes - Codechange: Introduction of Textbuf struct which not only holds physical data as length but also pixel-constrains (width) and information about the caret - Codechange: Move Clipboard function to OS specific file. Currently only Windows has clipboard actions - Feature: Editboxes, console and exit screen also accept the numeric-enter as a yes - Feature: Navigation through text with cursor keys is possible, as well as arbitrary insertion (also paste) and deletion; both backspace and del keys. Functions DeleteTextBufferChar, InsertTextBufferChar and InsertTextBufferClipboard handle input and deletion. Navigation is done through MoveTextBufferPos. - Fix: OTTD crash when opening 'add server' editbox - CodeChange: fix up some stringwidth calculations in gfx.c. You can get the width in pixels of a character by calling GetCharacterWidth(). --- console.c | 171 ++++++++++++++++++++++++-------------------------------------- 1 file changed, 66 insertions(+), 105 deletions(-) (limited to 'console.c') diff --git a/console.c b/console.c index 598683cfc..dd3b629bc 100644 --- a/console.c +++ b/console.c @@ -6,6 +6,7 @@ #include "gfx.h" #include "player.h" #include "variables.h" +#include "string.h" #include "hal.h" #include #include @@ -14,10 +15,6 @@ #include "network_data.h" #include "network_server.h" -#ifdef WIN32 -#include -#endif - #define ICON_BUFFER 79 #define ICON_CMDBUF_SIZE 20 #define ICON_CMDLN_SIZE 255 @@ -30,8 +27,7 @@ static bool _iconsole_inited; static char* _iconsole_buffer[ICON_BUFFER + 1]; static uint16 _iconsole_cbuffer[ICON_BUFFER + 1]; -static char _iconsole_cmdline[ICON_CMDLN_SIZE]; -static byte _iconsole_cmdpos; +static Textbuf _iconsole_cmdline; static byte _iconsole_scroll; // ** console cursor ** // @@ -48,56 +44,25 @@ FILE* _iconsole_output_file; static char* _iconsole_cmdbuffer[ICON_CMDBUF_SIZE]; static byte _iconsole_cmdbufferpos; -// ** console window ** // -static void IConsoleWndProc(Window* w, WindowEvent* e); -static const Widget _iconsole_window_widgets[] = { - {WIDGETS_END} -}; -static const WindowDesc _iconsole_window_desc = { - 0, 0, 2, 2, - WC_CONSOLE, 0, - WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, - _iconsole_window_widgets, - IConsoleWndProc, -}; - /* *************** */ /* end of header */ /* *************** */ -static void IConsoleAppendClipboard(void) -{ -#ifdef WIN32 - if (IsClipboardFormatAvailable(CF_TEXT)) { - const char* data; - HGLOBAL cbuf; - - OpenClipboard(NULL); - cbuf = GetClipboardData(CF_TEXT); - data = GlobalLock(cbuf); - - /* IS_INT_INSIDE = filter for ascii-function codes like BELL and so on [we need an special filter here later] */ - for (; (IS_INT_INSIDE(*data, ' ', 256)) && (_iconsole_cmdpos < lengthof(_iconsole_cmdline) - 1); ++data) - _iconsole_cmdline[_iconsole_cmdpos++] = *data; - - GlobalUnlock(cbuf); - CloseClipboard(); - } -#endif -} - static void IConsoleClearCommand(void) { - memset(_iconsole_cmdline, 0, sizeof(_iconsole_cmdline)); - _iconsole_cmdpos = 0; + memset(_iconsole_cmdline.buf, 0, ICON_CMDLN_SIZE); + _iconsole_cmdline.length = 0; + _iconsole_cmdline.width = 0; + _iconsole_cmdline.caretpos = 0; + _iconsole_cmdline.caretxoffs = 0; SetWindowDirty(_iconsole_win); } +// ** console window ** // static void IConsoleWndProc(Window* w, WindowEvent* e) { switch(e->event) { - case WE_PAINT: - { + case WE_PAINT: { int i = _iconsole_scroll; int max = (w->height / ICON_LINE_HEIGHT) - 1; int delta = 0; @@ -107,47 +72,30 @@ static void IConsoleWndProc(Window* w, WindowEvent* e) w->height - (_iconsole_scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]); i--; } - delta = w->width - 10 - GetStringWidth(_iconsole_cmdline) - ICON_RIGHT_BORDERWIDTH; + /* If the text is longer than the window, don't show the starting ']' */ + delta = w->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH; if (delta > 0) { DoDrawString("]", 5, w->height - ICON_LINE_HEIGHT, _iconsole_color_commands); delta = 0; } - DoDrawString(_iconsole_cmdline, 10 + delta, w->height - ICON_LINE_HEIGHT, _iconsole_color_commands); + DoDrawString(_iconsole_cmdline.buf, 10 + delta, w->height - ICON_LINE_HEIGHT, _iconsole_color_commands); + + if (_iconsole_cmdline.caret) + DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, w->height - ICON_LINE_HEIGHT, 12); break; } - case WE_TICK: - _icursor_counter++; - if (_icursor_counter > _icursor_rate) { - int posx; - int posy; - int delta; - - _icursor_state = !_icursor_state; - - _cur_dpi = &_screen; - delta = w->width - 10 - GetStringWidth(_iconsole_cmdline) - ICON_RIGHT_BORDERWIDTH; - if (delta > 0) - delta = 0; - posx = 10 + GetStringWidth(_iconsole_cmdline) + delta; - posy = w->height - 3; - GfxFillRect(posx, posy, posx + 5, posy + 1, _icursor_state ? 14 : 0); - _video_driver->make_dirty(posx, posy, 5, 1); - _icursor_counter = 0; - } + case WE_MOUSELOOP: + if (HandleCaret(&_iconsole_cmdline)) + SetWindowDirty(w); break; case WE_DESTROY: _iconsole_win = NULL; _iconsole_mode = ICONSOLE_CLOSED; break; case WE_KEYPRESS: - { e->keypress.cont = false; switch (e->keypress.keycode) { - case WKC_CTRL | 'V': - IConsoleAppendClipboard(); - SetWindowDirty(w); - break; case WKC_UP: IConsoleCmdBufferNavigate(+1); SetWindowDirty(w); @@ -187,47 +135,57 @@ static void IConsoleWndProc(Window* w, WindowEvent* e) case WKC_BACKQUOTE: IConsoleSwitch(); break; - case WKC_RETURN: - IConsolePrintF(_iconsole_color_commands, "] %s", _iconsole_cmdline); - _iconsole_cmdbufferpos = 19; - IConsoleCmdBufferAdd(_iconsole_cmdline); + case WKC_RETURN: case WKC_NUM_ENTER: + IConsolePrintF(_iconsole_color_commands, "] %s", _iconsole_cmdline.buf); + _iconsole_cmdbufferpos = ICON_CMDBUF_SIZE - 1; + IConsoleCmdBufferAdd(_iconsole_cmdline.buf); - IConsoleCmdExec(_iconsole_cmdline); + IConsoleCmdExec(_iconsole_cmdline.buf); IConsoleClearCommand(); break; case WKC_CTRL | WKC_RETURN: - if (_iconsole_mode == ICONSOLE_FULL) { - _iconsole_mode = ICONSOLE_OPENED; - } else { - _iconsole_mode = ICONSOLE_FULL; - } + _iconsole_mode = (_iconsole_mode == ICONSOLE_FULL) ? ICONSOLE_OPENED : ICONSOLE_FULL; IConsoleResize(); MarkWholeScreenDirty(); break; - case WKC_BACKSPACE: - if (_iconsole_cmdpos != 0) _iconsole_cmdpos--; - _iconsole_cmdline[_iconsole_cmdpos] = 0; - SetWindowDirty(w); - _iconsole_cmdbufferpos = 19; + case (WKC_CTRL | 'V'): + if (InsertTextBufferClipboard(&_iconsole_cmdline)) + SetWindowDirty(w); + break; + case WKC_BACKSPACE: case WKC_DELETE: + if (DeleteTextBufferChar(&_iconsole_cmdline, e->keypress.keycode)) + SetWindowDirty(w); + _iconsole_cmdbufferpos = ICON_CMDBUF_SIZE - 1; + break; + case WKC_LEFT: case WKC_RIGHT: case WKC_END: case WKC_HOME: + if (MoveTextBufferPos(&_iconsole_cmdline, e->keypress.keycode)) + SetWindowDirty(w); break; default: - /* IS_INT_INSIDE = filter for ascii-function codes like BELL and so on [we need an special filter here later] */ - if (IS_INT_INSIDE(e->keypress.ascii, ' ', 256)) { + if (IsValidAsciiChar(e->keypress.ascii)) { _iconsole_scroll = ICON_BUFFER; - _iconsole_cmdline[_iconsole_cmdpos] = e->keypress.ascii; - if (_iconsole_cmdpos != lengthof(_iconsole_cmdline)) - _iconsole_cmdpos++; - SetWindowDirty(w); + InsertTextBufferChar(&_iconsole_cmdline, e->keypress.ascii); _iconsole_cmdbufferpos = ICON_CMDBUF_SIZE - 1; - } - else + SetWindowDirty(w); + } else e->keypress.cont = true; - } break; } } } +static const Widget _iconsole_window_widgets[] = { + {WIDGETS_END} +}; + +static const WindowDesc _iconsole_window_desc = { + 0, 0, 2, 2, + WC_CONSOLE, 0, + WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, + _iconsole_window_widgets, + IConsoleWndProc, +}; + extern const char _openttd_revision[]; void IConsoleInit(void) @@ -254,6 +212,8 @@ void IConsoleInit(void) memset(_iconsole_cmdbuffer, 0, sizeof(_iconsole_cmdbuffer)); memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer)); memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer)); + _iconsole_cmdline.buf = calloc(ICON_CMDLN_SIZE, sizeof(*_iconsole_cmdline.buf)); // create buffer and zero it + _iconsole_cmdline.maxlength = ICON_CMDLN_SIZE - 1; IConsoleStdLibRegister(); IConsolePrintF(13, "OpenTTD Game Console Revision 6 - %s", _openttd_revision); @@ -269,6 +229,8 @@ void IConsoleClear(void) uint i; for (i = 0; i <= ICON_BUFFER; i++) free(_iconsole_buffer[i]); + + free(_iconsole_cmdline.buf); } static void IConsoleWriteToLogFile(const char* string) @@ -357,9 +319,9 @@ void IConsoleOpen(void) void IConsoleCmdBufferAdd(const char* cmd) { int i; - if (_iconsole_cmdbufferpos != 19) return; - free(_iconsole_cmdbuffer[18]); - for (i = 18; i > 0; i--) _iconsole_cmdbuffer[i] = _iconsole_cmdbuffer[i - 1]; + if (_iconsole_cmdbufferpos != (ICON_CMDBUF_SIZE - 1)) return; + free(_iconsole_cmdbuffer[ICON_CMDBUF_SIZE - 2]); + for (i = (ICON_CMDBUF_SIZE - 2); i > 0; i--) _iconsole_cmdbuffer[i] = _iconsole_cmdbuffer[i - 1]; _iconsole_cmdbuffer[0] = strdup(cmd); } @@ -367,23 +329,22 @@ void IConsoleCmdBufferNavigate(signed char direction) { int i; i = _iconsole_cmdbufferpos + direction; - if (i < 0) i = 19; - if (i > 19) i = 0; + if (i < 0) i = ICON_CMDBUF_SIZE - 1; + if (i >= ICON_CMDBUF_SIZE) i = 0; if (direction > 0) while (_iconsole_cmdbuffer[i] == NULL) { - ++i; - if (i > 19) i = 0; + i++; + if (i >= ICON_CMDBUF_SIZE) i = 0; } if (direction < 0) while (_iconsole_cmdbuffer[i] == NULL) { --i; - if (i < 0) i = 19; + if (i < 0) i = ICON_CMDBUF_SIZE - 1; } _iconsole_cmdbufferpos = i; IConsoleClearCommand(); - memcpy(_iconsole_cmdline, _iconsole_cmdbuffer[i], - strlen(_iconsole_cmdbuffer[i])); - _iconsole_cmdpos = strlen(_iconsole_cmdbuffer[i]); + ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_cmdbuffer[i], _iconsole_cmdline.maxlength); + UpdateTextBufferSize(&_iconsole_cmdline); } void IConsolePrint(uint16 color_code, const char* string) -- cgit v1.2.3-54-g00ecf