(svn r2243) -Fix: Rework of console. Use 'help command|variable' to get help about it. You can assign variables with =, ++, --, or just new value. Console parser is now lenient towards typed spaces, and more robust in general (at least readable). Removed the 'set' command, instead implemented all such variables as 'variables'.
authorDarkvater
Mon, 02 May 2005 15:52:19 +0000
changeset 1739 4f3082735fbc
parent 1738 6c7f9d12197d
child 1740 29e13b639a78
(svn r2243) -Fix: Rework of console. Use 'help command|variable' to get help about it. You can assign variables with =, ++, --, or just new value. Console parser is now lenient towards typed spaces, and more robust in general (at least readable). Removed the 'set' command, instead implemented all such variables as 'variables'.
- Some variables are really special and cannot be assigned normally, use their callback procedure for assignment/querying. This commit also obsoletes "[1172804] Console set command cleanup"
console.c
console.h
console_cmds.c
network.c
network.h
player_gui.c
settings.h
settings_gui.c
--- a/console.c	Sun May 01 20:16:52 2005 +0000
+++ b/console.c	Mon May 02 15:52:19 2005 +0000
@@ -16,17 +16,17 @@
 #include "network_server.h"
 
 #define ICON_BUFFER 79
-#define ICON_CMDBUF_SIZE 20
-#define ICON_CMDLN_SIZE 255
+#define ICON_HISTORY_SIZE 20
 #define ICON_LINE_HEIGHT 12
 #define ICON_RIGHT_BORDERWIDTH 10
 #define ICON_BOTTOM_BORDERWIDTH 12
 #define ICON_MAX_ALIAS_LINES 40
+#define ICON_TOKEN_COUNT 20
 
 // ** main console ** //
 static Window *_iconsole_win; // Pointer to console window
 static bool _iconsole_inited;
-static char* _iconsole_buffer[ICON_BUFFER + 1];
+static char *_iconsole_buffer[ICON_BUFFER + 1];
 static uint16 _iconsole_cbuffer[ICON_BUFFER + 1];
 static Textbuf _iconsole_cmdline;
 static byte _iconsole_scroll;
@@ -34,11 +34,11 @@
 // ** stdlib ** //
 byte _stdlib_developer = 1;
 bool _stdlib_con_developer = false;
-FILE* _iconsole_output_file;
+FILE *_iconsole_output_file;
 
 // ** main console cmd buffer
-static char* _iconsole_cmdbuffer[ICON_CMDBUF_SIZE];
-static byte _iconsole_cmdbufferpos;
+static char *_iconsole_history[ICON_HISTORY_SIZE];
+static byte _iconsole_historypos;
 
 /* *************** */
 /*  end of header  */
@@ -54,10 +54,12 @@
 	SetWindowDirty(_iconsole_win);
 }
 
+static inline void IConsoleResetHistoryPos(void) {_iconsole_historypos = ICON_HISTORY_SIZE - 1;}
+
 // ** console window ** //
 static void IConsoleWndProc(Window* w, WindowEvent* e)
 {
-	switch(e->event) {
+	switch (e->event) {
 		case WE_PAINT: {
 			int i = _iconsole_scroll;
 			int max = (w->height / ICON_LINE_HEIGHT) - 1;
@@ -93,11 +95,11 @@
 			e->keypress.cont = false;
 			switch (e->keypress.keycode) {
 				case WKC_UP:
-					IConsoleCmdBufferNavigate(+1);
+					IConsoleHistoryNavigate(+1);
 					SetWindowDirty(w);
 					break;
 				case WKC_DOWN:
-					IConsoleCmdBufferNavigate(-1);
+					IConsoleHistoryNavigate(-1);
 					SetWindowDirty(w);
 					break;
 				case WKC_SHIFT | WKC_PAGEUP:
@@ -133,8 +135,7 @@
 					break;
 				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);
+					IConsoleHistoryAdd(_iconsole_cmdline.buf);
 
 					IConsoleCmdExec(_iconsole_cmdline.buf);
 					IConsoleClearCommand();
@@ -145,23 +146,28 @@
 					MarkWholeScreenDirty();
 					break;
 				case (WKC_CTRL | 'V'):
-					if (InsertTextBufferClipboard(&_iconsole_cmdline))
+					if (InsertTextBufferClipboard(&_iconsole_cmdline)) {
+						IConsoleResetHistoryPos();
 						SetWindowDirty(w);
+					}
 					break;
 				case WKC_BACKSPACE: case WKC_DELETE:
-					if (DeleteTextBufferChar(&_iconsole_cmdline, e->keypress.keycode))
+					if (DeleteTextBufferChar(&_iconsole_cmdline, e->keypress.keycode)) {
+						IConsoleResetHistoryPos();
 						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))
+					if (MoveTextBufferPos(&_iconsole_cmdline, e->keypress.keycode)) {
+						IConsoleResetHistoryPos();
 						SetWindowDirty(w);
+					}
 					break;
 				default:
 					if (IsValidAsciiChar(e->keypress.ascii)) {
 						_iconsole_scroll = ICON_BUFFER;
 						InsertTextBufferChar(&_iconsole_cmdline, e->keypress.ascii);
-						_iconsole_cmdbufferpos = ICON_CMDBUF_SIZE - 1;
+						IConsoleResetHistoryPos();
 						SetWindowDirty(w);
 					} else
 						e->keypress.cont = true;
@@ -182,10 +188,9 @@
 	IConsoleWndProc,
 };
 
-extern const char _openttd_revision[];
-
 void IConsoleInit(void)
 {
+	extern const char _openttd_revision[];
 	_iconsole_output_file = NULL;
 	_iconsole_color_default = 1;
 	_iconsole_color_error = 3;
@@ -193,7 +198,7 @@
 	_iconsole_color_debug = 5;
 	_iconsole_color_commands = 2;
 	_iconsole_scroll = ICON_BUFFER;
-	_iconsole_cmdbufferpos = ICON_CMDBUF_SIZE - 1;
+	_iconsole_historypos = ICON_HISTORY_SIZE - 1;
 	_iconsole_inited = true;
 	_iconsole_mode = ICONSOLE_CLOSED;
 	_iconsole_win = NULL;
@@ -202,19 +207,19 @@
 	_redirect_console_to_client = 0;
 #endif
 
-	memset(_iconsole_cmdbuffer, 0, sizeof(_iconsole_cmdbuffer));
+	memset(_iconsole_history, 0, sizeof(_iconsole_history));
 	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;
 
+	IConsolePrintF(13, "OpenTTD Game Console Revision 7 - %s", _openttd_revision);
+	IConsolePrint(12,  "------------------------------------");
+	IConsolePrint(12,  "use \"help\" for more information");
+	IConsolePrint(12,  "");
 	IConsoleStdLibRegister();
-	IConsolePrintF(13, "OpenTTD Game Console Revision 6 - %s", _openttd_revision);
-	IConsolePrint(12, "---------------------------------");
-	IConsolePrint(12, "use \"help\" for more info");
-	IConsolePrint(12, "");
 	IConsoleClearCommand();
-	IConsoleCmdBufferAdd("");
+	IConsoleHistoryAdd("");
 }
 
 void IConsoleClear(void)
@@ -256,7 +261,6 @@
 
 void IConsoleResize(void)
 {
-
 	_iconsole_win = FindWindowById(WC_CONSOLE, 0);
 
 	switch (_iconsole_mode) {
@@ -269,7 +273,7 @@
 			_iconsole_win->width = _screen.width;
 			break;
 		default:
-			break;
+			NOT_REACHED();
 	}
 
 	MarkWholeScreenDirty();
@@ -283,7 +287,7 @@
 			_iconsole_win->height = _screen.height / 3;
 			_iconsole_win->width = _screen.width;
 			_iconsole_mode = ICONSOLE_OPENED;
-			SETBIT(_no_scroll, SCROLL_CON);
+			SETBIT(_no_scroll, SCROLL_CON); // override cursor arrows; the gamefield will not scroll
 			break;
 		case ICONSOLE_OPENED: case ICONSOLE_FULL:
 			DeleteWindowById(WC_CONSOLE, 0);
@@ -296,44 +300,47 @@
 	MarkWholeScreenDirty();
 }
 
-void IConsoleClose(void)
-{
-	if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();
-}
+void IConsoleClose(void) {if (_iconsole_mode == ICONSOLE_OPENED) IConsoleSwitch();}
+void IConsoleOpen(void)  {if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();}
 
-void IConsoleOpen(void)
+/**
+ * Add the entered line into the history so you can look it back
+ * scroll, etc. Put it to the beginning as it is the latest text
+ * @param cmd Text to be entered into the 'history'
+ */
+void IConsoleHistoryAdd(const char *cmd)
 {
-	if (_iconsole_mode == ICONSOLE_CLOSED) IConsoleSwitch();
-}
+	free(_iconsole_history[ICON_HISTORY_SIZE - 1]);
 
-void IConsoleCmdBufferAdd(const char* cmd)
-{
-	int i;
-	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);
+	memmove(&_iconsole_history[1], &_iconsole_history[0], sizeof(_iconsole_history[0]) * (ICON_HISTORY_SIZE - 1));
+	_iconsole_history[0] = strdup(cmd);
+	IConsoleResetHistoryPos();
 }
 
-void IConsoleCmdBufferNavigate(signed char direction)
+/**
+ * Navigate Up/Down in the history of typed commands
+ * @param direction Go further back in history (+1), go to recently typed commands (-1)
+ */
+void IConsoleHistoryNavigate(signed char direction)
 {
-	int i;
-	i = _iconsole_cmdbufferpos + direction;
-	if (i < 0) i = ICON_CMDBUF_SIZE - 1;
-	if (i >= ICON_CMDBUF_SIZE) i = 0;
+	int i = _iconsole_historypos + direction;
+
+	// watch out for overflows, just wrap around
+	if (i < 0) i = ICON_HISTORY_SIZE - 1;
+	if (i >= ICON_HISTORY_SIZE) i = 0;
+
 	if (direction > 0)
-		while (_iconsole_cmdbuffer[i] == NULL) {
-			i++;
-			if (i >= ICON_CMDBUF_SIZE) i = 0;
-		}
-	if (direction < 0)
-		while (_iconsole_cmdbuffer[i] == NULL) {
-			--i;
-			if (i < 0) i = ICON_CMDBUF_SIZE - 1;
-		}
-	_iconsole_cmdbufferpos = i;
+		if (_iconsole_history[i] == NULL) i = 0;
+
+	if (direction < 0) {
+		while (i > 0 && _iconsole_history[i] == NULL) i--;
+	}
+
+	_iconsole_historypos = i;
 	IConsoleClearCommand();
-	ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_cmdbuffer[i], _iconsole_cmdline.maxlength);
+	// copy history to 'command prompt / bash'
+	assert(_iconsole_history[i] != NULL && IS_INT_INSIDE(i, 0, ICON_HISTORY_SIZE));
+	ttd_strlcpy(_iconsole_cmdline.buf, _iconsole_history[i], _iconsole_cmdline.maxlength);
 	UpdateTextBufferSize(&_iconsole_cmdline);
 }
 
