src/console_gui.cpp
changeset 9906 9c0a829bf58e
parent 9339 189117c9c937
child 9915 9c9960c44822
equal deleted inserted replaced
9905:591248f0d341 9906:9c0a829bf58e
    12 #include "console_internal.h"
    12 #include "console_internal.h"
    13 #include "window_func.h"
    13 #include "window_func.h"
    14 #include "string_func.h"
    14 #include "string_func.h"
    15 #include "gfx_func.h"
    15 #include "gfx_func.h"
    16 #include "core/math_func.hpp"
    16 #include "core/math_func.hpp"
       
    17 #include "settings_type.h"
    17 #include "rev.h"
    18 #include "rev.h"
    18 
    19 
    19 #include "table/strings.h"
    20 #include "table/strings.h"
    20 
    21 
    21 #define ICON_BUFFER 79
    22 enum {
    22 #define ICON_HISTORY_SIZE 20
    23 	ICON_HISTORY_SIZE       = 20,
    23 #define ICON_LINE_HEIGHT 12
    24 	ICON_LINE_HEIGHT        = 12,
    24 #define ICON_RIGHT_BORDERWIDTH 10
    25 	ICON_RIGHT_BORDERWIDTH  = 10,
    25 #define ICON_BOTTOM_BORDERWIDTH 12
    26 	ICON_BOTTOM_BORDERWIDTH = 12,
    26 #define ICON_MAX_ALIAS_LINES 40
    27 };
    27 #define ICON_TOKEN_COUNT 20
    28 
    28 
    29 /**
    29 /* console modes */
    30  * Container for a single line of console output
    30 IConsoleModes _iconsole_mode;
    31  */
    31 
    32 struct IConsoleLine {
    32 /* ** main console ** */
    33 	static IConsoleLine *front; ///< The front of the console backlog buffer
    33 static char *_iconsole_buffer[ICON_BUFFER + 1];
    34 	static int size;            ///< The amount of items in the backlog
    34 static uint16 _iconsole_cbuffer[ICON_BUFFER + 1];
    35 
       
    36 	IConsoleLine *previous; ///< The previous console message.
       
    37 	char *buffer;          ///< The data to store.
       
    38 	uint16 colour;         ///< The colour of the line.
       
    39 	uint16 time;           ///< The amount of time the line is in the backlog.
       
    40 
       
    41 	/**
       
    42 	 * Initialize the console line.
       
    43 	 * @param buffer the data to print.
       
    44 	 * @param colour the colour of the line.
       
    45 	 */
       
    46 	IConsoleLine(char *buffer, uint16 colour) :
       
    47 			previous(IConsoleLine::front),
       
    48 			buffer(buffer),
       
    49 			colour(colour),
       
    50 			time(0)
       
    51 	{
       
    52 		IConsoleLine::front = this;
       
    53 		IConsoleLine::size++;
       
    54 	}
       
    55 
       
    56 	/**
       
    57 	 * Clear this console line and any further ones.
       
    58 	 */
       
    59 	~IConsoleLine()
       
    60 	{
       
    61 		IConsoleLine::size--;
       
    62 		free(buffer);
       
    63 
       
    64 		delete previous;
       
    65 	}
       
    66 
       
    67 	/**
       
    68 	 * Get the index-ed item in the list.
       
    69 	 */
       
    70 	static const IConsoleLine *Get(uint index)
       
    71 	{
       
    72 		const IConsoleLine *item = IConsoleLine::front;
       
    73 		while (index != 0 && item != NULL) {
       
    74 			index--;
       
    75 			item = item->previous;
       
    76 		}
       
    77 
       
    78 		return item;
       
    79 	}
       
    80 
       
    81 	/**
       
    82 	 * Truncate the list removing everything older than/more than the amount
       
    83 	 * as specified in the config file.
       
    84 	 * As a side effect also increase the time the other lines have been in
       
    85 	 * the list.
       
    86 	 * @return true if and only if items got removed.
       
    87 	 */
       
    88 	static bool Truncate()
       
    89 	{
       
    90 		IConsoleLine *cur = IConsoleLine::front;
       
    91 		if (cur == NULL) return false;
       
    92 
       
    93 		int count = 1;
       
    94 		for (IConsoleLine *item = cur->previous; item != NULL; count++, cur = item, item = item->previous) {
       
    95 			if (item->time > _settings_client.gui.console_backlog_timeout &&
       
    96 					count > _settings_client.gui.console_backlog_length) {
       
    97 				delete item;
       
    98 				cur->previous = NULL;
       
    99 				return true;
       
   100 			}
       
   101 
       
   102 			if (item->time != MAX_UVALUE(typeof(item->time))) item->time++;
       
   103 		}
       
   104 
       
   105 		return false;
       
   106 	}
       
   107 
       
   108 	/**
       
   109 	 * Reset the complete console line backlog.
       
   110 	 */
       
   111 	static void Reset()
       
   112 	{
       
   113 		delete IConsoleLine::front;
       
   114 		IConsoleLine::front = NULL;
       
   115 		IConsoleLine::size = 0;
       
   116 	}
       
   117 };
       
   118 
       
   119 /* static */ IConsoleLine *IConsoleLine::front = NULL;
       
   120 /* static */ int IConsoleLine::size  = 0;
       
   121 
       
   122 
       
   123 /* ** main console cmd buffer ** */
    35 static Textbuf _iconsole_cmdline;
   124 static Textbuf _iconsole_cmdline;
    36 
       
    37 /* ** main console cmd buffer ** */
       
    38 static char *_iconsole_history[ICON_HISTORY_SIZE];
   125 static char *_iconsole_history[ICON_HISTORY_SIZE];
    39 static byte _iconsole_historypos;
   126 static byte _iconsole_historypos;
       
   127 IConsoleModes _iconsole_mode;
    40 
   128 
    41 /* *************** *
   129 /* *************** *
    42  *  end of header  *
   130  *  end of header  *
    43  * *************** */
   131  * *************** */
    44 
   132 
    58 static void IConsoleHistoryAdd(const char *cmd);
   146 static void IConsoleHistoryAdd(const char *cmd);
    59 static void IConsoleHistoryNavigate(int direction);
   147 static void IConsoleHistoryNavigate(int direction);
    60 
   148 
    61 struct IConsoleWindow : Window
   149 struct IConsoleWindow : Window
    62 {
   150 {
    63 	static byte scroll;
   151 	static int scroll;
    64 
   152 
    65 	IConsoleWindow(const WindowDesc *desc) : Window(desc)
   153 	IConsoleWindow(const WindowDesc *desc) : Window(desc)
    66 	{
   154 	{
    67 		_iconsole_mode = ICONSOLE_OPENED;
   155 		_iconsole_mode = ICONSOLE_OPENED;
    68 		SetBit(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
   156 		SetBit(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
    77 		ClrBit(_no_scroll, SCROLL_CON);
   165 		ClrBit(_no_scroll, SCROLL_CON);
    78 	}
   166 	}
    79 
   167 
    80 	virtual void OnPaint()
   168 	virtual void OnPaint()
    81 	{
   169 	{
    82 		int i = IConsoleWindow::scroll;
       
    83 		int max = (this->height / ICON_LINE_HEIGHT) - 1;
   170 		int max = (this->height / ICON_LINE_HEIGHT) - 1;
    84 		int delta = 0;
   171 		const IConsoleLine *print = IConsoleLine::Get(IConsoleWindow::scroll);
    85 		GfxFillRect(this->left, this->top, this->width, this->height - 1, 0);
   172 		GfxFillRect(this->left, this->top, this->width, this->height - 1, 0);
    86 		while ((i > 0) && (i > IConsoleWindow::scroll - max) && (_iconsole_buffer[i] != NULL)) {
   173 		for (int i = 0; i < max && print != NULL; i++, print = print->previous) {
    87 			DoDrawString(_iconsole_buffer[i], 5,
   174 			DoDrawString(print->buffer, 5,
    88 				this->height - (IConsoleWindow::scroll + 2 - i) * ICON_LINE_HEIGHT, _iconsole_cbuffer[i]);
   175 				this->height - (2 + i) * ICON_LINE_HEIGHT, print->colour);
    89 			i--;
       
    90 		}
   176 		}
    91 		/* If the text is longer than the window, don't show the starting ']' */
   177 		/* If the text is longer than the window, don't show the starting ']' */
    92 		delta = this->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH;
   178 		int delta = this->width - 10 - _iconsole_cmdline.width - ICON_RIGHT_BORDERWIDTH;
    93 		if (delta > 0) {
   179 		if (delta > 0) {
    94 			DoDrawString("]", 5, this->height - ICON_LINE_HEIGHT, CC_COMMAND);
   180 			DoDrawString("]", 5, this->height - ICON_LINE_HEIGHT, CC_COMMAND);
    95 			delta = 0;
   181 			delta = 0;
    96 		}
   182 		}
    97 
   183 
   100 		if (_iconsole_cmdline.caret) {
   186 		if (_iconsole_cmdline.caret) {
   101 			DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, this->height - ICON_LINE_HEIGHT, TC_WHITE);
   187 			DoDrawString("_", 10 + delta + _iconsole_cmdline.caretxoffs, this->height - ICON_LINE_HEIGHT, TC_WHITE);
   102 		}
   188 		}
   103 	}
   189 	}
   104 
   190 
       
   191 	virtual void OnHundredthTick()
       
   192 	{
       
   193 		if (IConsoleLine::Truncate() &&
       
   194 				(IConsoleWindow::scroll > IConsoleLine::size)) {
       
   195 			IConsoleWindow::scroll = max(0, IConsoleLine::size - (this->height / ICON_LINE_HEIGHT) + 1);
       
   196 			this->SetDirty();
       
   197 		}
       
   198 	}
       
   199 
   105 	virtual void OnMouseLoop()
   200 	virtual void OnMouseLoop()
   106 	{
   201 	{
   107 		if (HandleCaret(&_iconsole_cmdline)) this->SetDirty();
   202 		if (HandleCaret(&_iconsole_cmdline)) this->SetDirty();
   108 	}
   203 	}
   109 
   204 
   110 	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
   205 	virtual EventState OnKeyPress(uint16 key, uint16 keycode)
   111 	{
   206 	{
       
   207 		const int scroll_height = (this->height / ICON_LINE_HEIGHT) - 1;
   112 		switch (keycode) {
   208 		switch (keycode) {
   113 			case WKC_UP:
   209 			case WKC_UP:
   114 				IConsoleHistoryNavigate(+1);
   210 				IConsoleHistoryNavigate(+1);
   115 				this->SetDirty();
   211 				this->SetDirty();
   116 				break;
   212 				break;
   118 			case WKC_DOWN:
   214 			case WKC_DOWN:
   119 				IConsoleHistoryNavigate(-1);
   215 				IConsoleHistoryNavigate(-1);
   120 				this->SetDirty();
   216 				this->SetDirty();
   121 				break;
   217 				break;
   122 
   218 
   123 			case WKC_SHIFT | WKC_PAGEUP:
   219 			case WKC_SHIFT | WKC_PAGEDOWN:
   124 				if (IConsoleWindow::scroll - (this->height / ICON_LINE_HEIGHT) - 1 < 0) {
   220 				if (IConsoleWindow::scroll - scroll_height < 0) {
   125 					IConsoleWindow::scroll = 0;
   221 					IConsoleWindow::scroll = 0;
   126 				} else {
   222 				} else {
   127 					IConsoleWindow::scroll -= (this->height / ICON_LINE_HEIGHT) - 1;
   223 					IConsoleWindow::scroll -= scroll_height;
   128 				}
   224 				}
   129 				this->SetDirty();
   225 				this->SetDirty();
   130 				break;
   226 				break;
   131 
   227 
   132 			case WKC_SHIFT | WKC_PAGEDOWN:
   228 			case WKC_SHIFT | WKC_PAGEUP:
   133 				if (IConsoleWindow::scroll + (this->height / ICON_LINE_HEIGHT) - 1 > ICON_BUFFER) {
   229 				if (IConsoleWindow::scroll + scroll_height > IConsoleLine::size - scroll_height) {
   134 					IConsoleWindow::scroll = ICON_BUFFER;
   230 					IConsoleWindow::scroll = IConsoleLine::size - scroll_height;
   135 				} else {
   231 				} else {
   136 					IConsoleWindow::scroll += (this->height / ICON_LINE_HEIGHT) - 1;
   232 					IConsoleWindow::scroll += scroll_height;
   137 				}
   233 				}
   138 				this->SetDirty();
   234 				this->SetDirty();
   139 				break;
   235 				break;
   140 
   236 
   141 			case WKC_SHIFT | WKC_UP:
   237 			case WKC_SHIFT | WKC_DOWN:
   142 				if (IConsoleWindow::scroll <= 0) {
   238 				if (IConsoleWindow::scroll <= 0) {
   143 					IConsoleWindow::scroll = 0;
   239 					IConsoleWindow::scroll = 0;
   144 				} else {
   240 				} else {
   145 					--IConsoleWindow::scroll;
   241 					--IConsoleWindow::scroll;
   146 				}
   242 				}
   147 				this->SetDirty();
   243 				this->SetDirty();
   148 				break;
   244 				break;
   149 
   245 
   150 			case WKC_SHIFT | WKC_DOWN:
   246 			case WKC_SHIFT | WKC_UP:
   151 				if (IConsoleWindow::scroll >= ICON_BUFFER) {
   247 				if (IConsoleWindow::scroll >= IConsoleLine::size) {
   152 					IConsoleWindow::scroll = ICON_BUFFER;
   248 					IConsoleWindow::scroll = IConsoleLine::size;
   153 				} else {
   249 				} else {
   154 					++IConsoleWindow::scroll;
   250 					++IConsoleWindow::scroll;
   155 				}
   251 				}
   156 				this->SetDirty();
   252 				this->SetDirty();
   157 				break;
   253 				break;
   204 				}
   300 				}
   205 				break;
   301 				break;
   206 
   302 
   207 			default:
   303 			default:
   208 				if (IsValidChar(key, CS_ALPHANUMERAL)) {
   304 				if (IsValidChar(key, CS_ALPHANUMERAL)) {
   209 					IConsoleWindow::scroll = ICON_BUFFER;
   305 					IConsoleWindow::scroll = 0;
   210 					InsertTextBufferChar(&_iconsole_cmdline, key);
   306 					InsertTextBufferChar(&_iconsole_cmdline, key);
   211 					IConsoleResetHistoryPos();
   307 					IConsoleResetHistoryPos();
   212 					this->SetDirty();
   308 					this->SetDirty();
   213 				} else {
   309 				} else {
   214 					return ES_NOT_HANDLED;
   310 					return ES_NOT_HANDLED;
   216 		}
   312 		}
   217 		return ES_HANDLED;
   313 		return ES_HANDLED;
   218 	}
   314 	}
   219 };
   315 };
   220 
   316 
   221 byte IConsoleWindow::scroll = ICON_BUFFER;
   317 int IConsoleWindow::scroll = 0;
   222 
   318 
   223 static const Widget _iconsole_window_widgets[] = {
   319 static const Widget _iconsole_window_widgets[] = {
   224 	{WIDGETS_END}
   320 	{WIDGETS_END}
   225 };
   321 };
   226 
   322 
   234 void IConsoleGUIInit()
   330 void IConsoleGUIInit()
   235 {
   331 {
   236 	_iconsole_historypos = ICON_HISTORY_SIZE - 1;
   332 	_iconsole_historypos = ICON_HISTORY_SIZE - 1;
   237 	_iconsole_mode = ICONSOLE_CLOSED;
   333 	_iconsole_mode = ICONSOLE_CLOSED;
   238 
   334 
       
   335 	IConsoleLine::Reset();
   239 	memset(_iconsole_history, 0, sizeof(_iconsole_history));
   336 	memset(_iconsole_history, 0, sizeof(_iconsole_history));
   240 	memset(_iconsole_buffer, 0, sizeof(_iconsole_buffer));
   337 
   241 	memset(_iconsole_cbuffer, 0, sizeof(_iconsole_cbuffer));
       
   242 	_iconsole_cmdline.buf = CallocT<char>(ICON_CMDLN_SIZE); // create buffer and zero it
   338 	_iconsole_cmdline.buf = CallocT<char>(ICON_CMDLN_SIZE); // create buffer and zero it
   243 	_iconsole_cmdline.maxlength = ICON_CMDLN_SIZE;
   339 	_iconsole_cmdline.maxlength = ICON_CMDLN_SIZE;
   244 
   340 
   245 	IConsolePrintF(CC_WARNING, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
   341 	IConsolePrintF(CC_WARNING, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
   246 	IConsolePrint(CC_WHITE,  "------------------------------------");
   342 	IConsolePrint(CC_WHITE,  "------------------------------------");
   250 	IConsoleHistoryAdd("");
   346 	IConsoleHistoryAdd("");
   251 }
   347 }
   252 
   348 
   253 void IConsoleClearBuffer()
   349 void IConsoleClearBuffer()
   254 {
   350 {
   255 	uint i;
   351 	IConsoleLine::Reset();
   256 	for (i = 0; i <= ICON_BUFFER; i++) {
       
   257 		free(_iconsole_buffer[i]);
       
   258 		_iconsole_buffer[i] = NULL;
       
   259 	}
       
   260 }
   352 }
   261 
   353 
   262 void IConsoleGUIFree()
   354 void IConsoleGUIFree()
   263 {
   355 {
   264 	free(_iconsole_cmdline.buf);
   356 	free(_iconsole_cmdline.buf);
   351  * @param color_code the colour of the command. Red in case of errors, etc.
   443  * @param color_code the colour of the command. Red in case of errors, etc.
   352  * @param string the message entered or output on the console (notice, error, etc.)
   444  * @param string the message entered or output on the console (notice, error, etc.)
   353  */
   445  */
   354 void IConsoleGUIPrint(ConsoleColour color_code, char *str)
   446 void IConsoleGUIPrint(ConsoleColour color_code, char *str)
   355 {
   447 {
   356 	/* move up all the strings in the buffer one place and do the same for colour
   448 	new IConsoleLine(str, color_code);
   357 	 * to accomodate for the new command/message */
       
   358 	free(_iconsole_buffer[0]);
       
   359 	memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER);
       
   360 	_iconsole_buffer[ICON_BUFFER] = str;
       
   361 
       
   362 	memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER);
       
   363 	_iconsole_cbuffer[ICON_BUFFER] = color_code;
       
   364 
       
   365 	SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
   449 	SetWindowDirty(FindWindowById(WC_CONSOLE, 0));
   366 }
   450 }