@@ -348,8 +355,6 @@
  */
 void IConsolePrint(uint16 color_code, const char* string)
 {
-	char *i;
-
 #ifdef ENABLE_NETWORK
 	if (_redirect_console_to_client != 0) {
 		/* Redirect the string to the client */
@@ -372,9 +377,11 @@
 	memmove(&_iconsole_buffer[0], &_iconsole_buffer[1], sizeof(_iconsole_buffer[0]) * ICON_BUFFER);
 	_iconsole_buffer[ICON_BUFFER] = strdup(string);
 
-	// filter out unprintable characters
-	for (i = _iconsole_buffer[ICON_BUFFER]; *i != '\0'; i++)
-		if (!IsValidAsciiChar((byte)*i)) *i = ' ';
+	{ // filter out unprintable characters
+		char *i;
+		for (i = _iconsole_buffer[ICON_BUFFER]; *i != '\0'; i++)
+			if (!IsValidAsciiChar((byte)*i)) *i = ' ';
+	}
 
 	memmove(&_iconsole_cbuffer[0], &_iconsole_cbuffer[1], sizeof(_iconsole_cbuffer[0]) * ICON_BUFFER);
 	_iconsole_cbuffer[ICON_BUFFER] = color_code;
@@ -384,1103 +391,716 @@
 	if (_iconsole_win != NULL) SetWindowDirty(_iconsole_win);
 }
 
-
-void CDECL IConsolePrintF(uint16 color_code, const char* s, ...)
+/**
+ * Handle the printing of text entered into the console or redirected there
+ * by any other means. Uses printf() style format, for more information look
+ * at @IConsolePrint()
+ */
+void CDECL IConsolePrintF(uint16 color_code, const char *s, ...)
 {
 	va_list va;
-	char buf[1024];
-	int len;
+	char buf[ICON_MAX_STREAMSIZE];
 
 	va_start(va, s);
-	len = vsnprintf(buf, sizeof(buf), s, va);
+	vsnprintf(buf, sizeof(buf), s, va);
 	va_end(va);
 
 	IConsolePrint(color_code, buf);
 }
 
+/**
+ * It is possible to print debugging information to the console,
+ * which is achieved by using this function. Can only be used by
+ * @debug() in debug.c. You need at least a level 2 (developer) for debugging
+ * messages to show up
+ */
 void IConsoleDebug(const char* string)
 {
 	if (_stdlib_developer > 1)
 		IConsolePrintF(_iconsole_color_debug, "dbg: %s", string);
 }
 
-void IConsoleError(const char* string)
-{
-	if (_stdlib_developer > 0)
-		IConsolePrintF(_iconsole_color_error, "ERROR: %s", string);
-}
-
+/**
+ * It is possible to print warnings to the console. These are mostly
+ * errors or mishaps, but non-fatal. You need at least a level 1 (developer) for
+ * debugging messages to show up
+ */
 void IConsoleWarning(const char* string)
 {
 	if (_stdlib_developer > 0)
 		IConsolePrintF(_iconsole_color_warning, "WARNING: %s", string);
 }
 
-void IConsoleCmdRegister(const char* name, _iconsole_cmd_addr addr)
+/**
+ * It is possible to print error information to the console. This can include
+ * game errors, or errors in general you would want the user to notice
+ */
+void IConsoleError(const char* string)
 {
-	char* _new;
-	_iconsole_cmd* item;
-	_iconsole_cmd* item_new;
-	_iconsole_cmd* item_before;
-
-	_new = strdup(name);
-
-	item_new = malloc(sizeof(_iconsole_cmd));
-
-	item_new->_next = NULL;
-	item_new->addr = addr;
-	item_new->name = _new;
-
-	item_new->hook_access = NULL;
-	item_new->hook_after_exec = NULL;
-	item_new->hook_before_exec = NULL;
-
-	item_before = NULL;
-	item = _iconsole_cmds;
-
-	if (item == NULL) {
-		_iconsole_cmds = item_new;
-	} else {
-		while ((item->_next != NULL) && (strcmp(item->name,item_new->name)<=0)) {
-			item_before = item;
-			item = item->_next;
-			}
-// insertion sort
-		if (item_before==NULL) {
-			if (strcmp(item->name,item_new->name)<=0) {
-				// appending
-				item ->_next = item_new;
-			} else {
-				// inserting as startitem
-				_iconsole_cmds = item_new;
-				item_new ->_next = item;
-			}
-		} else {
-			if (strcmp(item->name,item_new->name)<=0) {
-				// appending
-				item ->_next = item_new;
-			} else {
-				// inserting
-				item_new ->_next = item_before->_next;
-				item_before ->_next = item_new;
-			}
-		}
-// insertion sort end
-	}
-
+	IConsolePrintF(_iconsole_color_error, "ERROR: %s", string);
 }
 
-_iconsole_cmd* IConsoleCmdGet(const char* name)
+/**
+ * Change a string into its number representation. Supports
+ * decimal and hexadecimal numbers as well as 'on'/'off' 'true'/'false'
+ * @param *value the variable a successfull conversion will be put in
+ * @param *arg the string to be converted
+ * @return Return true on success or false on failure
+ */
+bool GetArgumentInteger(uint32 *value, const char *arg)
 {
-	_iconsole_cmd* item;
+	int result = sscanf(arg, "%u", value);
 
-	item = _iconsole_cmds;
-	while (item != NULL) {
-		if (strcmp(item->name, name) == 0) return item;
-		item = item->_next;
-	}
-	return NULL;
+	if (result == 0 && arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X'))
+		result = sscanf(arg, "%x", value);
+
+	if (result == 0 && (strcmp(arg, "on") == 0 || strcmp(arg, "true") == 0 )) {*value = 1; result = 1;}
+
+	if (result == 0 && (strcmp(arg, "off") == 0 || strcmp(arg, "false") == 0)) {*value = 0; result = 1;}
+
+	return !!result;
 }
 
-void IConsoleAliasRegister(const char* name, const char* cmdline)
-{
-	char* _new;
-	char* _newcmd;
-	_iconsole_alias* item;
-	_iconsole_alias* item_new;
-	_iconsole_alias* item_before;
-
-	_new = strdup(name);
-	_newcmd = strdup(cmdline);
-
-	item_new = malloc(sizeof(_iconsole_alias));
-
-	item_new->_next = NULL;
-	item_new->cmdline = _newcmd;
-	item_new->name = _new;
-
-	item_before = NULL;
-	item = _iconsole_aliases;
-
-	if (item == NULL) {
-		_iconsole_aliases = item_new;
-	} else {
-		while ((item->_next != NULL) && (strcmp(item->name,item_new->name)<=0)) {
-			item_before = item;
-			item = item->_next;
-			}
-// insertion sort
-		if (item_before==NULL) {
-			if (strcmp(item->name,item_new->name)<=0) {
-				// appending
-				item ->_next = item_new;
-			} else {
-				// inserting as startitem
-				_iconsole_aliases = item_new;
-				item_new ->_next = item;
-			}
-		} else {
-			if (strcmp(item->name,item_new->name)<=0) {
-				// appending
-				item ->_next = item_new;
-			} else {
-				// inserting
-				item_new ->_next = item_before->_next;
-				item_before ->_next = item_new;
-			}
-		}
-// insertion sort end
-	}
-
+/**
+ * Perhaps ugly macro, but this saves us the trouble of writing the same function
+ * three types, just with different variables. Yes, templates would be handy. It was
+ * either this define or an even more ugly void* magic function
+ */
+#define IConsoleAddSorted(_base, item_new, IConsoleType, type)                      \
+{                                                                                   \
+	IConsoleType *item, *item_before;                                                 \
+	/* first command */                                                               \
+	if (_base == NULL) {                                                              \
+		_base = item_new;                                                               \
+		return;                                                                         \
+	}                                                                                 \
+                                                                                    \
+	item_before = NULL;                                                               \
+	item = _base;                                                                     \
+                                                                                    \
+	/* BEGIN - Alphabetically insert the commands into the linked list */             \
+	while (item != NULL) {                                                            \
+		int i = strcmp(item->name, item_new->name);                                     \
+		if (i == 0) {                                                                   \
+			IConsoleError(type " with this name already exists; insertion aborted");      \
+			free(item_new);                                                               \
+			return;                                                                       \
+		}                                                                               \
+                                                                                    \
+		if (i > 0) break; /* insert at this position */                                 \
+                                                                                    \
+		item_before = item;                                                             \
+		item = item->next;                                                              \
+	}                                                                                 \
+                                                                                    \
+	if (item_before == NULL) {                                                        \
+		_base = item_new;                                                               \
+	} else                                                                            \
+		item_before->next = item_new;                                                   \
+                                                                                    \
+	item_new->next = item;                                                            \
+	/* END - Alphabetical insert */                                                   \
 }
 
-_iconsole_alias* IConsoleAliasGet(const char* name)
+/**
+ * Register a new command to be used in the console
+ * @param name name of the command that will be used
+ * @param proc function that will be called upon execution of command
+ */
+void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc)
 {
-	_iconsole_alias* item;
+	char *new_cmd = strdup(name);
+	IConsoleCmd *item_new = malloc(sizeof(IConsoleCmd));
 
-	item = _iconsole_aliases;
-	while (item != NULL) {
+	item_new->next = NULL;
+	item_new->proc = proc;
+	item_new->name = new_cmd;
+
+	item_new->hook.access = NULL;
+	item_new->hook.pre = NULL;
+	item_new->hook.post = NULL;
+
+	IConsoleAddSorted(_iconsole_cmds, item_new, IConsoleCmd, "a command");
+}
+
+/**
+ * Find the command pointed to by its string
+ * @param name command to be found
+ * @return return Cmdstruct of the found command, or NULL on failure
+ */
+IConsoleCmd *IConsoleCmdGet(const char *name)
+{
+	IConsoleCmd *item;
+
+	for (item = _iconsole_cmds; item != NULL; item = item->next) {
 		if (strcmp(item->name, name) == 0) return item;
-		item = item->_next;
 	}
 	return NULL;
 }
 
-static void IConsoleAliasExec(const char* cmdline, char* tokens[20], byte tokentypes[20])
+/**
+ * Register a an alias for an already existing command in the console
+ * @param name name of the alias that will be used
+ * @param cmd name of the command that 'name' will be alias of
+ */
+void IConsoleAliasRegister(const char *name, const char *cmd)
 {
-	char* lines[ICON_MAX_ALIAS_LINES];
-	char* linestream;
-	char* linestream_s;
-
-	int c;
-	int i;
-	int l;
-	int x;
-	byte t;
-
-	//** clearing buffer **//
-
-	for (i = 0; i < 40; i++) {
-		lines[0] = NULL;
-	}
-	linestream_s = linestream = malloc(1024*ICON_MAX_ALIAS_LINES);
-	memset(linestream, 0, 1024*ICON_MAX_ALIAS_LINES);
-
-	//** parsing **//
-
-	l = strlen(cmdline);
-	i = 0;
-	c = 0;
-	x = 0;
-	t = 0;
-	lines[c] = linestream;
+	char *new_alias = strdup(name);
+	char *cmd_aliased = strdup(cmd);
+	IConsoleAlias *item_new = malloc(sizeof(IConsoleAlias));
 
-	while (i < l && c < ICON_MAX_ALIAS_LINES - 1) {
-		if (cmdline[i] == '%') {
-			i++;
-			if (cmdline[i] == '+') {
-				// all params seperated: "[param 1]" "[param 2]"
-				t=1;
-				while ((tokens[t]!=NULL) && (t<20) &&
-						((tokentypes[t] == ICONSOLE_VAR_STRING) || (tokentypes[t] == ICONSOLE_VAR_UNKNOWN))) {
-					int l2 = strlen(tokens[t]);
-					*linestream = '"';
-					linestream++;
-					memcpy(linestream,tokens[t],l2);
-					linestream += l2;
-					*linestream = '"';
-					linestream++;
-					*linestream = ' ';
-					linestream++;
-					x += l2+3;
-					t++;
-				}
-			} else if (cmdline[i] == '!') {
-				// merge the params to one: "[param 1] [param 2] [param 3...]"
-				t=1;
-				*linestream = '"';
-				linestream++;
-				while ((tokens[t]!=NULL) && (t<20) &&
-						((tokentypes[t] == ICONSOLE_VAR_STRING) || (tokentypes[t] == ICONSOLE_VAR_UNKNOWN))) {
-					int l2 = strlen(tokens[t]);
-					memcpy(linestream,tokens[t],l2);
-					linestream += l2;
-					*linestream = ' ';
-					linestream++;
-					x += l2+1;
-					t++;
-				}
-				linestream--;
-				*linestream = '"';
-				linestream++;
-				x += 1;
-			} else {
-				// one specific parameter: %A = [param 1] %B = [param 2] ...
-				int l2;
-				t = ((byte)cmdline[i]) - 64;
-				if ((t<20) && (tokens[t]!=NULL) &&
-						((tokentypes[t] == ICONSOLE_VAR_STRING) || (tokentypes[t] == ICONSOLE_VAR_UNKNOWN))) {
-					l2 = strlen(tokens[t]);
-					*linestream = '"';
-					linestream++;
-					memcpy(linestream,tokens[t],l2);
-					linestream += l2;
-					*linestream = '"';
-					linestream++;
-					x += l2+2;
-				}
-			}
-		} else if (cmdline[i] == '\\') {
-			// \\ = \       \' = '      \% = %
-			i++;
-			if (cmdline[i] == '\\') {
-				*linestream = '\\';
-				linestream++;
-			} else if (cmdline[i] == '\'') {
-				*linestream = '\'';
-				linestream++;
-			} else if (cmdline[i] == '%') {
-				*linestream = '%';
-				linestream++;
-			}
-		} else if (cmdline[i] == '\'') {
-			// ' = "
-			*linestream = '"';
-			linestream++;
-		} else if (cmdline[i] == ';') {
-			// ; = start a new line
-			c++;
-			*linestream = '\0';
-			linestream += 1024 - (x % 1024);
-			x += 1024 - (x % 1024);
-			lines[c] = linestream;
-		} else {
-			*linestream = cmdline[i];
-			linestream++;
-			x++;
-		}
-		i++;
+	item_new->next = NULL;
+	item_new->cmdline = cmd_aliased;
+	item_new->name = new_alias;
+
+	IConsoleAddSorted(_iconsole_aliases, item_new, IConsoleAlias, "an alias");
+}
+
+/**
+ * Find the alias pointed to by its string
+ * @param name alias to be found
+ * @return return Aliasstruct of the found alias, or NULL on failure
+ */
+IConsoleAlias *IConsoleAliasGet(const char *name)
+{
+	IConsoleAlias* item;
+
+	for (item = _iconsole_aliases; item != NULL; item = item->next) {
+		if (strcmp(item->name, name) == 0) return item;
 	}
 
-	linestream--;
-	if (*linestream != '\0') {
-		c++;
-		linestream++;
-		*linestream = '\0';
-	}
-
-	for (i=0; i<c; i++)	{
-		IConsoleCmdExec(lines[i]);
-	}
-
-	free(linestream_s);
-}
-
-void IConsoleVarInsert(_iconsole_var* item_new, const char* name)
-{
-	_iconsole_var* item;
-	_iconsole_var* item_before;
-
-	item_new->_next = NULL;
-
-	item_new->name = malloc(strlen(name) + 2); /* XXX unchecked malloc */
-	sprintf(item_new->name, "%s", name);
-
-	item_before = NULL;
-	item = _iconsole_vars;
-
-	if (item == NULL) {
-		_iconsole_vars = item_new;
-	} else {
-		while ((item->_next != NULL) && (strcmp(item->name,item_new->name)<=0)) {
-			item_before = item;
-			item = item->_next;
-			}
-// insertion sort
-		if (item_before==NULL) {
-			if (strcmp(item->name,item_new->name)<=0) {
-				// appending
-				item ->_next = item_new;
-			} else {
-				// inserting as startitem
-				_iconsole_vars = item_new;
-				item_new ->_next = item;
-			}
-		} else {
-			if (strcmp(item->name,item_new->name)<=0) {
-				// appending
-				item ->_next = item_new;
-			} else {
-				// inserting
-				item_new ->_next = item_before->_next;
-				item_before ->_next = item_new;
-			}
-		}
-// insertion sort end
-	}
-}
-
-void IConsoleVarRegister(const char* name, void* addr, _iconsole_var_types type)
-{
-	_iconsole_var* item_new;
-
-	item_new = malloc(sizeof(_iconsole_var)); /* XXX unchecked malloc */
-
-	item_new->_next = NULL;
-
-	switch (type) {
-		case ICONSOLE_VAR_BOOLEAN:
-			item_new->data.bool_ = addr;
-			break;
-		case ICONSOLE_VAR_BYTE:
-		case ICONSOLE_VAR_UINT8:
-			item_new->data.byte_ = addr;
-			break;
-		case ICONSOLE_VAR_UINT16:
-			item_new->data.uint16_ = addr;
-			break;
-		case ICONSOLE_VAR_UINT32:
-			item_new->data.uint32_ = addr;
-			break;
-		case ICONSOLE_VAR_INT16:
-			item_new->data.int16_ = addr;
-			break;
-		case ICONSOLE_VAR_INT32:
-			item_new->data.int32_ = addr;
-			break;
-		case ICONSOLE_VAR_STRING:
-			item_new->data.string_ = addr;
-			break;
-		default:
-			error("unknown console variable type");
-			break;
-	}
-
-	IConsoleVarInsert(item_new, name);
-
-	item_new->type = type;
-	item_new->_malloc = false;
-
-	item_new->hook_access = NULL;
-	item_new->hook_after_change = NULL;
-	item_new->hook_before_change = NULL;
-
-}
-
-void IConsoleVarMemRegister(const char* name, _iconsole_var_types type)
-{
-	_iconsole_var* item;
-	item = IConsoleVarAlloc(type);
-	IConsoleVarInsert(item, name);
-}
-
-_iconsole_var* IConsoleVarGet(const char* name)
-{
-	_iconsole_var* item;
-	for (item = _iconsole_vars; item != NULL; item = item->_next)
-		if (strcmp(item->name, name) == 0) return item;
 	return NULL;
 }
 
-_iconsole_var* IConsoleVarAlloc(_iconsole_var_types type)
+/** copy in an argument into the aliasstream */
+static inline int IConsoleCopyInParams(char *dst, const char *src, uint bufpos)
 {
-	_iconsole_var* item = malloc(sizeof(_iconsole_var)); /* XXX unchecked malloc */
-	item->_next = NULL;
-	item->name = NULL;
-	item->type = type;
-	switch (item->type) {
-		case ICONSOLE_VAR_BOOLEAN:
-			item->data.bool_ = malloc(sizeof(*item->data.bool_));
-			*item->data.bool_ = false;
-			item->_malloc = true;
-			break;
-		case ICONSOLE_VAR_BYTE:
-		case ICONSOLE_VAR_UINT8:
-			item->data.byte_ = malloc(sizeof(*item->data.byte_));
-			*item->data.byte_ = 0;
-			item->_malloc = true;
-			break;
-		case ICONSOLE_VAR_UINT16:
-			item->data.uint16_ = malloc(sizeof(*item->data.uint16_));
-			*item->data.uint16_ = 0;
-			item->_malloc = true;
+	int len = min(ICON_MAX_STREAMSIZE - bufpos, strlen(src));
+	strncpy(dst, src, len);
+
+	return len;
+}
+
+/**
+ * An alias is just another name for a command, or for more commands
+ * Execute it as well.
+ * @param *alias is the alias of the command
+ * @param tokencount the number of parameters passed
+ * @param *tokens are the parameters given to the original command (0 is the first param)
+ */
+void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[ICON_TOKEN_COUNT])
+{
+	const char *cmdptr;
+	char *aliases[ICON_MAX_ALIAS_LINES], aliasstream[ICON_MAX_STREAMSIZE];
+	int i;
+	uint a_index, astream_i;
+
+	memset(&aliases, 0, sizeof(aliases));
+	memset(&aliasstream, 0, sizeof(aliasstream));
+
+	aliases[0] = aliasstream;
+	for (cmdptr = alias->cmdline, a_index = 0, astream_i = 0; *cmdptr != '\0'; *cmdptr++) {
+		if (a_index >= lengthof(aliases) || astream_i >= lengthof(aliasstream)) break;
+
+		switch (*cmdptr) {
+		case '\'': /* ' will double for "" */
+			aliasstream[astream_i++] = '"';
 			break;
-		case ICONSOLE_VAR_UINT32:
-			item->data.uint32_ = malloc(sizeof(*item->data.uint32_));
-			*item->data.uint32_ = 0;
-			item->_malloc = true;
-			break;
-		case ICONSOLE_VAR_INT16:
-			item->data.int16_ = malloc(sizeof(*item->data.int16_));
-			*item->data.int16_ = 0;
-			item->_malloc = true;
+		case ';': /* Cmd seperator, start new command */
+			aliasstream[astream_i] = '\0';
+			aliases[++a_index] = &aliasstream[++astream_i];
+			*cmdptr++;
 			break;
-		case ICONSOLE_VAR_INT32:
-			item->data.int32_ = malloc(sizeof(*item->data.int32_));
-			*item->data.int32_ = 0;
-			item->_malloc = true;
+		case '%': /* Some or all parameters */
+			*cmdptr++;
+			switch (*cmdptr) {
+			case '+': { /* All parameters seperated: "[param 1]" "[param 2]" */
+				for (i = 0; i != tokencount; i++) {
+					aliasstream[astream_i++] = '"';
+					astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
+					aliasstream[astream_i++] = '"';
+					aliasstream[astream_i++] = ' ';
+				}
+			} break;
+			case '!': { /* Merge the parameters to one: "[param 1] [param 2] [param 3...]" */
+				aliasstream[astream_i++] = '"';
+				for (i = 0; i != tokencount; i++) {
+					astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[i], astream_i);
+					aliasstream[astream_i++] = ' ';
+				}
+				aliasstream[astream_i++] = '"';
+
+			} break;
+				default: { /* One specific parameter: %A = [param 1] %B = [param 2] ... */
+				int param = *cmdptr - 'A';
+
+				if (param < 0 || param >= tokencount) {
+					IConsoleError("too many or wrong amount of parameters passed to alias, aborting");
+					IConsolePrintF(_iconsole_color_warning, "Usage of alias '%s': %s", alias->name, alias->cmdline);
+					return;
+				}
+
+				aliasstream[astream_i++] = '"';
+				astream_i += IConsoleCopyInParams(&aliasstream[astream_i], tokens[param], astream_i);
+				aliasstream[astream_i++] = '"';
+			} break;
+			} break;
+
+		default:
+			aliasstream[astream_i++] = *cmdptr;
 			break;
-		case ICONSOLE_VAR_POINTER:
-		case ICONSOLE_VAR_STRING:
-			// needs no memory ... it gets memory when it is set to an value
-			item->data.addr = NULL;
-			item->_malloc = false;
-			break;
-		default:
-			error("unknown console variable type");
-			break;
+		}
 	}
 
-	item->hook_access = NULL;
-	item->hook_after_change = NULL;
-	item->hook_before_change = NULL;
-	return item;
-}
-
-
-void IConsoleVarFree(_iconsole_var* var)
-{
-	if (var->_malloc)
-		free(var->data.addr);
-	free(var->name);
-	free(var);
-}
-
-void IConsoleVarSetString(_iconsole_var* var, const char* string)
-{
-	if (string == NULL) return;
-
-	if (var->_malloc)
-		free(var->data.string_);
-
-	var->data.string_ = strdup(string);
-	var->_malloc = true;
+	for (i = 0; i <= (int)a_index; i++) IConsoleCmdExec(aliases[i]); // execute each alias in turn
 }
 
-void IConsoleVarSetValue(_iconsole_var* var, int value) {
+/**
+ * Special function for adding string-type variables. They in addition
+ * also need a 'size' value saying how long their string buffer is.
+ * @param size the length of the string buffer
+ * For more information see @IConsoleVarRegister()
+ */
+void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help)
+{
+	IConsoleVar *var;
+	IConsoleVarRegister(name, addr, ICONSOLE_VAR_STRING, help);
+	var = IConsoleVarGet(name);
+	var->size = size;
+}
+
+/**
+ * Register a new variable to be used in the console
+ * @param name name of the variable that will be used
+ * @param addr memory location the variable will point to
+ * @param help the help string shown for the variable
+ * @param type the type of the variable (simple atomic) so we know which values it can get
+ */
+void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help)
+{
+	char *new_cmd = strdup(name);
+	IConsoleVar *item_new = malloc(sizeof(IConsoleVar));
+
+	item_new->help = (help != NULL) ? strdup(help) : NULL;
+
+	item_new->next = NULL;
+	item_new->name = new_cmd;
+	item_new->addr = addr;
+	item_new->proc = NULL;
+	item_new->type = type;
+
+	item_new->hook.access = NULL;
+	item_new->hook.pre = NULL;
+	item_new->hook.post = NULL;
+
+	IConsoleAddSorted(_iconsole_vars, item_new, IConsoleVar, "a variable");
+}
+
+/**
+ * Find the variable pointed to by its string
+ * @param name variable to be found
+ * @return return Varstruct of the found variable, or NULL on failure
+ */
+IConsoleVar *IConsoleVarGet(const char *name)
+{
+	IConsoleVar *item;
+	for (item = _iconsole_vars; item != NULL; item = item->next) {
+		if (strcmp(item->name, name) == 0) return item;
+	}
+
+	return NULL;
+}
+
+/**
+ * Set a new value to a console variable
+ * @param *var the variable being set/changed
+ * @param value the new value given to the variable, cast properly
+ */
+static void IConsoleVarSetValue(const IConsoleVar *var, uint32 value)
+{
 	switch (var->type) {
 		case ICONSOLE_VAR_BOOLEAN:
-			*var->data.bool_ = (value != 0);
+			*(bool*)var->addr = (value != 0);
 			break;
 		case ICONSOLE_VAR_BYTE:
-		case ICONSOLE_VAR_UINT8:
-			*var->data.byte_ = value;
+			*(byte*)var->addr = (byte)value;
 			break;
 		case ICONSOLE_VAR_UINT16:
-			*var->data.uint16_ = value;
+			*(uint16*)var->addr = (byte)value;
+			break;
+		case ICONSOLE_VAR_INT16:
+			*(int16*)var->addr = (int16)value;
 			break;
 		case ICONSOLE_VAR_UINT32:
-			*var->data.uint32_ = value;
-			break;
-		case ICONSOLE_VAR_INT16:
-			*var->data.int16_ = value;
+			*(uint32*)var->addr = (uint32)value;
 			break;
 		case ICONSOLE_VAR_INT32:
-			*var->data.int32_ = value;
+			*(int32*)var->addr = (int32)value;
 			break;
-		default:
-			assert(0);
-			break;
+		default: NOT_REACHED();
 	}
+
+	IConsoleVarPrintSetValue(var);
 }
 
-void IConsoleVarDump(const _iconsole_var* var, const char* dump_desc)
+/**
+ * Set a new value to a string-type variable. Basically this
+ * means to copy the new value over to the container.
+ * @param *var the variable in question
+ * @param *value the new value
+ */
+static void IConsoleVarSetStringvalue(const IConsoleVar *var, char *value)
 {
-	if (var == NULL) return;
-	if (dump_desc == NULL) dump_desc = var->name;
+	if (var->type != ICONSOLE_VAR_STRING || var->addr == NULL) return;
+
+	ttd_strlcpy((char*)var->addr, (char*)value, var->size);
+	IConsoleVarPrintSetValue(var); // print out the new value, giving feedback
+	return;
+}
+
+/**
+ * Query the current value of a variable and return it
+ * @param *var the variable queried
+ * @return current value of the variable
+ */
+static uint32 IConsoleVarGetValue(const IConsoleVar *var)
+{
+	uint32 result = 0;
 
 	switch (var->type) {
 		case ICONSOLE_VAR_BOOLEAN:
-			IConsolePrintF(_iconsole_color_default, "%s = %s",
-				dump_desc, *var->data.bool_ ? "true" : "false");
+			result = *(bool*)var->addr;
 			break;
 		case ICONSOLE_VAR_BYTE:
-		case ICONSOLE_VAR_UINT8:
-			IConsolePrintF(_iconsole_color_default, "%s = %u",
-				dump_desc, *var->data.byte_);
+			result = *(byte*)var->addr;
 			break;
 		case ICONSOLE_VAR_UINT16:
-			IConsolePrintF(_iconsole_color_default, "%s = %u",
-				dump_desc, *var->data.uint16_);
-			break;
-		case ICONSOLE_VAR_UINT32:
-			IConsolePrintF(_iconsole_color_default, "%s = %u",
-				dump_desc, *var->data.uint32_);
+			result = *(uint16*)var->addr;
 			break;
 		case ICONSOLE_VAR_INT16:
-			IConsolePrintF(_iconsole_color_default, "%s = %i",
-				dump_desc, *var->data.int16_);
+			result = *(int16*)var->addr;
+			break;
+		case ICONSOLE_VAR_UINT32:
+			result = *(uint32*)var->addr;
 			break;
 		case ICONSOLE_VAR_INT32:
-			IConsolePrintF(_iconsole_color_default, "%s = %i",
-				dump_desc, *var->data.int32_);
+			result = *(int32*)var->addr;
+			break;
+		default: NOT_REACHED();
+	}
+	return result;
+}
+
+/**
+ * Get the value of the variable and put it into a printable
+ * string form so we can use it for printing
+ */
+static char *IConsoleVarGetStringValue(const IConsoleVar *var)
+{
+	static char tempres[50];
+	char *value = tempres;
+
+	switch (var->type) {
+		case ICONSOLE_VAR_BOOLEAN:
+			snprintf(tempres, sizeof(tempres), "%s", (*(bool*)var->addr) ? "on" : "off");
+			break;
+		case ICONSOLE_VAR_BYTE:
+			snprintf(tempres, sizeof(tempres), "%u", *(byte*)var->addr);
+			break;
+		case ICONSOLE_VAR_UINT16:
+			snprintf(tempres, sizeof(tempres), "%u", *(uint16*)var->addr);
+			break;
+		case ICONSOLE_VAR_UINT32:
+			snprintf(tempres, sizeof(tempres), "%u",  *(uint32*)var->addr);
+			break;
+		case ICONSOLE_VAR_INT16:
+			snprintf(tempres, sizeof(tempres), "%i", *(int16*)var->addr);
+			break;
+		case ICONSOLE_VAR_INT32:
+			snprintf(tempres, sizeof(tempres), "%i",  *(int32*)var->addr);
 			break;
 		case ICONSOLE_VAR_STRING:
-			IConsolePrintF(_iconsole_color_default, "%s = %s",
-				dump_desc, var->data.string_);
-			break;
-		case ICONSOLE_VAR_REFERENCE:
-			IConsolePrintF(_iconsole_color_default, "%s = @%s",
-				dump_desc, var->data.reference_);
-		case ICONSOLE_VAR_UNKNOWN:
-		case ICONSOLE_VAR_POINTER:
-			IConsolePrintF(_iconsole_color_default, "%s = @%p",
-				dump_desc, var->data.addr);
-			break;
-		case ICONSOLE_VAR_NONE:
-			IConsolePrintF(_iconsole_color_default, "%s = [nothing]",
-				dump_desc);
-			break;
+			value = (char*)var->addr;
+		default: NOT_REACHED();
 	}
+
+	return value;
+}
+
+/**
+ * Print out the value of the variable when asked
+ */
+void IConsoleVarPrintGetValue(const IConsoleVar *var)
+{
+	char *value;
+	/* Some variables need really specific handling, handle this in its
+	 * callback function */
+	if (var->proc != NULL) {
+		var->proc(0, NULL);
+		return;
+	}
+
+	value = IConsoleVarGetStringValue(var);
+	IConsolePrintF(_iconsole_color_warning, "Current value for '%s' is:  %s", var->name, value);
+}
+
+/**
+ * Print out the value of the variable after it has been assigned
+ * a new value, thus giving us feedback on the action
+ */
+void IConsoleVarPrintSetValue(const IConsoleVar *var)
+{
+	char *value = IConsoleVarGetStringValue(var);
+	IConsolePrintF(_iconsole_color_warning, "'%s' changed to:  %s", var->name, value);
+}
+
+/**
+ * Execute a variable command. Without any parameters, print out its value
+ * with parameters it assigns a new value to the variable
+ * @param *var the variable that we will be querying/changing
+ * @param tokencount how many additional parameters have been given to the commandline
+ * @param *token the actual parameters the variable was called with
+ */
+void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[ICON_TOKEN_COUNT])
+{
+	const char *tokenptr = token[0];
+	byte t_index = tokencount;
+	uint32 value;
+
+	if (tokencount == 0) { /* Just print out value */
+		IConsoleVarPrintGetValue(var);
+		return;
+	}
+
+	/* Use of assignment sign is not mandatory but supported, so just 'ignore it appropiately' */
+	if (strcmp(tokenptr, "=") == 0) tokencount--;
+
+	if (tokencount == 1) {
+		/* Some variables need really special handling, handle it in their callback procedure */
+		if (var->proc != NULL) {
+			var->proc(tokencount, &token[t_index - tokencount]); // set the new value
+			var->proc(0, NULL); // print out new value
+			return;
+		}
+		/* Strings need special processing. No need to convert the argument to
+		 * an integer value, just copy over the argument on a one-by-one basis */
+		if (var->type == ICONSOLE_VAR_STRING) {
+			IConsoleVarSetStringvalue(var, token[t_index - tokencount]);
+			return;
+		} else if (GetArgumentInteger(&value, token[t_index - tokencount])) {
+			IConsoleVarSetValue(var, value);
+			return;
+		}
+
+		/* Increase or decrease the value by one. This of course can only happen to 'number' types */
+		if (strcmp(tokenptr, "++") == 0 && var->type != ICONSOLE_VAR_STRING) {
+			IConsoleVarSetValue(var, IConsoleVarGetValue(var) + 1);
+			return;
+		}
+
+		if (strcmp(tokenptr, "--") == 0 && var->type != ICONSOLE_VAR_STRING) {
+			IConsoleVarSetValue(var, IConsoleVarGetValue(var) - 1);
+			return;
+		}
+	}
+
+	IConsoleError("invalid variable assignment");
 }
 
 // * ************************* * //
 // * hooking code              * //
 // * ************************* * //
+/**
+ * General internal hooking code that is the same for both commands and variables
+ * @param hooks @IConsoleHooks structure that will be set according to
+ * @param type type access trigger
+ * @param proc function called when the hook criteria is met
+ */
+static void IConsoleHookAdd(IConsoleHooks *hooks, IConsoleHookTypes type, IConsoleHook *proc)
+{
+	if (hooks == NULL || proc == NULL) return;
 
-void IConsoleVarHook(const char* name, _iconsole_hook_types type, iconsole_var_hook proc)
-{
-	_iconsole_var* hook_var = IConsoleVarGet(name);
-	if (hook_var == NULL) return;
 	switch (type) {
-		case ICONSOLE_HOOK_BEFORE_CHANGE:
-			hook_var->hook_before_change = proc;
-			break;
-		case ICONSOLE_HOOK_AFTER_CHANGE:
-			hook_var->hook_after_change = proc;
-			break;
-		case ICONSOLE_HOOK_ACCESS:
-			hook_var->hook_access = proc;
-			break;
-		case ICONSOLE_HOOK_BEFORE_EXEC:
-		case ICONSOLE_HOOK_AFTER_EXEC:
-			assert(0);
-			break;
+	case ICONSOLE_HOOK_ACCESS:
+		hooks->access = proc;
+		break;
+	case ICONSOLE_HOOK_PRE_ACTION:
+		hooks->pre = proc;
+		break;
+	case ICONSOLE_HOOK_POST_ACTION:
+		hooks->post = proc;
+		break;
+	default: NOT_REACHED();
 	}
 }
 
-bool IConsoleVarHookHandle(_iconsole_var* hook_var, _iconsole_hook_types type)
+/**
+ * Handle any special hook triggers. If the hook type is met check if
+ * there is a function associated with that and if so, execute it
+ * @param hooks @IConsoleHooks structure that will be checked
+ * @param type type of hook, trigger that needs to be activated
+ * @return true on a successfull execution of the hook command or if there
+ * is no hook/trigger present at all. False otherwise
+ */
+static bool IConsoleHookHandle(IConsoleHooks *hooks, IConsoleHookTypes type)
 {
-	iconsole_var_hook proc;
-	if (hook_var == NULL) return false;
+	IConsoleHook *proc = NULL;
+	if (hooks == NULL) return false;
 
-	proc = NULL;
 	switch (type) {
-		case ICONSOLE_HOOK_BEFORE_CHANGE:
-			proc = hook_var->hook_before_change;
-			break;
-		case ICONSOLE_HOOK_AFTER_CHANGE:
-			proc = hook_var->hook_after_change;
-			break;
-		case ICONSOLE_HOOK_ACCESS:
-			proc = hook_var->hook_access;
-			break;
-		case ICONSOLE_HOOK_BEFORE_EXEC:
-		case ICONSOLE_HOOK_AFTER_EXEC:
-			assert(0);
-			break;
+	case ICONSOLE_HOOK_ACCESS:
+		proc = hooks->access;
+		break;
+	case ICONSOLE_HOOK_PRE_ACTION:
+		proc = hooks->pre;
+		break;
+	case ICONSOLE_HOOK_POST_ACTION:
+		proc = hooks->post;
+		break;
+	default: NOT_REACHED();
 	}
-	return proc == NULL ? true : proc(hook_var);
-}
 
-void IConsoleCmdHook(const char* name, _iconsole_hook_types type, iconsole_cmd_hook proc)
-{
-	_iconsole_cmd* hook_cmd = IConsoleCmdGet(name);
-	if (hook_cmd == NULL) return;
-	switch (type) {
-		case ICONSOLE_HOOK_AFTER_EXEC:
-			hook_cmd->hook_after_exec = proc;
-			break;
-		case ICONSOLE_HOOK_BEFORE_EXEC:
-			hook_cmd->hook_before_exec = proc;
-			break;
-		case ICONSOLE_HOOK_ACCESS:
-			hook_cmd->hook_access = proc;
-			break;
-		case ICONSOLE_HOOK_BEFORE_CHANGE:
-		case ICONSOLE_HOOK_AFTER_CHANGE:
-			assert(0);
-			break;
-	}
+	return (proc == NULL) ? true : proc();
 }
 
-bool IConsoleCmdHookHandle(_iconsole_cmd* hook_cmd, _iconsole_hook_types type)
+/**
+ * Add a hook to a command that will be triggered at certain points
+ * @param name name of the command that the hook is added to
+ * @param type type of hook that is added (ACCESS, BEFORE and AFTER change)
+ * @param proc function called when the hook criteria is met
+ */
+void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
 {
-	iconsole_cmd_hook proc = NULL;
-	switch (type) {
-		case ICONSOLE_HOOK_AFTER_EXEC:
-			proc = hook_cmd->hook_after_exec;
-			break;
-		case ICONSOLE_HOOK_BEFORE_EXEC:
-			proc = hook_cmd->hook_before_exec;
-			break;
-		case ICONSOLE_HOOK_ACCESS:
-			proc = hook_cmd->hook_access;
-			break;
-		case ICONSOLE_HOOK_BEFORE_CHANGE:
-		case ICONSOLE_HOOK_AFTER_CHANGE:
-			assert(0);
-			break;
-	}
-	return proc == NULL ? true : proc(hook_cmd);
+	IConsoleCmd *cmd = IConsoleCmdGet(name);
+	if (cmd == NULL) return;
+	IConsoleHookAdd(&cmd->hook, type, proc);
 }
 
-void IConsoleCmdExec(const char* cmdstr)
+/**
+ * Add a hook to a variable that will be triggered at certain points
+ * @param name name of the variable that the hook is added to
+ * @param type type of hook that is added (ACCESS, BEFORE and AFTER change)
+ * @param proc function called when the hook criteria is met
+ */
+void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc)
 {
-	_iconsole_cmd_addr function;
-	char* tokens[20];
-	byte  tokentypes[20];
-	char* tokenstream;
-	char* tokenstream_s;
-	byte  execution_mode;
-	_iconsole_var* var     = NULL;
-	_iconsole_var* result  = NULL;
-	_iconsole_cmd* cmd     = NULL;
-	_iconsole_alias* alias = NULL;
+	IConsoleVar *var = IConsoleVarGet(name);
+	if (var == NULL) return;
+	IConsoleHookAdd(&var->hook, type, proc);
+}
 
-	bool longtoken;
-	bool valid_token;
-	bool skip_lt_change;
-
-	uint c;
-	uint i;
-	uint l;
+/**
+ * Add a callback function to the variable. Some variables need
+ * very special processing, which can only be done with custom code
+ * @param name name of the variable the callback function is added to
+ * @param proc the function called
+ */
+void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc)
+{
+	IConsoleVar *var = IConsoleVarGet(name);
+	if (var == NULL) return;
+	var->proc = proc;
+}
 
-	for (; strchr("\n\r \t", *cmdstr) != NULL; ++cmdstr) {
-		switch (*cmdstr) {
-			case '\0':
-			case '#':
-				return;
+/**
+ * Execute a given command passed to us. First chop it up into
+ * individual tokens (seperated by spaces), then execute it if possible
+ * @param cmdstr string to be parsed and executed
+ */
+void IConsoleCmdExec(const char *cmdstr)
+{
+	IConsoleCmd   *cmd    = NULL;
+	IConsoleAlias *alias  = NULL;
+	IConsoleVar   *var    = NULL;
 
-			default:
-				break;
+	const char *cmdptr;
+	char *tokens[ICON_TOKEN_COUNT], tokenstream[ICON_MAX_STREAMSIZE];
+	uint t_index, tstream_i;
+
+	bool longtoken = false;
+	bool foundtoken = false;
+
+	for (cmdptr = cmdstr; *cmdptr != '\0'; *cmdptr++) {
+		if (!IsValidAsciiChar(*cmdptr)) {
+			IConsoleError("command contains malformed characters, aborting");
+			return;
 		}
 	}
 
 	if (_stdlib_con_developer)
-		IConsolePrintF(_iconsole_color_debug, "CONDEBUG: execution_cmdline: %s", cmdstr);
-
-	//** clearing buffer **//
-
-	for (i = 0; i < 20; i++) {
-		tokens[i] = NULL;
-		tokentypes[i] = ICONSOLE_VAR_NONE;
-	}
-	tokenstream_s = tokenstream = malloc(1024);
-	memset(tokenstream, 0, 1024);
-
-	//** parsing **//
-
-	longtoken = false;
-	valid_token = false;
-	skip_lt_change = false;
-	l = strlen(cmdstr);
-	i = 0;
-	c = 0;
-	tokens[c] = tokenstream;
-	tokentypes[c] = ICONSOLE_VAR_UNKNOWN;
-	while (i < l && c < lengthof(tokens) - 1) {
-		if (cmdstr[i] == '"') {
-			if (longtoken) {
-				if (cmdstr[i + 1] == '"') {
-					i++;
-					*tokenstream = '"';
-					tokenstream++;
-					skip_lt_change = true;
-				} else {
-					longtoken = !longtoken;
-					tokentypes[c] = ICONSOLE_VAR_STRING;
-				}
-			} else {
-				longtoken = !longtoken;
-				tokentypes[c] = ICONSOLE_VAR_STRING;
-			}
-			if (!skip_lt_change) {
-				if (!longtoken) {
-					if (valid_token) {
-						c++;
-						*tokenstream = '\0';
-						tokenstream++;
-						tokens[c] = tokenstream;
-						tokentypes[c] = ICONSOLE_VAR_UNKNOWN;
-						valid_token = false;
-					}
-				}
-				skip_lt_change=false;
-			}
-		} else if (!longtoken && cmdstr[i] == ' ') {
-			if (valid_token) {
-				c++;
-				*tokenstream = '\0';
-				tokenstream++;
-				tokens[c] = tokenstream;
-				tokentypes[c] = ICONSOLE_VAR_UNKNOWN;
-				valid_token = false;
-			}
-		} else {
-			valid_token = true;
-			*tokenstream = cmdstr[i];
-			tokenstream++;
-		}
-		i++;
-	}
+		IConsolePrintF(_iconsole_color_debug, "condbg: executing cmdline: '%s'", cmdstr);
 
-	tokenstream--;
-	if (*tokenstream != '\0') {
-		c++;
-		tokenstream++;
-		*tokenstream = '\0';
-	}
-
-	//** interpreting **//
+	memset(&tokens, 0, sizeof(tokens));
+	memset(&tokenstream, 0, sizeof(tokenstream));
 
-	for (i = 0; i < c; i++) {
-		if (tokens[i] != NULL && i > 0 && strlen(tokens[i]) > 0) {
-			if (IConsoleVarGet((char *)tokens[i]) != NULL) {
-				// change the variable to an pointer if execution_mode != 4 is
-				// being prepared. execution_mode 4 is used to assign
-				// one variables data to another one
-				// [token 0 and 2]
-				if (!((i == 2) && (tokentypes[1] == ICONSOLE_VAR_UNKNOWN) &&
-					(strcmp(tokens[1], "<<") == 0))) {
-					// only look for another variable if it isnt an longtoken == string with ""
-					var = NULL;
-					if (tokentypes[i]!=ICONSOLE_VAR_STRING) var = IConsoleVarGet(tokens[i]);
-					if (var != NULL) {
-						// pointer to the data --> token
-						tokens[i] = (char *) var->data.addr; /* XXX: maybe someone finds an cleaner way to do this */
-						tokentypes[i] = var->type;
-					}
-				}
+	/* 1. Split up commandline into tokens, seperated by spaces, commands
+	 * enclosed in "" are taken as one token. We can only go as far as the amount
+	 * of characters in our stream or the max amount of tokens we can handle */
+	tokens[0] = tokenstream;
+	for (cmdptr = cmdstr, t_index = 0, tstream_i = 0; *cmdptr != '\0'; *cmdptr++) {
+		if (t_index >= lengthof(tokens) || tstream_i >= lengthof(tokenstream)) break;
+
+		switch (*cmdptr) {
+		case ' ': /* Token seperator */
+			if (!foundtoken) break;
+
+			tokenstream[tstream_i] = (longtoken) ? *cmdptr : '\0';
+
+			tstream_i++;
+			foundtoken = false;
+			break;
+		case '"': /* Tokens enclosed in "" are one token */
+			longtoken = !longtoken;
+			break;
+		default: /* Normal character */
+			tokenstream[tstream_i++] = *cmdptr;
+
+			if (!foundtoken) {
+				tokens[t_index++] = &tokenstream[tstream_i - 1];
+				foundtoken = true;
 			}
-			if (tokens[i] != NULL && tokens[i][0] == '@' && (IConsoleVarGet(tokens[i]+1) != NULL)) {
-				var = IConsoleVarGet(tokens[i]+1);
-				if (var != NULL) {
-					// pointer to the _iconsole_var struct --> token
-					tokens[i] = (char *) var; /* XXX: maybe someone finds an cleaner way to do this */
-					tokentypes[i] = ICONSOLE_VAR_REFERENCE;
-				}
-			}
-		}
-	}
-
-	execution_mode=0;
-
-	function = NULL;
-	cmd = IConsoleCmdGet(tokens[0]);
-	if (cmd != NULL) {
-		function = cmd->addr;
-	} else {
-		alias = IConsoleAliasGet(tokens[0]);
-		if (alias != NULL) execution_mode = 5; // alias handling
-	}
-
-	if (function != NULL) {
-		execution_mode = 1; // this is a command
-	} else {
-		var = IConsoleVarGet(tokens[0]);
-		if (var != NULL) {
-			execution_mode = 2; // this is a variable
-			if (c > 2 && strcmp(tokens[1], "<<") == 0) {
-				// this is command to variable mode [normal]
-
-				function = NULL;
-				cmd = IConsoleCmdGet(tokens[2]);
-				if (cmd != NULL) function = cmd->addr;
-
-				if (function != NULL) {
-					execution_mode = 3;
-				} else {
-					result = IConsoleVarGet(tokens[2]);
-					if (result != NULL)
-						execution_mode = 4;
-				}
-			}
+			break;
 		}
 	}
 
-	//** executing **//
-	if (_stdlib_con_developer)
-		IConsolePrintF(_iconsole_color_debug, "CONDEBUG: execution_mode: %i",
-			execution_mode);
-	switch (execution_mode) {
-		case 0:
-			// not found
-			IConsoleError("command or variable not found");
-			break;
-		case 1:
-			if (IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_ACCESS)) {
-				// execution with command syntax
-				IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_BEFORE_EXEC);
-				result = function(c, tokens, tokentypes);
-				if (result != NULL) {
-					IConsoleVarDump(result, "result");
-					IConsoleVarFree(result);
-				}
-				IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_AFTER_EXEC);
-				break;
-			}
-		case 2:
-		{
-			// execution with variable syntax
-			if (IConsoleVarHookHandle(var, ICONSOLE_HOOK_ACCESS) && (c == 2 || c == 3)) {
-				// ** variable modifications ** //
-				IConsoleVarHookHandle(var, ICONSOLE_HOOK_BEFORE_CHANGE);
-				switch (var->type) {
-					case ICONSOLE_VAR_BOOLEAN:
-					{
-						if (strcmp(tokens[1], "=") == 0) {
-							if (c == 3) {
-								*var->data.bool_ = (atoi(tokens[2]) != 0);
-							} else {
-								*var->data.bool_ = false;
-							}
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "++") == 0) {
-							*var->data.bool_ = true;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "--") == 0) {
-							*var->data.bool_ = false;
-							IConsoleVarDump(var, NULL);
-						}
-						else
-							IConsoleError("operation not supported");
-						break;
-					}
-					case ICONSOLE_VAR_BYTE:
-					case ICONSOLE_VAR_UINT8:
-					{
-						if (strcmp(tokens[1], "=") == 0) {
-							if (c == 3)
-								*var->data.byte_ = atoi(tokens[2]);
-							else
-								*var->data.byte_ = 0;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "++") == 0) {
-							++*var->data.byte_;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "--")==0) {
-							--*var->data.byte_;
-							IConsoleVarDump(var, NULL);
-						}
-						else
-							IConsoleError("operation not supported");
-						break;
-					}
-					case ICONSOLE_VAR_UINT16:
-					{
-						if (strcmp(tokens[1], "=") == 0) {
-							if (c == 3)
-								*var->data.uint16_ = atoi(tokens[2]);
-							else
-								*var->data.uint16_ = 0;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "++") == 0) {
-							++*var->data.uint16_;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "--") == 0) {
-							--*var->data.uint16_;
-							IConsoleVarDump(var, NULL);
-						}
-						else
-							IConsoleError("operation not supported");
-						break;
-					}
-					case ICONSOLE_VAR_UINT32:
-					{
-						if (strcmp(tokens[1], "=") == 0) {
-							if (c == 3)
-								*var->data.uint32_ = atoi(tokens[2]);
-							else
-								*var->data.uint32_ = 0;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "++") == 0) {
-							++*var->data.uint32_;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "--") == 0) {
-							--*var->data.uint32_;
-							IConsoleVarDump(var, NULL);
-						}
-						else
-							IConsoleError("operation not supported");
-						break;
-					}
-					case ICONSOLE_VAR_INT16:
-					{
-						if (strcmp(tokens[1], "=") == 0) {
-							if (c == 3)
-								*var->data.int16_ = atoi(tokens[2]);
-							else
-								*var->data.int16_ = 0;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "++") == 0) {
-							++*var->data.int16_;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "--") == 0) {
-							--*var->data.int16_;
-							IConsoleVarDump(var, NULL);
-						}
-						else
-							IConsoleError("operation not supported");
-						break;
-					}
-					case ICONSOLE_VAR_INT32:
-					{
-						if (strcmp(tokens[1], "=") == 0) {
-							if (c == 3)
-								*var->data.int32_ = atoi(tokens[2]);
-							else
-								*var->data.int32_ = 0;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "++") == 0) {
-							++*var->data.int32_;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "--") == 0) {
-							--*var->data.int32_;
-							IConsoleVarDump(var, NULL);
-						}
-						else { IConsoleError("operation not supported"); }
-						break;
-					}
-					case ICONSOLE_VAR_STRING:
-					{
-						if (strcmp(tokens[1], "=") == 0) {
-							if (c == 3)
-								IConsoleVarSetString(var, tokens[2]);
-							else
-								IConsoleVarSetString(var, "");
-							IConsoleVarDump(var, NULL);
-						}
-						else
-							IConsoleError("operation not supported");
-						break;
-					}
-					case ICONSOLE_VAR_POINTER:
-					{
-						if (strcmp(tokens[1], "=") == 0) {
-							if (c == 3) {
-								if (tokentypes[2] == ICONSOLE_VAR_UNKNOWN)
-									var->data.addr = (void*)atoi(tokens[2]); /* direct access on memory [by address] */
-								else
-									var->data.addr = (void*)tokens[2]; /* direct acces on memory [by variable] */
-							} else
-								var->data.addr = NULL;
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "++") == 0) {
-							++*(char*)&var->data.addr; /* change the address + 1 */
-							IConsoleVarDump(var, NULL);
-						} else if (strcmp(tokens[1], "--") == 0) {
-							--*(char*)&var->data.addr; /* change the address - 1 */
-							IConsoleVarDump(var, NULL);
-						}
-						else
-							IConsoleError("operation not supported");
-						break;
-					}
-					case ICONSOLE_VAR_NONE:
-					case ICONSOLE_VAR_REFERENCE:
-					case ICONSOLE_VAR_UNKNOWN:
-						IConsoleError("operation not supported");
-						break;
-				}
-				IConsoleVarHookHandle(var, ICONSOLE_HOOK_AFTER_CHANGE);
-			}
-			if (c == 1) // ** variable output ** //
-				IConsoleVarDump(var, NULL);
-			break;
-		}
-		case 3:
-		case 4:
-		{
-			// execute command with result or assign a variable
-			if (execution_mode == 3) {
-				if (IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_ACCESS)) {
-					int i;
-					int diff;
-					void* temp;
-					byte temp2;
-
-					// tokenshifting
-					for (diff = 0; diff < 2; diff++) {
-						temp = tokens[0];
-						temp2 = tokentypes[0];
-						for (i = 0; i < 19; i++) {
-							tokens[i] = tokens[i + 1];
-							tokentypes[i] = tokentypes[i + 1];
-						}
-						tokens[19] = temp;
-						tokentypes[19] = temp2;
-					}
-					IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_BEFORE_EXEC);
-					result = function(c, tokens, tokentypes);
-					IConsoleCmdHookHandle(cmd, ICONSOLE_HOOK_AFTER_EXEC);
-				} else
-					execution_mode = 255;
-			}
-
-			if (IConsoleVarHookHandle(var, ICONSOLE_HOOK_ACCESS) && result != NULL) {
-				if (result->type != var->type) {
-					IConsoleError("variable type missmatch");
-				} else {
-					IConsoleVarHookHandle(var, ICONSOLE_HOOK_BEFORE_CHANGE);
-					switch (result->type) {
-						case ICONSOLE_VAR_BOOLEAN:
-							*var->data.bool_ = *result->data.bool_;
-							IConsoleVarDump(var, NULL);
-							break;
-						case ICONSOLE_VAR_BYTE:
-						case ICONSOLE_VAR_UINT8:
-							*var->data.byte_ = *result->data.byte_;
-							IConsoleVarDump(var, NULL);
-							break;
-						case ICONSOLE_VAR_UINT16:
-							*var->data.uint16_ = *result->data.uint16_;
-							IConsoleVarDump(var, NULL);
-							break;
-						case ICONSOLE_VAR_UINT32:
-							*var->data.uint32_ = *result->data.uint32_;
-							IConsoleVarDump(var, NULL);
-							break;
-						case ICONSOLE_VAR_INT16:
-							*var->data.int16_ = *result->data.int16_;
-							IConsoleVarDump(var, NULL);
-							break;
-						case ICONSOLE_VAR_INT32:
-							*var->data.int32_ = *result->data.int32_;
-							IConsoleVarDump(var, NULL);
-							break;
-						case ICONSOLE_VAR_POINTER:
-							var->data.addr = result->data.addr;
-							IConsoleVarDump(var, NULL);
-							break;
-						case ICONSOLE_VAR_STRING:
-							IConsoleVarSetString(var, result->data.string_);
-							IConsoleVarDump(var, NULL);
-							break;
-						default:
-							IConsoleError("variable type missmatch");
-							break;
-					}
-					IConsoleVarHookHandle(var, ICONSOLE_HOOK_AFTER_CHANGE);
-				}
-
-				if (execution_mode == 3) {
-					IConsoleVarFree(result);
-				}
-			}
-			break;
-		}
-		case 5: {
-			// execute an alias
-			IConsoleAliasExec(alias->cmdline, tokens,tokentypes);
-			}
-			break;
-		default:
-			// execution mode invalid
-			IConsoleError("invalid execution mode");
-			break;
+	if (_stdlib_con_developer) {
+		uint i;
+		for (i = 0; tokens[i] != NULL; i++)
+			IConsolePrintF(_iconsole_color_debug, "condbg: token %d is: '%s'", i, tokens[i]);
 	}
 
-	//** freeing the tokenstream **//
-	free(tokenstream_s);
+	/* 2. Determine type of command (cmd, alias or variable) and execute
+	 * First try commands, then aliases, and finally variables. Execute
+	 * the found action taking into account its hooking code
+	 */
+	 cmd = IConsoleCmdGet(tokens[0]);
+	 if (cmd != NULL) {
+		if (IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_ACCESS)) {
+			IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_PRE_ACTION);
+			if (cmd->proc(t_index, tokens)) { // index started with 0
+				IConsoleHookHandle(&cmd->hook, ICONSOLE_HOOK_POST_ACTION);
+  		} else cmd->proc(0, NULL); // if command failed, give help
+		}
+	 	return;
+	 }
+
+	 t_index--; // ignore the variable-name for comfort for both aliases and variaables
+	 alias = IConsoleAliasGet(tokens[0]);
+	 if (alias != NULL) {
+	 	IConsoleAliasExec(alias, t_index, &tokens[1]);
+	 	return;
+	 }
+
+	 var = IConsoleVarGet(tokens[0]);
+	 if (var != NULL) {
+	 	if (IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_ACCESS)) {
+	 		IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_PRE_ACTION);
+	 		IConsoleVarExec(var, t_index, &tokens[1]);
+	 		if (t_index != 0) // value has indeed been changed
+	 			IConsoleHookHandle(&var->hook, ICONSOLE_HOOK_POST_ACTION);
+	 	}
+	 	return;
+	 }
+
+	 IConsoleError("command or variable not found");
 }
--- a/console.h	Sun May 01 20:16:52 2005 +0000
+++ b/console.h	Mon May 02 15:52:19 2005 +0000
@@ -1,108 +1,118 @@
 #ifndef CONSOLE_H
 #define CONSOLE_H
 
-// ** console parser ** //
+// maximum length of a typed in command
+#define ICON_CMDLN_SIZE 255
+// maximum length of a totally expanded command
+#define ICON_MAX_STREAMSIZE 1024
 
-typedef enum _iconsole_var_types {
-	ICONSOLE_VAR_NONE,
+typedef enum IConsoleVarTypes {
 	ICONSOLE_VAR_BOOLEAN,
 	ICONSOLE_VAR_BYTE,
-	ICONSOLE_VAR_UINT8,
 	ICONSOLE_VAR_UINT16,
 	ICONSOLE_VAR_UINT32,
 	ICONSOLE_VAR_INT16,
 	ICONSOLE_VAR_INT32,
-	ICONSOLE_VAR_STRING,
-	ICONSOLE_VAR_POINTER,
-	ICONSOLE_VAR_REFERENCE,
-	ICONSOLE_VAR_UNKNOWN
-} _iconsole_var_types;
+	ICONSOLE_VAR_STRING
+} IConsoleVarTypes;
 
-typedef enum {
+typedef enum IConsoleModes {
 	ICONSOLE_FULL,
 	ICONSOLE_OPENED,
 	ICONSOLE_CLOSED
-} _iconsole_modes;
-
-typedef enum _iconsole_hook_types {
-	ICONSOLE_HOOK_ACCESS,
-	ICONSOLE_HOOK_BEFORE_CHANGE,
-	ICONSOLE_HOOK_BEFORE_EXEC,
-	ICONSOLE_HOOK_AFTER_CHANGE,
-	ICONSOLE_HOOK_AFTER_EXEC
-} _iconsole_hook_types;
-
-struct _iconsole_var;
-typedef bool (*iconsole_var_hook)(struct _iconsole_var* hook_var);
+} IConsoleModes;
 
-typedef struct _iconsole_var {
-	// --------------- //
-	union {
-		void*   addr;
-		bool*   bool_;
-		byte*   byte_;
-		uint16* uint16_;
-		uint32* uint32_;
-		int16*  int16_;
-		int32*  int32_;
-		char*   string_;
-		struct _iconsole_var* reference_;
-	} data;
-	char* name;
-	_iconsole_var_types type;
-	// -------------- //
-	iconsole_var_hook hook_access;
-	iconsole_var_hook hook_before_change;
-	iconsole_var_hook hook_after_change;
-	// -------------- //
-	struct _iconsole_var* _next;
-	bool _malloc;
-} _iconsole_var;
+typedef enum IConsoleHookTypes {
+	ICONSOLE_HOOK_ACCESS,
+	ICONSOLE_HOOK_PRE_ACTION,
+	ICONSOLE_HOOK_POST_ACTION
+} IConsoleHookTypes;
 
-struct _iconsole_cmd;
-typedef bool (*iconsole_cmd_hook)(struct _iconsole_cmd* hook_cmd);
-
-typedef _iconsole_var* (*_iconsole_cmd_addr)(byte argc, char* argv[], byte argt[]);
+/** --Hooks--
+ * Hooks are certain triggers get get accessed/executed on either
+ * access, before execution/change or after execution/change. This allows
+ * for general flow of permissions or special action needed in some cases
+ */
+typedef bool IConsoleHook(void);
+typedef struct IConsoleHooks{
+	IConsoleHook *access; // trigger when accessing the variable/command
+	IConsoleHook *pre;    // trigger before the variable/command is changed/executed
+	IConsoleHook *post;   // trigger after the variable/command is changed/executed
+} IConsoleHooks;
 
-typedef struct _iconsole_cmd {
-	// -------------- //
-	_iconsole_cmd_addr addr;
-	char* name;
-	// -------------- //
-	iconsole_cmd_hook hook_access;
-	iconsole_cmd_hook hook_before_exec;
-	iconsole_cmd_hook hook_after_exec;
-	// -------------- //
-	void* _next;
-} _iconsole_cmd;
+/** --Commands--
+ * Commands are commands, or functions. They get executed once and any
+ * effect they produce are carried out. The arguments to the commands
+ * are given to them, each input word seperated by a double-quote (") is an argument
+ * If you want to handle multiple words as one, enclose them in double-quotes
+ * eg. 'say "hello sexy boy"'
+ */
+typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
 
-void IConsoleAliasRegister(const char* name, const char* cmdline);
+struct IConsoleCmd;
+typedef struct IConsoleCmd {
+	char *name;               // name of command
+	struct IConsoleCmd *next; // next command in list
 
-typedef struct _iconsole_alias {
-	// -------------- //
-	char * cmdline;
-	char* name;
-	void* _next;
-} _iconsole_alias;
+	IConsoleCmdProc *proc;    // process executed when command is typed
+	IConsoleHooks hook;       // any special trigger action that needs executing
+} IConsoleCmd;
 
-_iconsole_alias* IConsoleAliasGet(const char* name);
+/** --Variables--
+ * Variables are pointers to real ingame variables which allow for
+ * changing while ingame. After changing they keep their new value
+ * and can be used for debugging, gameplay, etc. It accepts:
+ * - no arguments; just print out current value
+ * - '= <new value>' to assign a new value to the variable
+ * - '++' to increase value by one
+ * - '--' to decrease value by one
+ */
+struct IConsoleVar;
+typedef struct IConsoleVar {
+	char *name;               // name of the variable
+	struct IConsoleVar *next; // next variable in list
+
+	void *addr;               // the address where the variable is pointing at
+	uint32 size;              // size of the variable, used for strings
+	char *help;               // the optional help string shown when requesting information
+	IConsoleVarTypes type;    // type of variable (for correct assignment/output)
+	IConsoleCmdProc *proc;    // some variables need really special handling, use a callback function for that
+	IConsoleHooks hook;       // any special trigger action that needs executing
+} IConsoleVar;
+
+/** --Aliases--
+ * Aliases are like shortcuts for complex functions, variable assignments,
+ * etc. You can use a simple alias to rename a longer command (eg 'lv' for
+ * 'list_vars' for example), or concatenate more commands into one
+ * (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
+ * given to them in the command line.
+ * - "%A - %Z" substitute arguments 1 t/m 26
+ * - "%+" lists all parameters keeping them seperated
+ * - "%!" also lists all parameters but presenting them to the aliased command as one argument
+ * - ";" allows for combining commands (see example 'ng')
+ */
+struct IConsoleAlias;
+typedef struct IConsoleAlias {
+	char *name;                 // name of the alias
+	struct IConsoleAlias *next; // next alias in list
+
+	char *cmdline;              // command(s) that is/are being aliased
+} IConsoleAlias;
 
 // ** console parser ** //
+IConsoleCmd   *_iconsole_cmds;    // list of registred commands
+IConsoleVar   *_iconsole_vars;    // list of registred vars
+IConsoleAlias *_iconsole_aliases; // list of registred aliases
 
-_iconsole_cmd* _iconsole_cmds; // list of registred commands
-_iconsole_var* _iconsole_vars; // list of registred vars
-_iconsole_alias* _iconsole_aliases; // list of registred aliases
-
-// ** console colors ** //
+// ** console colors/modes ** //
 VARDEF byte _iconsole_color_default;
 VARDEF byte _iconsole_color_error;
 VARDEF byte _iconsole_color_warning;
 VARDEF byte _iconsole_color_debug;
 VARDEF byte _iconsole_color_commands;
-VARDEF _iconsole_modes _iconsole_mode;
+VARDEF IConsoleModes _iconsole_mode;
 
 // ** console functions ** //
-
 void IConsoleInit(void);
 void IConsoleClear(void);
 void IConsoleFree(void);
@@ -112,44 +122,42 @@
 void IConsoleOpen(void);
 
 // ** console cmd buffer ** //
-void IConsoleCmdBufferAdd(const char* cmd);
-void IConsoleCmdBufferNavigate(signed char direction);
+void IConsoleHistoryAdd(const char *cmd);
+void IConsoleHistoryNavigate(signed char direction);
 
 // ** console output ** //
-void IConsolePrint(uint16 color_code, const char* string);
-void CDECL IConsolePrintF(uint16 color_code, const char* s, ...);
-void IConsoleDebug(const char* string);
-void IConsoleError(const char* string);
-void IConsoleWarning(const char* string);
+void IConsolePrint(uint16 color_code, const char *string);
+void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
+void IConsoleDebug(const char *string);
+void IConsoleWarning(const char *string);
+void IConsoleError(const char *string);
 
 // *** Commands *** //
-
-void IConsoleCmdRegister(const char* name, _iconsole_cmd_addr addr);
-_iconsole_cmd* IConsoleCmdGet(const char* name);
+void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
+void IConsoleAliasRegister(const char *name, const char *cmd);
+IConsoleCmd *IConsoleCmdGet(const char *name);
+IConsoleAlias *IConsoleAliasGet(const char *name);
 
 // *** Variables *** //
-
-void IConsoleVarRegister(const char* name, void* addr, _iconsole_var_types type);
-void IConsoleVarMemRegister(const char* name, _iconsole_var_types type);
-void IConsoleVarInsert(_iconsole_var* item_new, const char* name);
-_iconsole_var* IConsoleVarGet(const char* name);
-_iconsole_var* IConsoleVarAlloc(_iconsole_var_types type);
-void IConsoleVarFree(_iconsole_var* var);
-void IConsoleVarSetString(_iconsole_var* var, const char* string);
-void IConsoleVarSetValue(_iconsole_var* var, int value);
-void IConsoleVarDump(const _iconsole_var* var, const char* dump_desc);
+void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
+void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
+IConsoleVar* IConsoleVarGet(const char *name);
+void IConsoleVarPrintGetValue(const IConsoleVar *var);
+void IConsoleVarPrintSetValue(const IConsoleVar *var);
 
 // *** Parser *** //
+void IConsoleCmdExec(const char *cmdstr);
+void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
+void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[]);
 
-void IConsoleCmdExec(const char* cmdstr);
-
-// ** console std lib ** //
+// ** console std lib (register ingame commands/aliases/variables) ** //
 void IConsoleStdLibRegister(void);
 
-// ** hook code ** //
-void IConsoleVarHook(const char* name, _iconsole_hook_types type, iconsole_var_hook proc);
-void IConsoleCmdHook(const char* name, _iconsole_hook_types type, iconsole_cmd_hook proc);
-bool IConsoleVarHookHandle(_iconsole_var* hook_var, _iconsole_hook_types type);
-bool IConsoleCmdHookHandle(_iconsole_cmd* hook_cmd, _iconsole_hook_types type);
+// ** Hooking code ** //
+void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
+void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
+void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
 
+// ** Supporting functions **//
+bool GetArgumentInteger(uint32 *value, const char *arg);
 #endif /* CONSOLE_H */
--- a/console_cmds.c	Sun May 01 20:16:52 2005 +0000
+++ b/console_cmds.c	Mon May 02 15:52:19 2005 +0000
@@ -1,4 +1,3 @@
-/* -------------------- dont cross this line --------------------- */
 #include "stdafx.h"
 #include "ttd.h"
 #include "console.h"
@@ -15,30 +14,14 @@
 #include "settings.h"
 #include "hal.h" /* for file list */
 
-
 // ** scriptfile handling ** //
-static FILE * _script_file;
+static FILE *_script_file;
 static bool _script_running;
 
 // ** console command / variable defines ** //
-
-#define DEF_CONSOLE_CMD(yyyy) static _iconsole_var * yyyy(byte argc, char* argv[], byte argt[])
-#define DEF_CONSOLE_CMD_HOOK(yyyy) static bool yyyy(_iconsole_cmd * hookcmd)
-#define DEF_CONSOLE_VAR_HOOK(yyyy) static bool yyyy(_iconsole_var * hookvar)
-
-
-// ** supporting functions ** //
+#define DEF_CONSOLE_CMD(function) static bool function(byte argc, char *argv[])
+#define DEF_CONSOLE_HOOK(function) static bool function(void)
 
-static uint32 GetArgumentInteger(const char* arg)
-{
-	uint32 result;
-	sscanf(arg, "%u", &result);
-
-	if (result == 0 && arg[0] == '0' && arg[1] == 'x')
-		sscanf(arg, "%x", &result);
-
-	return result;
-}
 
 /* **************************** */
 /* variable and command hooks   */
@@ -46,7 +29,49 @@
 
 #ifdef ENABLE_NETWORK
 
-DEF_CONSOLE_CMD_HOOK(ConCmdHookNoNetwork)
+static inline bool NetworkAvailable(void)
+{
+	if (!_network_available) {
+		IConsoleError("You cannot use this command because there is no network available.");
+		return false;
+	}
+	return true;
+}
+
+DEF_CONSOLE_HOOK(ConHookServerOnly)
+{
+	if (!NetworkAvailable()) return false;
+
+	if (!_network_server) {
+		IConsoleError("This variable is only available to a network server.");
+		return false;
+	}
+	return true;
+}
+
+DEF_CONSOLE_HOOK(ConHookClientOnly)
+{
+	if (!NetworkAvailable()) return false;
+
+	if (_network_server) {
+		IConsoleError("This command is not available to a network server.");
+		return false;
+	}
+	return true;
+}
+
+DEF_CONSOLE_HOOK(ConHookNeedNetwork)
+{
+	if (!NetworkAvailable()) return false;
+
+	if (!_networking) {
+		IConsoleError("Not connected. This command is only available in multiplayer.");
+		return false;
+	}
+	return true;
+}
+
+DEF_CONSOLE_HOOK(ConHookNoNetwork)
 {
 	if (_networking) {
 		IConsoleError("This command is forbidden in multiplayer.");
@@ -55,126 +80,92 @@
 	return true;
 }
 
-DEF_CONSOLE_VAR_HOOK(ConVarHookNoNetClient)
-{
-	if (!_network_available) {
-		IConsoleError("You can not use this command because there is no network available.");
-		return false;
-	}
-	if (!_network_server) {
-		IConsoleError("This variable only makes sense for a network server.");
-		return false;
-	}
-	return true;
-}
-
-DEF_CONSOLE_CMD_HOOK(ConCmdHookNoNetClient)
-{
-	if (!_network_available) {
-		IConsoleError("You can not use this command because there is no network available.");
-		return false;
-	}
-	if (!_network_server) {
-		IConsoleError("This command is only available for a network server.");
-		return false;
-	}
-	return true;
-}
-
-DEF_CONSOLE_CMD_HOOK(ConCmdHookNoNetServer)
-{
-	if (!_network_available) {
-		IConsoleError("You can not use this command because there is no network available.");
-		return false;
-	}
-	if (_network_server) {
-		IConsoleError("You can not use this command because you are a network-server.");
-		return false;
-	}
-	return true;
-}
-
-DEF_CONSOLE_CMD_HOOK(ConCmdHookNeedNetwork)
-{
-	if (!_network_available) {
-		IConsoleError("You can not use this command because there is no network available.");
-		return false;
-	}
-	if (!_networking) {
-		IConsoleError("Not connected. Multiplayer only command.");
-		return false;
-	}
-	return true;
-}
-
 #endif /* ENABLE_NETWORK */
 
-/* **************************** */
-/* reset commands               */
-/* **************************** */
+static void IConsoleHelp(const char *str)
+{
+	IConsolePrintF(_iconsole_color_warning, "- %s", str);
+}
 
 DEF_CONSOLE_CMD(ConResetEngines)
 {
+	if (argc == 0) {
+		IConsoleHelp("Reset status data of all engines. This might solve some issues with 'lost' engines. Usage: 'resetengines'");
+		return true;
+	}
+
 	StartupEngines();
-	return 0;
+	return true;
 }
 
 #ifdef _DEBUG
 DEF_CONSOLE_CMD(ConResetTile)
 {
-	if (argc == 2) {
-		TileIndex tile = (TileIndex)GetArgumentInteger(argv[1]);
-		DoClearSquare(tile);
+	if (argc == 0) {
+		IConsoleHelp("Reset a tile to bare land. Usage: 'resettile <tile>'");
+		IConsoleHelp("Tile can be either decimal (34161) or hexadecimal (0x4a5B)");
+		return true;
 	}
 
-	return 0;
+	if (argc == 2) {
+		uint32 result;
+		if (GetArgumentInteger(&result, argv[1])) {
+			DoClearSquare((TileIndex)result);
+			return true;
+		}
+	}
+
+	return false;
 }
-#endif
 
 DEF_CONSOLE_CMD(ConScrollToTile)
 {
-	if (argc == 2) {
-		TileIndex tile = (TileIndex)GetArgumentInteger(argv[1]);
-		ScrollMainWindowToTile(tile);
+	if (argc == 0) {
+		IConsoleHelp("Center the screen on a given tile. Usage: 'scrollto <tile>'");
+		IConsoleHelp("Tile can be either decimal (34161) or hexadecimal (0x4a5B)");
+		return true;
 	}
 
-	return 0;
+	if (argc == 2) {
+		uint32 result;
+		if (GetArgumentInteger(&result, argv[1])) {
+			ScrollMainWindowToTile((TileIndex)result);
+			return true;
+		}
+	}
+
+	return false;
 }
+#endif /* _DEBUG */
 
 extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
 extern void BuildFileList(void);
 extern void SetFiosType(const byte fiostype);
 
-/* Save the map to current dir */
-static void SaveMap(const char *filename)
-{
-	char buf[200];
-
-	snprintf(buf, lengthof(buf), "%s%s%s.sav", _path.save_dir, PATHSEP, filename);
-	IConsolePrint(_iconsole_color_default, "Saving map...");
-
-	if (SaveOrLoad(buf, SL_SAVE) != SL_OK) {
-		IConsolePrint(_iconsole_color_error, "SaveMap failed");
-	} else
-		IConsolePrintF(_iconsole_color_default, "Map sucessfully saved to %s", buf);
-}
-
 /* Save the map to a file */
 DEF_CONSOLE_CMD(ConSave)
 {
-	/* We need 1 argument */
-	if (argc == 2) {
-		/* Save the map */
-		SaveMap(argv[1]);
-		return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Save the current game. Usage: 'save <filename>'");
+		return true;
 	}
 
-	/* Give usage */
-	IConsolePrint(_iconsole_color_default, "Unknown usage. Usage: save <filename>");
-	return NULL;
+	if (argc == 2) {
+		char buf[200];
+
+		snprintf(buf, lengthof(buf), "%s%s%s.sav", _path.save_dir, PATHSEP, argv[1]);
+		IConsolePrint(_iconsole_color_default, "Saving map...");
+
+		if (SaveOrLoad(buf, SL_SAVE) != SL_OK) {
+			IConsolePrint(_iconsole_color_error, "SaveMap failed");
+		} else
+			IConsolePrintF(_iconsole_color_default, "Map sucessfully saved to %s", buf);
+		return true;
+	}
+
+	return false;
 }
 
-
 static const FiosItem* GetFiosItem(const char* file)
 {
 	int i;
@@ -198,104 +189,101 @@
 
 DEF_CONSOLE_CMD(ConLoad)
 {
-	const FiosItem* item;
-	const char* file;
+	const FiosItem *item;
+	const char *file;
 
-	if (argc != 2) {
-		IConsolePrint(_iconsole_color_default, "Usage: load <file | number>");
-		return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Load a game by name or index. Usage: 'load <file | number>'");
+		return true;
 	}
 
+	if (argc != 2) return false;
+
 	file = argv[1];
 	item = GetFiosItem(file);
 	if (item != NULL) {
 		switch (item->type) {
-			case FIOS_TYPE_FILE:
-			case FIOS_TYPE_OLDFILE:
+			case FIOS_TYPE_FILE: case FIOS_TYPE_OLDFILE:
 				_switch_mode = SM_LOAD;
 				SetFiosType(item->type);
 				strcpy(_file_to_saveload.name, FiosBrowseTo(item));
 				break;
-
-			default:
-				IConsolePrintF(_iconsole_color_error, "%s: Not a map.", file);
-				break;
+			default: IConsolePrintF(_iconsole_color_error, "%s: Not a savegame.", file);
 		}
-	} else {
-		IConsolePrintF(_iconsole_color_error, "%s: No such file or directory.",
-			file);
-	}
+	} else
+		IConsolePrintF(_iconsole_color_error, "%s: No such file or directory.", file);
 
 	FiosFreeSavegameList();
-	return NULL;
+	return true;
 }
 
-
 /* List all the files in the current dir via console */
 DEF_CONSOLE_CMD(ConListFiles)
 {
 	int i;
 
+	if (argc == 0) {
+		IConsoleHelp("List all the files in the current dir via console. Usage: 'ls | dir'");
+		return true;
+	}
+
 	BuildFileList();
 
 	for (i = 0; i < _fios_num; i++) {
-		const FiosItem* item = &_fios_list[i];
-
-		IConsolePrintF(_iconsole_color_default, "%d) %s",
-			i, item->title[0] != '\0' ? item->title : item->name);
+		const FiosItem *item = &_fios_list[i];
+		IConsolePrintF(_iconsole_color_default, "%d) %s", i, (item->title[0] != '\0') ? item->title : item->name);
 	}
 
 	FiosFreeSavegameList();
-	return NULL;
+	return true;
 }
 
-
 /* Change the dir via console */
 DEF_CONSOLE_CMD(ConChangeDirectory)
 {
-	const FiosItem* item;
-	const char* file;
+	const FiosItem *item;
+	const char *file;
 
-	if (argc != 2) {
-		IConsolePrint(_iconsole_color_default, "Usage: cd <directory | number>");
-		return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Change the dir via console. Usage: 'cd <directory | number>'");
+		return true;
 	}
 
+	if (argc != 2) return false;
+
 	file = argv[1];
 	item = GetFiosItem(file);
 	if (item != NULL) {
 		switch (item->type) {
-			case FIOS_TYPE_DIR:
-			case FIOS_TYPE_DRIVE:
-			case FIOS_TYPE_PARENT:
+			case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
 				FiosBrowseTo(item);
 				break;
-
-			default:
-				IConsolePrintF(_iconsole_color_error, "%s: Not a directory.", file);
-				break;
+			default: IConsolePrintF(_iconsole_color_error, "%s: Not a directory.", file);
 		}
-	} else {
-		IConsolePrintF(_iconsole_color_error, "%s: No such file or directory.",
-			file);
-	}
+	} else
+		IConsolePrintF(_iconsole_color_error, "%s: No such file or directory.", file);
 
 	FiosFreeSavegameList();
-	return NULL;
+	return true;
 }
 
 
 DEF_CONSOLE_CMD(ConPrintWorkingDirectory)
 {
-	const char* path;
+	const char *path;
 
-	// XXX Workaround for broken file handling
+	if (argc == 0) {
+		IConsoleHelp("Print out the current working directory. Usage: 'pwd'");
+		return true;
+	}
+
+	// XXX - Workaround for broken file handling
 	FiosGetSavegameList(&_fios_num, SLD_LOAD_GAME);
 	FiosFreeSavegameList();
 
 	FiosGetDescText(&path, NULL);
 	IConsolePrint(_iconsole_color_default, path);
-	return NULL;
+	return true;
 }
 
 
@@ -307,72 +295,81 @@
 DEF_CONSOLE_CMD(ConBan)
 {
 	NetworkClientInfo *ci;
+	uint32 index;
 
-	if (argc == 2) {
-		uint32 index = atoi(argv[1]);
-		if (index == NETWORK_SERVER_INDEX) {
-			IConsolePrint(_iconsole_color_default, "Silly boy, you can not ban yourself!");
-			return NULL;
-		}
-		if (index == 0) {
-			IConsoleError("Invalid Client-ID");
-			return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Ban a player from a network game. Usage: 'ban <client-id>'");
+		IConsoleHelp("For client-id's, see the command 'clients'");
+		return true;
+	}
+
+	if (argc != 2) return false;
+
+	index = atoi(argv[1]);
+
+	if (index == NETWORK_SERVER_INDEX) {
+		IConsolePrint(_iconsole_color_default, "Silly boy, you can not ban yourself!");
+		return true;
+	}
+	if (index == 0) {
+		IConsoleError("Invalid Client-ID");
+		return true;
+	}
+
+	ci = NetworkFindClientInfoFromIndex(index);
+
+	if (ci != NULL) {
+		uint i;
+		/* Add user to ban-list */
+		for (i = 0; i < lengthof(_network_ban_list); i++) {
+			if (_network_ban_list[i] == NULL || _network_ban_list[i][0] == '\0') {
+				_network_ban_list[i] = strdup(inet_ntoa(*(struct in_addr *)&ci->client_ip));
+				break;
+			}
 		}
 
-		ci = NetworkFindClientInfoFromIndex(index);
+		SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
+	} else
+		IConsoleError("Client-ID not found");
 
-		if (ci != NULL) {
-			uint i;
-			/* Add user to ban-list */
-			for (i = 0; i < lengthof(_network_ban_list); i++) {
-				if (_network_ban_list[i] == NULL || _network_ban_list[i][0] == '\0') {
-					_network_ban_list[i] = strdup(inet_ntoa(*(struct in_addr *)&ci->client_ip));
-					break;
-				}
-			}
-
-			SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
-			return NULL;
-		} else {
-			IConsoleError("Client-ID not found");
-			return NULL;
-		}
-	}
-
-	IConsolePrint(_iconsole_color_default, "Unknown usage. Usage: ban <client-id>. For client-ids, see 'clients'.");
-
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConUnBan)
 {
-	if (argc == 2) {
-		uint i;
-		for (i = 0; i < lengthof(_network_ban_list); i++) {
-			if (_network_ban_list[i] == NULL || _network_ban_list[i][0] == '\0')
-				continue;
+	uint i;
 
-			if (strncmp(_network_ban_list[i], argv[1], strlen(_network_ban_list[i])) == 0) {
-				_network_ban_list[i][0] = '\0';
-				IConsolePrint(_iconsole_color_default, "IP unbanned.");
-				return NULL;
-			}
-		}
-
-		IConsolePrint(_iconsole_color_default, "IP not in ban-list.");
-
-		return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Unban a player from a network game. Usage: 'unban <ip>'");
+		return true;
 	}
 
-	IConsolePrint(_iconsole_color_default, "Unknown usage. Usage: unban <ip>.");
+	if (argc != 2) return false;
 
-	return NULL;
+	for (i = 0; i < lengthof(_network_ban_list); i++) {
+		if (_network_ban_list[i] == NULL || _network_ban_list[i][0] == '\0')
+			continue;
+
+		if (strncmp(_network_ban_list[i], argv[1], strlen(_network_ban_list[i])) == 0) {
+			_network_ban_list[i][0] = '\0';
+			IConsolePrint(_iconsole_color_default, "IP unbanned.");
+			return true;
+		}
+	}
+
+	IConsolePrint(_iconsole_color_default, "IP not in ban-list.");
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConBanList)
 {
 	uint i;
 
+	if (argc == 0) {
+		IConsoleHelp("List the IP's of banned clients: Usage 'banlist'");
+		return true;
+	}
+
 	IConsolePrint(_iconsole_color_default, "Banlist: ");
 
 	for (i = 0; i < lengthof(_network_ban_list); i++) {
@@ -382,115 +379,109 @@
 		IConsolePrintF(_iconsole_color_default, "  %d) %s", i + 1, _network_ban_list[i]);
 	}
 
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConPauseGame)
 {
+	if (argc == 0) {
+		IConsoleHelp("Pause a network game. Usage: 'pause'");
+		return true;
+	}
+
 	if (_pause == 0) {
 		DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
 		IConsolePrint(_iconsole_color_default, "Game paused.");
 	} else
 		IConsolePrint(_iconsole_color_default, "Game is already paused.");
 
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConUnPauseGame)
 {
+	if (argc == 0) {
+		IConsoleHelp("Unpause a network game. Usage: 'unpause'");
+		return true;
+	}
+
 	if (_pause != 0) {
 		DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
 		IConsolePrint(_iconsole_color_default, "Game unpaused.");
 	} else
 		IConsolePrint(_iconsole_color_default, "Game is already unpaused.");
 
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConRcon)
 {
-	if (argc < 3) {
-		IConsolePrint(_iconsole_color_default, "Usage: rcon <password> <command>");
-		return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Remote control the server from another client. Usage: 'rcon <password> <command>'");
+		IConsoleHelp("Remember to enclose the command in quotes, otherwise only the first parameter is sent");
+		return true;
 	}
 
+	if (argc < 3) return false;
+
 	SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
-
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConStatus)
 {
+	static const char *stat_str[] = {"inactive", "authorized", "waiting", "loading map", "map done", "ready", "active"};
 	const char *status;
-	int lag;
 	const NetworkClientState *cs;
-	const NetworkClientInfo *ci;
-	FOR_ALL_CLIENTS(cs) {
-		lag = NetworkCalculateLag(cs);
-		ci = DEREF_CLIENT_INFO(cs);
 
-		switch (cs->status) {
-			case STATUS_INACTIVE:
-				status = "inactive";
-				break;
-			case STATUS_AUTH:
-				status = "authorized";
-				break;
-			case STATUS_MAP_WAIT:
-				status = "waiting";
-				break;
-			case STATUS_MAP:
-				status = "loading map";
-				break;
-			case STATUS_DONE_MAP:
-				status = "done map";
-				break;
-			case STATUS_PRE_ACTIVE:
-				status = "ready";
-				break;
-			case STATUS_ACTIVE:
-				status = "active";
-				break;
-			default:
-				status = "unknown";
-				break;
-		}
+	if (argc == 0) {
+		IConsoleHelp("List the status of all clients connected to the server: Usage 'status'");
+		return true;
+	}
+
+	FOR_ALL_CLIENTS(cs) {
+		int lag = NetworkCalculateLag(cs);
+		const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
+
+		status = (cs->status <= STATUS_ACTIVE) ? stat_str[cs->status] : "unknown";
 		IConsolePrintF(8, "Client #%d/%s  status: %s  frame-lag: %d  play-as: %d  unique-id: %s",
 			cs->index, ci->client_name, status, lag, ci->client_playas, ci->unique_id);
 	}
 
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConKick)
 {
 	NetworkClientInfo *ci;
+	uint32 index;
 
-	if (argc == 2) {
-		uint32 index = atoi(argv[1]);
-		if (index == NETWORK_SERVER_INDEX) {
-			IConsolePrint(_iconsole_color_default, "Silly boy, you can not kick yourself!");
-			return NULL;
-		}
-		if (index == 0) {
-			IConsoleError("Invalid Client-ID");
-			return NULL;
-		}
-
-		ci = NetworkFindClientInfoFromIndex(index);
-
-		if (ci != NULL) {
-			SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
-			return NULL;
-		} else {
-			IConsoleError("Client-ID not found");
-			return NULL;
-		}
+	if (argc == 0) {
+		IConsoleHelp("Kick a player from a network game. Usage: 'kick <client-id>'");
+		IConsoleHelp("For client-id's, see the command 'clients'");
+		return true;
 	}
 
-	IConsolePrint(_iconsole_color_default, "Unknown usage. Usage: kick <client-id>. For client-ids, see 'clients'.");
+	if (argc != 2) return false;
 
-	return NULL;
+	index = atoi(argv[1]);
+	if (index == NETWORK_SERVER_INDEX) {
+		IConsolePrint(_iconsole_color_default, "Silly boy, you can not kick yourself!");
+		return true;
+	}
+	if (index == 0) {
+		IConsoleError("Invalid Client-ID");
+		return true;
+	}
+
+	ci = NetworkFindClientInfoFromIndex(index);
+
+	if (ci != NULL) {
+		SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
+	} else
+		IConsoleError("Client-ID not found");
+
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConResetCompany)
@@ -498,79 +489,92 @@
 	Player *p;
 	NetworkClientState *cs;
 	NetworkClientInfo *ci;
-
-	if (argc == 2) {
-		byte index = atoi(argv[1]);
-
-		/* Check valid range */
-		if (index < 1 || index > MAX_PLAYERS) {
-			IConsolePrintF(_iconsole_color_error, "Company does not exist. Company-ID must be between 1 and %d.", MAX_PLAYERS);
-			return NULL;
-		}
+	byte index;
 
-		/* Check if company does exist */
-		index--;
-		p = DEREF_PLAYER(index);
-		if (!p->is_active) {
-			IConsolePrintF(_iconsole_color_error, "Company does not exist.");
-			return NULL;
-		}
+	if (argc == 0) {
+		IConsoleHelp("Remove an (idle) company from the game. Usage: 'reset_company <company-id>'");
+		return true;
+	}
 
-		if (p->is_ai) {
-			IConsolePrintF(_iconsole_color_error, "Company is owned by an AI.");
-			return NULL;
-		}
+	if (argc != 2) return false;
 
-		/* Check if the company has active players */
-		FOR_ALL_CLIENTS(cs) {
-			ci = DEREF_CLIENT_INFO(cs);
-			if (ci->client_playas-1 == index) {
-				IConsolePrintF(_iconsole_color_error, "Cannot remove company: a client is connected to that company.");
-				return NULL;
-			}
-		}
-		ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+	index = atoi(argv[1]);
+
+	/* Check valid range */
+	if (index < 1 || index > MAX_PLAYERS) {
+		IConsolePrintF(_iconsole_color_error, "Company does not exist. Company-ID must be between 1 and %d.", MAX_PLAYERS);
+		return true;
+	}
+
+	/* Check if company does exist */
+	index--;
+	p = DEREF_PLAYER(index);
+	if (!p->is_active) {
+		IConsolePrintF(_iconsole_color_error, "Company does not exist.");
+		return true;
+	}
+
+	if (p->is_ai) {
+		IConsolePrintF(_iconsole_color_error, "Company is owned by an AI.");
+		return true;
+	}
+
+	/* Check if the company has active players */
+	FOR_ALL_CLIENTS(cs) {
+		ci = DEREF_CLIENT_INFO(cs);
 		if (ci->client_playas-1 == index) {
 			IConsolePrintF(_iconsole_color_error, "Cannot remove company: a client is connected to that company.");
-			return NULL;
+			return true;
 		}
-
-		/* It is safe to remove this company */
-		DoCommandP(0, 2, index, NULL, CMD_PLAYER_CTRL);
-		IConsolePrint(_iconsole_color_default, "Company deleted.");
-		return NULL;
+	}
+	ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+	if (ci->client_playas - 1 == index) {
+		IConsolePrintF(_iconsole_color_error, "Cannot remove company; a client is connected to that company.");
+		return true;
 	}
 
-	IConsolePrint(_iconsole_color_default, "Unknown usage. Usage: reset_company <company-id>.");
+	/* It is safe to remove this company */
+	DoCommandP(0, 2, index, NULL, CMD_PLAYER_CTRL);
+	IConsolePrint(_iconsole_color_default, "Company deleted.");
 
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConNetworkClients)
 {
 	NetworkClientInfo *ci;
+
+	if (argc == 0) {
+		IConsoleHelp("Get a list of connected clients including their ID, name, and company-id. Usage: 'clients'");
+		return true;
+	}
+
 	for (ci = _network_client_info; ci != &_network_client_info[MAX_CLIENT_INFO]; ci++) {
 		if (ci->client_index != NETWORK_EMPTY_INDEX) {
 			IConsolePrintF(8,"Client #%d   name: %s  play-as: %d", ci->client_index, ci->client_name, ci->client_playas);
 		}
 	}
 
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConNetworkConnect)
 {
-	char* ip;
+	char *ip;
 	const char *port = NULL;
 	const char *player = NULL;
 	uint16 rport;
 
-	if (argc<2) return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Connect to a remote OTTD server and join the game. Usage: 'connect <ip>'");
+		IConsoleHelp("IP can contain port and player: 'IP#Player:Port', eg: 'server.ottd.org#2:443'");
+		return true;
+	}
 
-	if (_networking) {
-		// We are in network-mode, first close it!
+	if (argc < 2) return false;
+
+	if (_networking) // We are in network-mode, first close it!
 		NetworkDisconnect();
-	}
 
 	ip = argv[1];
 	rport = NETWORK_DEFAULT_PORT;
@@ -589,7 +593,7 @@
 
 	NetworkClientConnectGame(ip, rport);
 
-	return NULL;
+	return true;
 }
 
 #endif /* ENABLE_NETWORK */
@@ -600,36 +604,44 @@
 
 DEF_CONSOLE_CMD(ConExec)
 {
-	char cmd[1024];
+	char cmdline[ICON_CMDLN_SIZE];
 
-	if (argc < 2) return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Execute a local script file. Usage: 'exec <script> <?>'");
+		return true;
+	}
+
+	if (argc < 2) return false;
 
 	_script_file = fopen(argv[1], "r");
 
 	if (_script_file == NULL) {
-		if (argc <= 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
-		return NULL;
+		if (argc == 2 || atoi(argv[2]) != 0) IConsoleError("script file not found");
+		return true;
 	}
 
 	_script_running = true;
 
-	while (_script_running && fgets(cmd, sizeof(cmd), _script_file) != NULL) {
-		IConsoleCmdExec(cmd);
-	}
+	while (_script_running && fgets(cmdline, sizeof(cmdline), _script_file) != NULL)
+		IConsoleCmdExec(cmdline);
 
-	if (ferror(_script_file)) {
+	if (ferror(_script_file))
 		IConsoleError("Encountered errror while trying to read from script file");
-	}
 
 	_script_running = false;
 	fclose(_script_file);
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConReturn)
 {
+	if (argc == 0) {
+		IConsoleHelp("Stop executing a running script. Usage: 'return'");
+		return true;
+	}
+
 	_script_running = false;
-	return NULL;
+	return true;
 }
 
 /* **************************** */
@@ -640,591 +652,482 @@
 DEF_CONSOLE_CMD(ConScript)
 {
 	extern FILE* _iconsole_output_file;
+
+	if (argc == 0) {
+		IConsoleHelp("Start or stop logging console output to a file. Usage: 'script <filename>'");
+		IConsoleHelp("If filename is omitted, a running log is stopped if it is active");
+		return true;
+	}
+
 	if (!CloseConsoleLogIfActive()) {
-		if (argc < 2) return NULL;
+		if (argc < 2) return false;
+
 		IConsolePrintF(_iconsole_color_default, "file output started to: %s",	argv[1]);
 		_iconsole_output_file = fopen(argv[1], "ab");
 		if (_iconsole_output_file == NULL) IConsoleError("could not open file");
 	}
 
-	return NULL;
+	return true;
 }
 
 
 DEF_CONSOLE_CMD(ConEcho)
 {
-	if (argc < 2) return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Print back the first argument to the console. Usage: 'echo <arg>'");
+		return true;
+	}
+
+	if (argc < 2) return false;
 	IConsolePrint(_iconsole_color_default, argv[1]);
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConEchoC)
 {
-	if (argc < 3) return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Print back the first argument to the console in a given colour. Usage: 'echoc <colour> <arg2>'");
+		return true;
+	}
+
+	if (argc < 3) return false;
 	IConsolePrint(atoi(argv[1]), argv[2]);
-	return NULL;
+	return true;
 }
 
 extern void SwitchMode(int new_mode);
 
 DEF_CONSOLE_CMD(ConNewGame)
 {
+	if (argc == 0) {
+		IConsoleHelp("Start a new game. Usage: 'newgame'");
+		return true;
+	}
+
 	_docommand_recursive = 0;
 
 	_random_seeds[0][0] = Random();
 	_random_seeds[0][1] = InteractiveRandom();
 
 	SwitchMode(SM_NEWGAME);
-	return NULL;
-}
-
-DEF_CONSOLE_CMD(ConPrintF)
-{
-	if (argc < 3) return NULL;
-	IConsolePrintF(_iconsole_color_default, argv[1] , argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18], argv[19]); /* XXX ugh... */
-	return NULL;
-}
-
-DEF_CONSOLE_CMD(ConPrintFC)
-{
-	if (argc < 3) return NULL;
-	IConsolePrintF(atoi(argv[1]), argv[2] , argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11], argv[12], argv[13], argv[14], argv[15], argv[16], argv[17], argv[18], argv[19]); /* XXX ugh... */
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConAlias)
 {
-	_iconsole_alias* alias;
+	IConsoleAlias *alias;
 
-	if (argc < 3) return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Add a new alias, or redefine the behaviour of an existing alias . Usage: 'alias <name> <command>'");
+		return true;
+	}
+
+	if (argc < 3) return false;
 
 	alias = IConsoleAliasGet(argv[1]);
 	if (alias == NULL) {
-		IConsoleAliasRegister(argv[1],argv[2]);
+		IConsoleAliasRegister(argv[1], argv[2]);
 	} else {
 		free(alias->cmdline);
 		alias->cmdline = strdup(argv[2]);
 	}
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConScreenShot)
 {
+	if (argc == 0) {
+		IConsoleHelp("Create a screenshot of the game. Usage: 'screenshot [big|no_con]'");
+		IConsoleHelp("'big' makes a screenshot of the whole map, 'no_con' hides the console to create the screenshot");
+		return true;
+	}
+
 	if (argc < 2) {
 		_make_screenshot = 1;
 	} else {
 		if (strcmp(argv[1], "big") == 0)
-			_make_screenshot=2;
+			_make_screenshot = 2;
+
 		if (strcmp(argv[1], "no_con") == 0) {
 			IConsoleClose();
 			_make_screenshot = 1;
 		}
 	}
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConInfoVar)
 {
-	if (argc < 2) return NULL;
-	if (argt[1] != ICONSOLE_VAR_REFERENCE) {
-		IConsoleError("first argument has to be a variable reference");
-	} else {
-		_iconsole_var* item;
-		item = (_iconsole_var*)argv[1];
-		IConsolePrintF(_iconsole_color_default, "var_name: %s", item->name);
-		IConsolePrintF(_iconsole_color_default, "var_type: %i", item->type);
-		IConsolePrintF(_iconsole_color_default, "var_addr: %i", item->data.addr);
-		if (item->_malloc)
-			IConsolePrintF(_iconsole_color_default, "var_malloc: internal");
-		else
-			IConsolePrintF(_iconsole_color_default, "var_malloc: external");
-		if (item->hook_access) IConsoleWarning("var_access hooked");
-		if (item->hook_before_change) IConsoleWarning("var_before_change hooked");
-		if (item->hook_after_change) IConsoleWarning("var_after_change hooked");
+	static const char *_icon_vartypes[] = {"boolean", "byte", "uint16", "uint32", "int16", "int32", "string"};
+	const IConsoleVar *var;
+
+	if (argc == 0) {
+		IConsoleHelp("Print out debugging information about a variable. Usage: 'info_var <var>'");
+		return true;
 	}
-	return NULL;
+
+	if (argc < 2) return false;
+
+	var = IConsoleVarGet(argv[1]);
+	if (var == NULL) {
+		IConsoleError("the given variable was not found");
+		return true;
+	}
+
+	IConsolePrintF(_iconsole_color_default, "variable name: %s", var->name);
+	IConsolePrintF(_iconsole_color_default, "variable type: %s", _icon_vartypes[var->type]);
+	IConsolePrintF(_iconsole_color_default, "variable addr: 0x%X", var->addr);
+
+	if (var->hook.access) IConsoleWarning("variable is access hooked");
+	if (var->hook.pre) IConsoleWarning("variable is pre hooked");
+	if (var->hook.post) IConsoleWarning("variable is post hooked");
+	return true;
 }
 
 
 DEF_CONSOLE_CMD(ConInfoCmd)
 {
-	if (argc < 2) return NULL;
-	if (argt[1] != ICONSOLE_VAR_UNKNOWN) {
-		IConsoleError("first argument has to be a command name");
-	} else {
-		_iconsole_cmd* item;
-		item = IConsoleCmdGet(argv[1]);
-		if (item == NULL) {
-			IConsoleError("the given command was not found");
-			return NULL;
-		}
-		IConsolePrintF(_iconsole_color_default, "cmd_name: %s", item->name);
-		IConsolePrintF(_iconsole_color_default, "cmd_addr: %i", item->addr);
-		if (item->hook_access) IConsoleWarning("cmd_access hooked");
-		if (item->hook_before_exec) IConsoleWarning("cmd_before_exec hooked");
-		if (item->hook_after_exec) IConsoleWarning("cmd_after_exec hooked");
+	const IConsoleCmd *cmd;
+
+	if (argc == 0) {
+		IConsoleHelp("Print out debugging information about a command. Usage: 'info_cmd <cmd>'");
+		return true;
 	}
-	return NULL;
+
+	if (argc < 2) return false;
+
+	cmd = IConsoleCmdGet(argv[1]);
+	if (cmd == NULL) {
+		IConsoleError("the given command was not found");
+		return true;
+	}
+
+	IConsolePrintF(_iconsole_color_default, "command name: %s", cmd->name);
+	IConsolePrintF(_iconsole_color_default, "command proc: 0x%X", cmd->proc);
+
+	if (cmd->hook.access) IConsoleWarning("command is access hooked");
+	if (cmd->hook.pre) IConsoleWarning("command is pre hooked");
+	if (cmd->hook.post) IConsoleWarning("command is post hooked");
+
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConDebugLevel)
 {
-	if (argc < 2) return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Set the default debugging level for the game. Usage: 'debug_level <level>'");
+		IConsoleHelp("Level can be any combination of names, levels. Eg 'net=5 ms=4'. Remember to enclose it in \"'s");
+		return true;
+	}
+
+	if (argc < 2) return false;
 	SetDebugString(argv[1]);
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConExit)
 {
+	if (argc == 0) {
+		IConsoleHelp("Exit the game. Usage: 'exit'");
+		return true;
+	}
+
 	_exit_game = true;
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConHelp)
 {
-	IConsolePrint(13, " -- console help -- ");
-	IConsolePrint( 1, " variables: [command to list them: list_vars]");
-	IConsolePrint( 1, " temp_string = \"my little \"");
-	IConsolePrint( 1, "");
-	IConsolePrint( 1, " commands: [command to list them: list_cmds]");
-	IConsolePrint( 1, " [command] [\"string argument with spaces\"] [argument 2] ...");
-	IConsolePrint( 1, " printf \"%s world\" temp_string");
+	if (argc == 2) {
+		IConsoleCmd *cmd;
+		IConsoleVar *var;
+
+		cmd = IConsoleCmdGet(argv[1]);
+	 	if (cmd != NULL) {
+	 		cmd->proc(0, NULL);
+	 		return true;
+	 	}
+
+	 	var = IConsoleVarGet(argv[1]);
+   	if (var != NULL && var->help != NULL) {
+   		IConsolePrintF(_iconsole_color_warning, "%s.", var->help);
+   		return true;
+   	}
+
+   	IConsoleError("command or variable not found");
+   	return true;
+  }
+
+	IConsolePrint(13, " -- OpenTTD Console Help -- ");
+	IConsolePrint( 1, " variables: [command to list all variables: list_vars]");
+	IConsolePrint( 1, " set value with '<var> = <value>', use '++/--' to in-or decrement");
+	IConsolePrint( 1, " or omit '=' and just '<var> <value>'. get value with typing '<var>'");
 	IConsolePrint( 1, "");
-	IConsolePrint( 1, " command/variable returning a value into an variable:");
-	IConsolePrint( 1, " temp_uint16 << random");
-	IConsolePrint( 1, " temp_uint16 << temp_uint16_2");
+	IConsolePrint( 1, " commands: [command to list all commands: list_cmds]");
+	IConsolePrint( 1, " call commands with '<command> <arg2> <arg3>...'");
 	IConsolePrint( 1, "");
-	return NULL;
-}
-
-DEF_CONSOLE_CMD(ConRandom)
-{
-	_iconsole_var* result;
-	result = IConsoleVarAlloc(ICONSOLE_VAR_UINT16);
-	IConsoleVarSetValue(result, rand());
-	return result;
+	IConsolePrint( 1, " to assign strings, or use them as arguments, enclose it within quotes");
+	IConsolePrint( 1, " like this: '<command> \"string argument with spaces\"'");
+	IConsolePrint( 1, " use 'help <command>|<variable>' to get specific information");
+	IConsolePrint( 1, "");
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConListCommands)
 {
-	const _iconsole_cmd* item;
+	const IConsoleCmd *cmd;
 	size_t l = 0;
 
+	if (argc == 0) {
+		IConsoleHelp("List all registered commands. Usage: 'list_cmds [<pre-filter>]'");
+		return true;
+	}
+
 	if (argv[1] != NULL) l = strlen(argv[1]);
 
-	for (item = _iconsole_cmds; item != NULL; item = item->_next)
-		if (argv[1] == NULL || strncmp(item->name, argv[1], l) == 0)
-			IConsolePrintF(_iconsole_color_default, "%s", item->name);
+	for (cmd = _iconsole_cmds; cmd != NULL; cmd = cmd->next) {
+		if (argv[1] == NULL || strncmp(cmd->name, argv[1], l) == 0) {
+				IConsolePrintF(_iconsole_color_default, "%s", cmd->name);
+		}
+	}
 
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConListVariables)
 {
-	const _iconsole_var* item;
+	const IConsoleVar *var;
 	size_t l = 0;
 
+	if (argc == 0) {
+		IConsoleHelp("List all registered variables. Usage: 'list_vars [<pre-filter>]'");
+		return true;
+	}
+
 	if (argv[1] != NULL) l = strlen(argv[1]);
 
-	for (item = _iconsole_vars; item != NULL; item = item->_next)
-		if (argv[1] == NULL || strncmp(item->name, argv[1], l) == 0)
-			IConsolePrintF(_iconsole_color_default, "%s", item->name);
+	for (var = _iconsole_vars; var != NULL; var = var->next) {
+		if (argv[1] == NULL || strncmp(var->name, argv[1], l) == 0)
+			IConsolePrintF(_iconsole_color_default, "%s", var->name);
+	}
 
-	return NULL;
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConListAliases)
 {
-	const _iconsole_alias* item;
+	const IConsoleAlias *alias;
 	size_t l = 0;
 
+	if (argc == 0) {
+		IConsoleHelp("List all registered aliases. Usage: 'list_aliases [<pre-filter>]'");
+		return true;
+	}
+
 	if (argv[1] != NULL) l = strlen(argv[1]);
 
-	for (item = _iconsole_aliases; item != NULL; item = item->_next)
-		if (argv[1] == NULL || strncmp(item->name, argv[1], l) == 0)
-			IConsolePrintF(_iconsole_color_default, "%s => %s", item->name, item->cmdline);
-
-	return NULL;
-}
+	for (alias = _iconsole_aliases; alias != NULL; alias = alias->next) {
+		if (argv[1] == NULL || strncmp(alias->name, argv[1], l) == 0)
+			IConsolePrintF(_iconsole_color_default, "%s => %s", alias->name, alias->cmdline);
+	}
 
-DEF_CONSOLE_CMD(ConListDumpVariables)
-{
-	const _iconsole_var* item;
-	size_t l = 0;
-
-	if (argv[1] != NULL) l = strlen(argv[1]);
-
-	for (item = _iconsole_vars; item != NULL; item = item->_next)
-		if (argv[1] == NULL || strncmp(item->name, argv[1], l) == 0)
-			IConsoleVarDump(item, NULL);
-
-	return NULL;
+	return true;
 }
 
 #ifdef ENABLE_NETWORK
 
 DEF_CONSOLE_CMD(ConSay)
 {
-	if (argc == 2) {
-		if (!_network_server)
-			SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
-		else
-			NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
+	if (argc == 0) {
+		IConsoleHelp("Chat to your fellow players in a multiplayer game. Usage: 'say \"<msg>\"'");
+		return true;
+	}
+
+	if (argc != 2) return false;
+
+	if (!_network_server) {
+		SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
 	} else
-		IConsolePrint(_iconsole_color_default, "Unknown usage. Usage: say \"<msg>\"");
-	return NULL;
+		NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
+
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConSayPlayer)
 {
-	if (argc == 3) {
-		if (atoi(argv[1]) < 1 || atoi(argv[1]) > MAX_PLAYERS) {
-			IConsolePrintF(_iconsole_color_default, "Unknown player. Player range is between 1 and %d.", MAX_PLAYERS);
-			return NULL;
-		}
+	if (argc == 0) {
+		IConsoleHelp("Chat to a certain player in a multiplayer game. Usage: 'say_player <player-no> \"<msg>\"'");
+		IConsoleHelp("PlayerNo is the player that plays as company <playerno>, 1 through max_players");
+		return true;
+	}
 
-		if (!_network_server)
-			SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_PLAYER, DESTTYPE_PLAYER, atoi(argv[1]), argv[2]);
-		else
-			NetworkServer_HandleChat(NETWORK_ACTION_CHAT_PLAYER, DESTTYPE_PLAYER, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
+	if (argc != 3) return false;
+
+	if (atoi(argv[1]) < 1 || atoi(argv[1]) > MAX_PLAYERS) {
+		IConsolePrintF(_iconsole_color_default, "Unknown player. Player range is between 1 and %d.", MAX_PLAYERS);
+		return true;
+	}
+
+	if (!_network_server) {
+		SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_PLAYER, DESTTYPE_PLAYER, atoi(argv[1]), argv[2]);
 	} else
-		IConsolePrint(_iconsole_color_default, "Unknown usage. Usage: say_player <playerno> \"<msg>\"");
-	return NULL;
+		NetworkServer_HandleChat(NETWORK_ACTION_CHAT_PLAYER, DESTTYPE_PLAYER, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
+
+	return true;
 }
 
 DEF_CONSOLE_CMD(ConSayClient)
 {
-	if (argc == 3) {
-		if (!_network_server)
-			SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
-		else
-			NetworkServer_HandleChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
-	} else
-		IConsolePrint(_iconsole_color_default, "Unknown usage. Usage: say_client <clientno> \"<msg>\"");
-	return NULL;
-}
-
-#endif /* ENABLE_NETWORK */
-
-/* **************************** */
-/*   the "set" command          */
-/* **************************** */
-
-extern void ConsoleSetPatchSetting(char *name, char *value);
-extern void ConsoleGetPatchSetting(char *name);
-
-DEF_CONSOLE_CMD(ConSet) {
-	if (argc < 2) {
-		IConsolePrint(_iconsole_color_warning, "Unknonw usage. Usage: set [setting] [value].");
-		return NULL;
-	}
-
-#ifdef ENABLE_NETWORK
-
-	// setting the server password
-	if ((strcmp(argv[1],"server_pw") == 0) || (strcmp(argv[1],"server_password") == 0)) {
-		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3) {
-			// Change server password
-			if (strncmp(argv[2], "*", NETWORK_PASSWORD_LENGTH) == 0) {
-				_network_server_password[0] = '\0';
-				_network_game_info.use_password = 0;
-			} else {
-				ttd_strlcpy(_network_server_password, argv[2], sizeof(_network_server_password));
-				_network_game_info.use_password = 1;
-			}
-			IConsolePrintF(_iconsole_color_warning, "Game-password changed to '%s'", _network_server_password);
-			ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_game_info.server_password));
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current game-password is set to '%s'", _network_game_info.server_password);
-			IConsolePrint(_iconsole_color_warning, "Usage: set server_pw \"<password>\".   Use * as <password> to set no password.");
-		}
-		return NULL;
-	}
-
-	// setting the rcon password
-	if ((strcmp(argv[1], "rcon_pw") == 0) || (strcmp(argv[1], "rcon_password") == 0)) {
-		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3) {
-			// Change server password
-			if (strncmp(argv[2], "*", NETWORK_PASSWORD_LENGTH) == 0) {
-				_network_rcon_password[0] = '\0';
-			} else {
-				ttd_strlcpy(_network_rcon_password, argv[2], sizeof(_network_rcon_password));
-			}
-			IConsolePrintF(_iconsole_color_warning, "Rcon-password changed to '%s'", _network_rcon_password);
-			ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_game_info.rcon_password));
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current rcon-password is set to '%s'", _network_game_info.rcon_password);
-			IConsolePrint(_iconsole_color_warning, "Usage: set rcon_pw \"<password>\".   Use * as <password> to disable rcon.");
-		}
-		return NULL;
-	}
-
-	// setting the company password
-	if ((strcmp(argv[1],"company_pw") == 0) || (strcmp(argv[1],"company_password") == 0)) {
-		if (!_networking) {
-			IConsolePrintF(_iconsole_color_error,"No network game running");
-			return NULL;
-		}
-		if (_local_player >= MAX_PLAYERS) {
-			IConsolePrintF(_iconsole_color_default, "You have to own a company to make use of this command.");
-			return NULL;
-		}
-		if (argc == 3) {
-			NetworkChangeCompanyPassword(argv[2]);
-		} else {
-			IConsolePrint(_iconsole_color_default, "'set company_pw' sets a password for your company, so no-one without the correct password can join.");
-			IConsolePrint(_iconsole_color_warning, "Usage: set company_pw \"<password>\".   Use * as <password> to set no password.");
-		}
-		return NULL;
-	}
-
-	// setting the player name
-	if (strcmp(argv[1],"name") == 0) {
-		NetworkClientInfo *ci;
-
-		if (!_networking) {
-			IConsolePrintF(_iconsole_color_error,"No network game running");
-			return NULL;
-		}
-
-		ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
-
-		if (argc == 3 && ci != NULL) {
-			// Don't change the name if it is the same as the old name
-			if (strcmp(ci->client_name, argv[2]) != 0) {
-				if (!_network_server) {
-					SEND_COMMAND(PACKET_CLIENT_SET_NAME)(argv[2]);
-				} else {
-					if (NetworkFindName(argv[2])) {
-						NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, argv[2]);
-						ttd_strlcpy(ci->client_name, argv[2], sizeof(ci->client_name));
-						NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
-					}
-				}
-				/* Also keep track of the new name on the client itself */
-				ttd_strlcpy(_network_player_name, argv[2], sizeof(_network_player_name));
-			}
-		} else {
-			IConsolePrint(_iconsole_color_default, "With 'set name' you can change your network-player name.");
-			IConsolePrint(_iconsole_color_warning, "Usage: set name \"<name>\".");
-		}
-		return NULL;
-	}
-
-	// setting the server name
-	if (strcmp(argv[1],"server_name") == 0) {
-		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3) {
-			ttd_strlcpy(_network_server_name, argv[2], sizeof(_network_server_name));
-			IConsolePrintF(_iconsole_color_warning, "Server-name changed to '%s'", _network_server_name);
-			ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current server-name is '%s'", _network_server_name);
-			IConsolePrint(_iconsole_color_warning, "Usage: set server_name \"<GameName>\".");
-		}
-		return NULL;
-	}
-
-	// setting the server port
-	if (strcmp(argv[1],"server_port") == 0) {
-		if (argc == 3 && atoi(argv[2]) != 0) {
-			_network_server_port = atoi(argv[2]);
-			IConsolePrintF(_iconsole_color_warning, "Server-port changed to '%d'", _network_server_port);
-			IConsolePrintF(_iconsole_color_warning, "Changes will take effect the next time you start a server.");
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current server-port is '%d'", _network_server_port);
-			IConsolePrint(_iconsole_color_warning, "Usage: set server_port <port>.");
-		}
-		return NULL;
+	if (argc == 0) {
+		IConsoleHelp("Chat to a certain player in a multiplayer game. Usage: 'say_client <client-no> \"<msg>\"'");
+  	IConsoleHelp("For client-id's, see the command 'clients'");
+		return true;
 	}
 
-	// setting the server ip
-	if (strcmp(argv[1],"server_bind_ip") == 0 || strcmp(argv[1],"server_ip_bind") == 0 ||
-			strcmp(argv[1],"server_ip") == 0 || strcmp(argv[1],"server_bind") == 0) {
-		if (argc == 3) {
-			_network_server_bind_ip = inet_addr(argv[2]);
-			snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
-			IConsolePrintF(_iconsole_color_warning, "Server-bind-ip changed to '%s'", _network_server_bind_ip_host);
-			IConsolePrintF(_iconsole_color_warning, "Changes will take effect the next time you start a server.");
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current server-bind-ip is '%s'", _network_server_bind_ip_host);
-			IConsolePrint(_iconsole_color_warning, "Usage: set server_bind_ip <ip>.");
-		}
-		return NULL;
-	}
-
-	// setting max-join-time
-	if (strcmp(argv[1],"max_join_time") == 0) {
-		if (argc == 3 && atoi(argv[2]) != 0) {
-			_network_max_join_time = atoi(argv[2]);
-			IConsolePrintF(_iconsole_color_warning, "Max-join-time changed to '%d'", _network_max_join_time);
-			IConsolePrintF(_iconsole_color_warning, "Changes will take effect immediatly.");
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current max-join-time is '%d'", _network_max_join_time);
-			IConsolePrint(_iconsole_color_warning, "Usage: set max_join_time <ticks> (default = 500).");
-		}
-		return NULL;
-	}
-
+	if (argc != 3) return false;
 
-	// setting the server advertising on/off
-	if (strcmp(argv[1],"server_advertise") == 0) {
-		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3) {
-			if (strcmp(argv[2], "on") == 0 || atoi(argv[2]) == 1)
-				_network_advertise = true;
-			else {
-				NetworkUDPRemoveAdvertise();
-				_network_advertise = false;
-			}
-			IConsolePrintF(_iconsole_color_warning, "Server-advertise changed to '%s'", (_network_advertise)?"on":"off");
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current server-advertise is '%s'", (_network_advertise)?"on":"off");
-			IConsolePrint(_iconsole_color_warning, "Usage: set server_advertise on/off.");
-		}
-		return NULL;
-	}
+	if (!_network_server) {
+		SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
+	} else
+		NetworkServer_HandleChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
 
-	// setting the server 'pause on client join' on/off
-	if (strcmp(argv[1],"pause_on_join") == 0) {
-		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3) {
-			if (strcmp(argv[2], "on") == 0 || atoi(argv[2]) == 1)
-				_network_pause_on_join = true;
-			else
-				_network_pause_on_join = false;
-			IConsolePrintF(_iconsole_color_warning, "Pause-on-join changed to '%s'", (_network_pause_on_join)?"on":"off");
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current pause-on-join is '%s'", (_network_pause_on_join)?"on":"off");
-			IConsolePrint(_iconsole_color_warning, "Usage: set pause_on_join on/off.");
-		}
-		return NULL;
-	}
+	return true;
+}
 
-	// setting the server autoclean on/off
-	if (strcmp(argv[1],"autoclean_companies") == 0) {
-		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3) {
-			if (strcmp(argv[2], "on") == 0 || atoi(argv[2]) == 1)
-				_network_autoclean_companies = true;
-			else
-				_network_autoclean_companies = false;
-			IConsolePrintF(_iconsole_color_warning, "Autoclean-companies changed to '%s'", (_network_autoclean_companies)?"on":"off");
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current autoclean-companies is '%s'", (_network_autoclean_companies)?"on":"off");
-			IConsolePrint(_iconsole_color_warning, "Usage: set autoclean_companies on/off.");
-		}
-		return NULL;
+DEF_CONSOLE_HOOK(ConHookServerPW)
+{
+	if (strncmp(_network_server_password, "*", NETWORK_PASSWORD_LENGTH) == 0) {
+		_network_server_password[0] = '\0';
+		_network_game_info.use_password = 0;
+	} else
+		_network_game_info.use_password = 1;
+
+	return true;
+}
+
+DEF_CONSOLE_HOOK(ConHookRconPW)
+{
+	if (strncmp(_network_rcon_password, "*", NETWORK_PASSWORD_LENGTH) == 0)
+		_network_rcon_password[0] = '\0';
+
+	ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_game_info.rcon_password));
+
+	return true;
+}
+
+/* Also use from within player_gui to change the password graphically */
+bool NetworkChangeCompanyPassword(byte argc, char *argv[])
+{
+	if (argc == 0) {
+		IConsolePrintF(_iconsole_color_warning, "Current value of 'company_pw': %s", _network_player_info[_local_player].password);
+		return true;
 	}
 
-	// setting the server autoclean protected
-	if (strcmp(argv[1],"autoclean_protected") == 0) {
-		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3) {
-			_network_autoclean_protected = atoi(argv[2]);
-			IConsolePrintF(_iconsole_color_warning, "Autoclean-protected changed to '%d'", _network_autoclean_protected);
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current autoclean-protected is '%d'", _network_autoclean_protected);
-			IConsolePrint(_iconsole_color_warning, "Usage: set autoclean_protected <months>.");
-		}
-		return NULL;
-	}
-
-	// setting the server autoclean protected
-	if (strcmp(argv[1],"autoclean_unprotected") == 0) {
-		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3) {
-			_network_autoclean_unprotected = atoi(argv[2]);
-			IConsolePrintF(_iconsole_color_warning, "Autoclean-unprotected changed to '%d'", _network_autoclean_unprotected);
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current autoclean-unprotected is '%d'", _network_autoclean_unprotected);
-			IConsolePrint(_iconsole_color_warning, "Usage: set autoclean_unprotected <months>.");
-		}
-		return NULL;
+	if (_local_player >= MAX_PLAYERS) {
+		IConsoleError("You have to own a company to make use of this command.");
+		return false;
 	}
 
-	// setting the server auto restart date
-	if (strcmp(argv[1],"restart_game_date") == 0) {
+	if (argc != 1) return false;
+
+	if (strncmp(argv[0], "*", sizeof(_network_player_info[_local_player].password)) == 0)
+		argv[0][0] = '\0';
+
+	ttd_strlcpy(_network_player_info[_local_player].password, argv[0], sizeof(_network_player_info[_local_player].password));
+
+	if (!_network_server)
+		SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
+
+	return true;
+}
+
+DEF_CONSOLE_HOOK(ConProcPlayerName)
+{
+	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
+
+	if (ci == NULL) return false;
+
+	// Don't change the name if it is the same as the old name
+	if (strcmp(ci->client_name, _network_player_name) != 0) {
 		if (!_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
+			SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_network_player_name);
+		} else {
+			if (NetworkFindName(_network_player_name)) {
+				NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, _network_player_name);
+				ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
+				NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
+			}
 		}
-		if (argc == 3) {
-			_network_restart_game_date = atoi(argv[2]);
-			IConsolePrintF(_iconsole_color_warning, "Restart Game Date changed to '%d'", _network_restart_game_date);
-		} else {
-			IConsolePrintF(_iconsole_color_default, "Current Restart Game Date is '%d'", _network_restart_game_date);
-			IConsolePrint(_iconsole_color_warning, "Usage: set restart_game_date <year>. '0' means disabled.");
-			IConsolePrint(_iconsole_color_warning, " Auto-restart the server when 1 jan of this year is reached (e.g.: 2030).");
-		}
-		return NULL;
 	}
 
+	return true;
+}
+
+DEF_CONSOLE_HOOK(ConHookServerName)
+{
+	ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
+	return true;
+}
+
+DEF_CONSOLE_HOOK(ConHookServerAdvertise)
+{
+	if (!_network_advertise)
+		NetworkUDPRemoveAdvertise();
+
+	return true;
+}
+
+DEF_CONSOLE_CMD(ConProcServerIP)
+{
+	if (argc == 0) {
+		IConsolePrintF(_iconsole_color_warning, "Current value of 'server_ip': %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
+		return true;
+	}
+
+	if (argc != 1) return false;
+
+	_network_server_bind_ip = inet_addr(argv[0]);
+	snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
+	return true;
+}
+
+DEF_CONSOLE_CMD(ConPatch)
+{
+	if (argc == 0) {
+		IConsoleHelp("Change patch variables for all players. Usage: 'patch <name> [<value>]'");
+		IConsoleHelp("Omitting <value> will print out the current value of the patch-setting.");
+		return true;
+	}
+
+	if (argc == 1 || argc > 3) return false;
+
+	if (argc == 2) {
+		IConsoleGetPatchSetting(argv[1]);
+	} else
+		IConsoleSetPatchSetting(argv[1], argv[2]);
+
+	return true;
+}
 #endif /* ENABLE_NETWORK */
 
-	// Patch-options
-	if (strcmp(argv[1],"patch") == 0) {
-		if (_networking && !_network_server) {
-			IConsolePrintF(_iconsole_color_error, "You are not the server");
-			return NULL;
-		}
-		if (argc == 3)
-			ConsoleGetPatchSetting(argv[2]);
-		else if (argc == 4)
-			ConsoleSetPatchSetting(argv[2], argv[3]);
-		else
-			IConsolePrint(_iconsole_color_warning, "Usage: set patch <patch_name> [<value>].");
-		return NULL;
+DEF_CONSOLE_CMD(ConListDumpVariables)
+{
+	const IConsoleVar *var;
+	size_t l = 0;
+
+	if (argc == 0) {
+		IConsoleHelp("List all variables with their value. Usage: 'dump_vars [<pre-filter>]'");
+		return true;
 	}
 
+	if (argv[1] != NULL) l = strlen(argv[1]);
 
-	IConsolePrint(_iconsole_color_error, "Unknown setting");
-	IConsolePrint(_iconsole_color_error, "Known settings are:");
-#ifdef ENABLE_NETWORK
-	IConsolePrint(_iconsole_color_error, " - autoclean_companies on/off");
-	IConsolePrint(_iconsole_color_error, " - autoclean_protected <months>");
-	IConsolePrint(_iconsole_color_error, " - autoclean_unprotected <months>");
-	IConsolePrint(_iconsole_color_error, " - company_pw \"<password>\"");
-	IConsolePrint(_iconsole_color_error, " - max_join_time <frames>");
-	IConsolePrint(_iconsole_color_error, " - name \"<playername>\"");
-	IConsolePrint(_iconsole_color_error, " - pause_on_join on/off");
-	IConsolePrint(_iconsole_color_error, " - rcon_pw \"<password>\"");
-	IConsolePrint(_iconsole_color_error, " - server_name \"<name>\"");
-	IConsolePrint(_iconsole_color_error, " - server_advertise on/off");
-	IConsolePrint(_iconsole_color_error, " - server_bind_ip <ip>");
-	IConsolePrint(_iconsole_color_error, " - server_port <port>");
-	IConsolePrint(_iconsole_color_error, " - server_pw \"<password>\"");
-	IConsolePrint(_iconsole_color_error, " - restart_game_date \"<year>\"");
-#endif /* ENABLE_NETWORK */
-	IConsolePrint(_iconsole_color_error, " - patch <patch_name> [<value>]");
+	for (var = _iconsole_vars; var != NULL; var = var->next) {
+		if (argv[1] == NULL || strncmp(var->name, argv[1], l) == 0)
+			IConsoleVarPrintGetValue(var);
+	}
 
-	return NULL;
+	return true;
 }
 
 
@@ -1238,12 +1141,10 @@
 	// debugging variables and functions
 	extern bool _stdlib_con_developer; /* XXX extern in .c */
 
-	IConsoleVarRegister("con_developer", &_stdlib_con_developer, ICONSOLE_VAR_BOOLEAN);
-	IConsoleVarMemRegister("temp_string2", ICONSOLE_VAR_STRING);
-	IConsoleVarMemRegister("temp_uint16_2", ICONSOLE_VAR_UINT16);
-	IConsoleCmdRegister("resettile", ConResetTile);
-	IConsoleAliasRegister("dbg_echo","echo %A; echo %B");
-	IConsoleAliasRegister("dbg_echo2","echo %+");
+	IConsoleVarRegister("con_developer",    &_stdlib_con_developer, ICONSOLE_VAR_BOOLEAN, "Enable/disable console debugging information (internal)");
+	IConsoleCmdRegister("resettile",        ConResetTile);
+	IConsoleAliasRegister("dbg_echo",       "echo %A; echo %B");
+	IConsoleAliasRegister("dbg_echo2",      "echo %!");
 }
 #endif
 
@@ -1268,86 +1169,129 @@
 	IConsoleCmdRegister("info_var",     ConInfoVar);
 	IConsoleCmdRegister("list_cmds",    ConListCommands);
 	IConsoleCmdRegister("list_vars",    ConListVariables);
-	IConsoleCmdRegister("list_aliases",    ConListAliases);
-	IConsoleCmdRegister("newgame",         ConNewGame);
-	IConsoleCmdRegister("printf",       ConPrintF);
-	IConsoleCmdRegister("printfc",      ConPrintFC);
+	IConsoleCmdRegister("list_aliases", ConListAliases);
+	IConsoleCmdRegister("newgame",      ConNewGame);
 	IConsoleCmdRegister("quit",         ConExit);
-	IConsoleCmdRegister("random",       ConRandom);
 	IConsoleCmdRegister("resetengines", ConResetEngines);
-	IConsoleCmdRegister("return",     ConReturn);
-	IConsoleCmdRegister("screenshot", ConScreenShot);
-	IConsoleCmdRegister("script",     ConScript);
-	IConsoleCmdRegister("scrollto",   ConScrollToTile);
-	IConsoleCmdRegister("set",			ConSet);
-	IConsoleCmdRegister("alias",		ConAlias);
-	IConsoleCmdRegister("load",			ConLoad);
-	IConsoleCmdRegister("save",			ConSave);
-	IConsoleCmdRegister("ls", ConListFiles);
-	IConsoleCmdRegister("cd", ConChangeDirectory);
-	IConsoleCmdRegister("pwd", ConPrintWorkingDirectory);
-	IConsoleAliasRegister("dir", "ls");
+	IConsoleCmdRegister("return",       ConReturn);
+	IConsoleCmdRegister("screenshot",   ConScreenShot);
+	IConsoleCmdRegister("script",       ConScript);
+	IConsoleCmdRegister("scrollto",     ConScrollToTile);
+	IConsoleCmdRegister("alias",	      ConAlias);
+	IConsoleCmdRegister("load",			    ConLoad);
+	IConsoleCmdRegister("save",			    ConSave);
+	IConsoleCmdRegister("ls",           ConListFiles);
+	IConsoleCmdRegister("cd",           ConChangeDirectory);
+	IConsoleCmdRegister("pwd",          ConPrintWorkingDirectory);
+
+	IConsoleAliasRegister("dir",      "ls");
+	IConsoleAliasRegister("newmap",   "newgame");
+	IConsoleAliasRegister("new_map",  "newgame");
 	IConsoleAliasRegister("new_game", "newgame");
-	IConsoleAliasRegister("newmap", "newgame");
-	IConsoleAliasRegister("new_map", "newgame");
-
-	IConsoleVarRegister("developer", &_stdlib_developer, ICONSOLE_VAR_BYTE);
-
-	// temporary data containers for alias scripting
-	IConsoleVarMemRegister("temp_string", ICONSOLE_VAR_STRING);
-	IConsoleVarMemRegister("temp_bool", ICONSOLE_VAR_BOOLEAN);
-	IConsoleVarMemRegister("temp_int16", ICONSOLE_VAR_INT16);
-	IConsoleVarMemRegister("temp_int32", ICONSOLE_VAR_INT32);
-	IConsoleVarMemRegister("temp_pointer", ICONSOLE_VAR_POINTER);
-	IConsoleVarMemRegister("temp_uint16", ICONSOLE_VAR_UINT16);
-	IConsoleVarMemRegister("temp_uint32", ICONSOLE_VAR_UINT32);
 
 
-	// networking variables and functions
-#ifdef ENABLE_NETWORK
-	IConsoleCmdRegister("say",        ConSay);
-	IConsoleCmdHook("say", ICONSOLE_HOOK_ACCESS, ConCmdHookNeedNetwork);
-	IConsoleCmdRegister("say_player", ConSayPlayer);
-	IConsoleCmdHook("say_player", ICONSOLE_HOOK_ACCESS, ConCmdHookNeedNetwork);
-	IConsoleCmdRegister("say_client", ConSayClient);
-	IConsoleCmdHook("say_client", ICONSOLE_HOOK_ACCESS, ConCmdHookNeedNetwork);
-	IConsoleCmdRegister("kick",         ConKick);
-	IConsoleCmdHook("kick", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
-	IConsoleCmdRegister("reset_company",         ConResetCompany);
-	IConsoleCmdHook("reset_company", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
-	IConsoleCmdRegister("connect", ConNetworkConnect);
-	IConsoleCmdHook("connect", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetServer);
-	IConsoleCmdRegister("clients", ConNetworkClients);
-	IConsoleCmdRegister("status",   ConStatus);
-	IConsoleCmdHook("status", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
-	IConsoleCmdHook("resetengines", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetwork);
+	IConsoleVarRegister("developer", &_stdlib_developer, ICONSOLE_VAR_BYTE, "Redirect debugging output from the console/command line to the ingame console (value 2). Default value: 1");
 
-	IConsoleCmdRegister("rcon",        ConRcon);
-	IConsoleCmdHook("rcon", ICONSOLE_HOOK_ACCESS, ConCmdHookNeedNetwork);
+	/* networking variables and functions */
+#ifdef ENABLE_NETWORK
+	/*** Networking commands ***/
+	IConsoleCmdRegister("say",             ConSay);
+	IConsoleCmdHookAdd("say",              ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
+	IConsoleCmdRegister("say_player",      ConSayPlayer);
+	IConsoleCmdHookAdd("say_player",       ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
+	IConsoleCmdRegister("say_client",      ConSayClient);
+	IConsoleCmdHookAdd("say_client",       ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
+	IConsoleCmdRegister("kick",            ConKick);
+	IConsoleCmdHookAdd("kick",             ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleCmdRegister("reset_company",   ConResetCompany);
+	IConsoleCmdHookAdd("reset_company",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleAliasRegister("clean_company", "reset_company %A");
+	IConsoleCmdRegister("connect",         ConNetworkConnect);
+	IConsoleCmdHookAdd("connect",          ICONSOLE_HOOK_ACCESS, ConHookClientOnly);
+	IConsoleCmdRegister("clients",         ConNetworkClients);
+	IConsoleCmdRegister("status",          ConStatus);
+	IConsoleCmdHookAdd("status",           ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleCmdHookAdd("resetengines",     ICONSOLE_HOOK_ACCESS, ConHookNoNetwork);
 
-	IConsoleCmdRegister("ban",   ConBan);
-	IConsoleCmdHook("ban", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
-	IConsoleCmdRegister("unban",   ConUnBan);
-	IConsoleCmdHook("unban", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
-	IConsoleCmdRegister("banlist",   ConBanList);
-	IConsoleCmdHook("banlist", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
-	IConsoleCmdRegister("pause",   ConPauseGame);
-	IConsoleCmdHook("pause", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
-	IConsoleCmdRegister("unpause",   ConUnPauseGame);
-	IConsoleCmdHook("unpause", ICONSOLE_HOOK_ACCESS, ConCmdHookNoNetClient);
+	IConsoleCmdRegister("rcon",            ConRcon);
+	IConsoleCmdHookAdd("rcon",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 
-	IConsoleAliasRegister("clean_company",		"reset_company %A");
+	IConsoleCmdRegister("ban",             ConBan);
+	IConsoleCmdHookAdd("ban",              ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleCmdRegister("unban",           ConUnBan);
+	IConsoleCmdHookAdd("unban",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleCmdRegister("banlist",         ConBanList);
+	IConsoleCmdHookAdd("banlist",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleCmdRegister("pause",           ConPauseGame);
+	IConsoleCmdHookAdd("pause",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleCmdRegister("unpause",         ConUnPauseGame);
+	IConsoleCmdHookAdd("unpause",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
-	IConsoleVarRegister("net_frame_freq", &_network_frame_freq, ICONSOLE_VAR_UINT8);
-	IConsoleVarHook("net_frame_freq", ICONSOLE_HOOK_ACCESS, ConVarHookNoNetClient);
-	IConsoleVarRegister("net_sync_freq", &_network_sync_freq, ICONSOLE_VAR_UINT16);
-	IConsoleVarHook("net_sync_freq", ICONSOLE_HOOK_ACCESS, ConVarHookNoNetClient);
+	IConsoleCmdRegister("patch",           ConPatch);
+	IConsoleCmdHookAdd("patch",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+
+	/*** Networking variables ***/
+	IConsoleVarRegister("net_frame_freq",        &_network_frame_freq, ICONSOLE_VAR_BYTE, "The amount of frames before a command will be (visibly) executed. Default value: 1");
+	IConsoleVarHookAdd("net_frame_freq",         ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleVarRegister("net_sync_freq",         &_network_sync_freq,  ICONSOLE_VAR_UINT16, "The amount of frames to check if the game is still in sync. Default value: 100");
+	IConsoleVarHookAdd("net_sync_freq",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+
+	IConsoleVarStringRegister("server_pw",       &_network_server_password, sizeof(_network_server_password), "Set the server password to protect your server. Use '*' to clear the password");
+	IConsoleVarHookAdd("server_pw",              ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleVarHookAdd("server_pw",              ICONSOLE_HOOK_POST_ACTION, ConHookServerPW);
+	IConsoleAliasRegister("server_password",     "server_pw %+");
+
+	IConsoleVarStringRegister("rcon_pw",         &_network_rcon_password, sizeof(_network_rcon_password), "Set the rcon-password to change server behaviour. Use '*' to disable rcon");
+	IConsoleVarHookAdd("rcon_pw",                ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleVarHookAdd("rcon_pw",                ICONSOLE_HOOK_POST_ACTION, ConHookRconPW);
+	IConsoleAliasRegister("rcon_password",       "rcon_pw %+");
+
+	IConsoleVarStringRegister("company_pw",      NULL, 0, "Set a password for your company, so no one without the correct password can join. Use '*' to clear the password");
+	IConsoleVarHookAdd("company_pw",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
+	IConsoleVarProcAdd("company_pw",             NetworkChangeCompanyPassword);
+	IConsoleAliasRegister("company_password",    "company_pw %+");
+
+	IConsoleVarStringRegister("name",            &_network_player_name, sizeof(_network_player_name), "Set your name for multiplayer");
+	IConsoleVarHookAdd("name",                   ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
+	IConsoleVarHookAdd("name",                   ICONSOLE_HOOK_POST_ACTION, ConProcPlayerName);
+
+	IConsoleVarStringRegister("server_name",     &_network_server_name, sizeof(_network_server_name), "Set the name of the server for multiplayer");
+	IConsoleVarHookAdd("server_name",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleVarHookAdd("server_name",            ICONSOLE_HOOK_POST_ACTION, ConHookServerName);
+
+	IConsoleVarRegister("server_port",           &_network_server_port, ICONSOLE_VAR_UINT32, "Set the server port. Changes take effect the next time you start a server");
+
+	IConsoleVarRegister("server_ip",             &_network_server_bind_ip, ICONSOLE_VAR_UINT32, "Set the IP the server binds to. Changes take effect the next time you start a server");
+	IConsoleVarProcAdd("server_ip",              ConProcServerIP);
+	IConsoleAliasRegister("server_bind_ip",      "server_ip %+");
+	IConsoleAliasRegister("server_ip_bind",      "server_ip %+");
+	IConsoleAliasRegister("server_bind",         "server_ip %+");
+
+	IConsoleVarRegister("max_join_time",         &_network_max_join_time, ICONSOLE_VAR_UINT16, "Set the maximum amount of time (ticks) a client is allowed to join. Default value: 500");
+
+	IConsoleVarRegister("server_advertise",      &_network_advertise, ICONSOLE_VAR_BOOLEAN, "Set if the server will advertise to the master server and show up there");
+	IConsoleVarHookAdd("server_advertise",       ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+	IConsoleVarHookAdd("server_advertise",       ICONSOLE_HOOK_POST_ACTION, ConHookServerAdvertise);
+
+	IConsoleVarRegister("pause_on_join",         &_network_pause_on_join, ICONSOLE_VAR_BOOLEAN, "Set if the server should pause gameplay while a client is joining. This might help slow users");
+	IConsoleVarHookAdd("pause_on_join",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+
+	IConsoleVarRegister("autoclean_companies",   &_network_autoclean_companies, ICONSOLE_VAR_BOOLEAN, "Automatically shut down inactive companies to free them up for other players. Customize with 'autoclean_(un)protected'");
+	IConsoleVarHookAdd("autoclean_companies",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+
+	IConsoleVarRegister("autoclean_protected",   &_network_autoclean_protected, ICONSOLE_VAR_BYTE, "Automatically remove the password from an inactive company after the given amount of months");
+	IConsoleVarHookAdd("autoclean_protected",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+
+	IConsoleVarRegister("autoclean_unprotected", &_network_autoclean_protected, ICONSOLE_VAR_BYTE, "Automatically shut down inactive companies after the given amount of months");
+	IConsoleVarHookAdd("autoclean_unprotected",  ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+
+	IConsoleVarRegister("restart_game_date",     &_network_restart_game_date, ICONSOLE_VAR_BYTE, "Auto-restart the server when Jan 1st of the set year is reached. Use '0' to disable this");
+	IConsoleVarHookAdd("restart_game_date",      ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
+
 #endif /* ENABLE_NETWORK */
 
 	// debugging stuff
 #ifdef _DEBUG
 	IConsoleDebugLibRegister();
 #endif
-
 }
-/* -------------------- don't cross this line --------------------- */
--- a/network.c	Sun May 01 20:16:52 2005 +0000
+++ b/network.c	Mon May 02 15:52:19 2005 +0000
@@ -1370,21 +1370,6 @@
 	}
 	#endif
 }
-
-void NetworkChangeCompanyPassword(const char *str)
-{
-	if (strncmp(str, "*", sizeof(_network_player_info[_local_player].password)) == 0) {
-		_network_player_info[_local_player].password[0] = '\0';
-		IConsolePrint(_iconsole_color_warning, "Company password protection removed.");
-	} else {
-		ttd_strlcpy(_network_player_info[_local_player].password, str, sizeof(_network_player_info[_local_player].password));
-		IConsolePrintF(_iconsole_color_warning, "Company protected with password '%s'.", _network_player_info[_local_player].password);
-	}
-
-	if (!_network_server)
-		SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
-}
-
 #else
 
 void ParseConnectionString(const char **player, const char **port, char *connection_string) {}
--- a/network.h	Sun May 01 20:16:52 2005 +0000
+++ b/network.h	Mon May 02 15:52:19 2005 +0000
@@ -217,6 +217,6 @@
 void NetworkUpdateClientInfo(uint16 client_index);
 void NetworkAddServer(const char *b);
 void NetworkRebuildHostList(void);
-void NetworkChangeCompanyPassword(const char *str);
+bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
 
 #endif /* NETWORK_H */
--- a/player_gui.c	Sun May 01 20:16:52 2005 +0000
+++ b/player_gui.c	Mon May 02 15:52:19 2005 +0000
@@ -656,7 +656,7 @@
 		#ifdef ENABLE_NETWORK
 		case 2: /* Change company password */
 			if (*b == 0) *b = '*'; // empty password is a '*' because of console argument
-			NetworkChangeCompanyPassword(b);
+			NetworkChangeCompanyPassword(1, &b);
 		#endif
 		}
 	} break;
--- a/settings.h	Sun May 01 20:16:52 2005 +0000
+++ b/settings.h	Mon May 02 15:52:19 2005 +0000
@@ -42,4 +42,7 @@
 	const void *b;
 } SettingDesc;
 
+void IConsoleSetPatchSetting(const char *name, const char *value);
+void IConsoleGetPatchSetting(const char *name);
+
 #endif /* SETTINGS_H */
--- a/settings_gui.c	Sun May 01 20:16:52 2005 +0000
+++ b/settings_gui.c	Mon May 02 15:52:19 2005 +0000
@@ -1033,17 +1033,22 @@
 	}
 }
 
+/**
+ * Network-safe changing of patch-settings.
+ * @param p1 bytes 0 - 7:  the patches type (page) that is being changed (construction, network, ai)
+ * @param p1 bytes 8 - ..: the actual patch (entry) being set inside the category
+ * @param p2 the new value for the patch
+ */
 int32 CmdChangePatchSetting(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
-	const PatchPage *page;
-	const PatchEntry *pe;
+	byte pcat = p1 & 0xFF;
+	byte pel = (p1 >> 8) & 0xFF;
+
+	if (pcat >= lengthof(_patches_page)) return 0;
+	if (pel >= _patches_page[pcat].num) return 0;
 
 	if (flags & DC_EXEC) {
-		page = &_patches_page[(byte)p1];
-		if (page == NULL) return 0;
-		pe = &page->entries[(byte)(p1 >> 8)];
-		if (pe == NULL) return 0;
-
+		const PatchEntry *pe = &_patches_page[pcat].entries[pel];
 		WritePE(pe, (int32)p2);
 
 		InvalidateWindow(WC_GAME_OPTIONS, 0);
@@ -1052,116 +1057,79 @@
 	return 0;
 }
 
+static const PatchEntry *IConsoleGetPatch(const char *name, uint *page, uint *entry)
+{
+	const PatchPage *pp;
+	const PatchEntry *pe;
+
+	for (*page = 0; *page < lengthof(_patches_page); (*page)++) {
+		pp = &_patches_page[*page];
+		for (*entry = 0; *entry < pp->num; (*entry)++) {
+			pe = &pp->entries[*entry];
+			if (strncmp(pe->console_name, name, sizeof(pe->console_name)) == 0)
+				return pe;
+		}
+	}
+
+	return NULL;
+}
+
 /* Those 2 functions need to be here, else we have to make some stuff non-static
     and besides, it is also better to keep stuff like this at the same place */
-void ConsoleSetPatchSetting(char *name, char *value)
+void IConsoleSetPatchSetting(char *name, const char *value)
 {
-	const PatchPage *page;
-	const PatchEntry *pe = NULL;
-	bool found = false;
-	uint i;
-	unsigned int j;
+	const PatchEntry *pe;
+	uint page, entry;
 	int val;
 
-	/* Search for the name in the patch-settings */
-	for (i = 0; i < lengthof(_patches_page); i++) {
-		page = &_patches_page[i];
-		for (j = 0; j < page->num; j++) {
-			pe = &page->entries[j];
-			if (strncmp(pe->console_name, name, sizeof(pe->console_name)) == 0) {
-				/* We found the name */
-				found = true;
-				break;
-			}
-		}
-		if (found)
-			break;
-	}
+	pe = IConsoleGetPatch(name, &page, &entry);
 
-	/* We did not found the patch setting */
-	if (!found || pe == NULL) {
-		IConsolePrintF(_iconsole_color_warning, "'%s' is an unkown patch setting", name);
+	if (pe == NULL) {
+		IConsolePrintF(_iconsole_color_warning, "'%s' is an unknown patch setting.", name);
 		return;
 	}
 
-	val = atoi(value);
+	sscanf(value, "%d", &val);
 
-	if (pe->type == PE_CURRENCY) {
+	if (pe->type == PE_CURRENCY) // currency can be different on each client
 		val /= GetCurrentCurrencyRate();
-	}
 
 	// If an item is playerbased, we do not send it over the network (if any)
 	if (pe->flags & PF_PLAYERBASED) {
 		WritePE(pe, val);
-	} else {
-		// Else we do
-		DoCommandP(0, i + (j << 8), val, NULL, CMD_CHANGE_PATCH_SETTING);
-	}
+	} else // Else we do
+		DoCommandP(0, page + (entry << 8), val, NULL, CMD_CHANGE_PATCH_SETTING);
 
-	switch(pe->type) {
-		case PE_BOOL:
-			if (val == 1)
-				snprintf(value, sizeof(value), "enabled");
-			else
-				snprintf(value, sizeof(value), "disabled");
-			break;
-		default:
-			break;
+	{
+		char tval[20];
+		const char *tval2 = value;
+		if (pe->type == PE_BOOL) {
+			snprintf(tval, sizeof(tval), (val == 1) ? "on" : "off");
+			tval2 = tval;
+		}
+
+		IConsolePrintF(_iconsole_color_warning, "'%s' changed to:  %s", name, tval2);
 	}
-
-	IConsolePrintF(_iconsole_color_warning, "'%s' changed in:", name);
-	IConsolePrintF(_iconsole_color_warning, "  '%s'", value);
 }
 
-void ConsoleGetPatchSetting(char *name)
+void IConsoleGetPatchSetting(const char *name)
 {
-	const PatchPage *page;
-	const PatchEntry *pe = NULL;
-	char value[50];
-	bool found = false;
-	uint i;
-	unsigned int j;
+	char value[20];
+	uint page, entry;
+	const PatchEntry *pe = IConsoleGetPatch(name, &page, &entry);
 
-	/* Search for the name in the patch-settings */
-	for (i = 0; i < lengthof(_patches_page); i++) {
-		page = &_patches_page[i];
-		for (j = 0; j < page->num; j++) {
-			pe = &page->entries[j];
-			if (strncmp(pe->console_name, name, sizeof(pe->console_name)) == 0) {
-				/* We found the name */
-				found = true;
-				break;
-			}
-		}
-		if (found)
-			break;
-	}
-
-	/* We did not found the patch setting */
-	if (!found || pe == NULL) {
-		IConsolePrintF(_iconsole_color_warning, "'%s' is an unkown patch setting", name);
+	/* We did not find the patch setting */
+	if (pe == NULL) {
+		IConsolePrintF(_iconsole_color_warning, "'%s' is an unknown patch setting.", name);
 		return;
 	}
 
-	/* 'pe' is now the correct patch setting */
-	switch(pe->type) {
-		case PE_BOOL:
-			if (ReadPE(pe) == 1)
-				snprintf(value, sizeof(value), "enabled");
-			else
-				snprintf(value, sizeof(value), "disabled");
-			break;
-		case PE_UINT8:
-		case PE_INT16:
-		case PE_UINT16:
-		case PE_INT32:
-		case PE_CURRENCY:
-			snprintf(value, sizeof(value), "%d", ReadPE(pe));
-			break;
-	}
+	if (pe->type == PE_BOOL) {
+		snprintf(value, sizeof(value), (ReadPE(pe) == 1) ? "on" : "off");
+	} else
+		snprintf(value, sizeof(value), "%d", ReadPE(pe));
 
-	IConsolePrintF(_iconsole_color_warning, "Current value for '%s' is:", name);
-	IConsolePrintF(_iconsole_color_warning, "  '%s'", value);
+	IConsolePrintF(_iconsole_color_warning, "Current value for '%s' is: '%s'", name, value);
 }
 
 static const Widget _patches_selection_widgets[] = {