Scandum 6 лет назад
Родитель
Сommit
17978b07ab
47 измененных файлов с 2910 добавлено и 1818 удалено
  1. 3 2
      CREDITS
  2. 26 13
      TODO
  3. 52 7
      mods/igr.mods
  4. 8 9
      src/Makefile.in
  5. 0 89
      src/action.c
  6. 0 151
      src/alias.c
  7. 12 15
      src/buffer.c
  8. 3 1
      src/chat.c
  9. 8 1
      src/class.c
  10. 54 12
      src/config.c
  11. 10 3
      src/cursor.c
  12. 39 14
      src/data.c
  13. 10 0
      src/debug.c
  14. 10 0
      src/event.c
  15. 21 5
      src/files.c
  16. 0 72
      src/gag.c
  17. 109 20
      src/help.c
  18. 0 211
      src/highlight.c
  19. 1 1
      src/history.c
  20. 30 92
      src/input.c
  21. 142 69
      src/line.c
  22. 40 14
      src/log.c
  23. 0 66
      src/macro.c
  24. 13 13
      src/main.c
  25. 292 183
      src/mapper.c
  26. 3 1
      src/math.c
  27. 1 1
      src/misc.c
  28. 14 5
      src/net.c
  29. 3 3
      src/parse.c
  30. 5 2
      src/port.c
  31. 0 197
      src/prompt.c
  32. 121 26
      src/screen.c
  33. 23 8
      src/session.c
  34. 75 42
      src/show.c
  35. 100 2
      src/split.c
  36. 2 2
      src/ssl.c
  37. 1040 56
      src/substitute.c
  38. 0 56
      src/tab.c
  39. 135 12
      src/tables.c
  40. 18 15
      src/telopt_client.c
  41. 1 1
      src/telopt_server.c
  42. 19 26
      src/text.c
  43. 361 282
      src/tintin.h
  44. 1 1
      src/tokenize.c
  45. 2 2
      src/utils.c
  46. 69 7
      src/variable.c
  47. 34 8
      src/vt102.c

+ 3 - 2
CREDITS

@@ -23,9 +23,10 @@ Special thanks to the following
 
 
 Beta Testers
 Beta Testers
 -----------------------------------------------------------------------------
 -----------------------------------------------------------------------------
-There are too many to list, but your help has been greatly appreciated. You
-are important to TinTin++'s continued success.
+Unfortunately (or fortunately) there are too many to list, but your help has
+been greatly appreciated. You are invaluable to TinTin++'s continued success.
 
 
+Thanks!
 
 
 
 
 Modification History
 Modification History

+ 26 - 13
TODO

@@ -1,21 +1,36 @@
 * STUFF THAT IS PROBABLY GONNA GET DONE
 * STUFF THAT IS PROBABLY GONNA GET DONE
 
 
-  - add #line background option that prevents automatic session
-    activation.
+  - #loop {1} {1000} {cnt} {#var test[$cnt] 123456789-123456789-123456789-123456789-123456789-123456789-123456789-123456789-}
 
 
-  - add syntax highlighting to map data.
+  - add #map destroy area <area>
 
 
-  - add maze flag for maze handling.
+  - make format %X take unicode
+
+  - more potent long-click handling including held down ticks.
+
+  - look into discord api / arachnos
+
+  - finish mth true color conversion code
+
+  - #bell off option.
+
+  - draw example in #help
+
+  - make *draw_room more comprehensible
 
 
-  - asciivnum void room display.
+  - give SUB_FIX its own flag to avoid confusion.
 
 
-  - look into empty symbol setting.
+  - #detach command.
 
 
-  - easier bit checks for map data
+  - Improve #draw including 0000 mode.
+
+  - Add gtd->cursor_level to avoid saving an already saved cursor position
+
+  - add maze flag for maze handling.
+
+  - #buffer copy {lines} with strip option. #line strip?
 
 
-  - #buffer copy {lines} with strip option.
 
 
-  - add #line logmode {raw|html|plain} option
 
 
   - add class specific debug
   - add class specific debug
 
 
@@ -23,8 +38,6 @@
 
 
   - Work on VT2020
   - Work on VT2020
 
 
-  - massive map / html map drawing.
-
   - add tunnel void utility to #map interface. (covered by #map move tho)
   - add tunnel void utility to #map interface. (covered by #map move tho)
 
 
   - make #split static and fix wrapping of split line on horizontal shrink.
   - make #split static and fix wrapping of split line on horizontal shrink.
@@ -51,8 +64,6 @@
 
 
   - set packet patch on EOR and GA detection. #config packet patch auto ?
   - set packet patch on EOR and GA detection. #config packet patch auto ?
 
 
-  - See if cpu usage of time events can be lowered.
-
   - Add debugger to syntax highlighter, substitution highlighing, 256 color support, and variable expansion.
   - Add debugger to syntax highlighter, substitution highlighing, 256 color support, and variable expansion.
 
 
   - allow #class save/load to memory.
   - allow #class save/load to memory.
@@ -170,6 +181,8 @@
 
 
   - http://tintin.sourceforge.net/board/viewtopic.php?p=9934 Strange #map pathdir bug
   - http://tintin.sourceforge.net/board/viewtopic.php?p=9934 Strange #map pathdir bug
 
 
+  - Add seconds till execution message to delays and tickers.
+
 --------------------------------------------------------------------------------
 --------------------------------------------------------------------------------
 
 
 * ROADMAP
 * ROADMAP

+ 52 - 7
mods/igr.mods

@@ -1,4 +1,55 @@
-Jul 2019        2.02.0
+Sep 2019        2.01.92
+------------------------------------------------------------------------------
+
+Aug 2019        2.01.91
+------------------------------------------------------------------------------
+vt100.c         Added %2 rows %3 cols arguments to the VT100 SCROLL REGION
+                event to increase ease of use.
+
+mapper.c        Changed #map at to also take an exit for the location.
+
+data.c          No longer saving or displaying the priority of triggers which
+                are set to the default priority.
+
+mapper.c        Added #map map <rows> <cols> draw <square> to draw the map at
+                the given location. This is no real alternative for using #map
+                offset as #map offset allows mouse map events.
+
+draw.c          Added unicode drawing options.
+
+line.c          Added #line logmode {html|plain|raw} {argument} Allows you
+                to execute a command with a temporary logging mode.
+
+mapper.c        Now drawing + and - for muds using nu dn eu ed exits.
+
+macro.c         Added ^ support to macros to make a macro only trigger at the
+                start of input. If you want to macro a literal ^ use \^ at
+                the start of the line. It behaves very similar to the ~ for
+                color triggers.
+
+mapper.c        Improved exit drawing in unicode mode.
+
+draw.c          Added #draw command and #help file.
+
+mapper.c        Added #map update option to force an update of the vtmap. Keep
+                in mind the vtmap will only update once every 0.1 seconds.
+
+screen.c        Added #screen clear {split|top|bottom} to clear split lines.
+
+config.c        Added #config {wordwrap {on|off|number} when a number is given
+                tintin will wrap at the given width, and will also report the
+                given width to MUDs over TELNET.
+
+config.c        Added #config {telnet} {on|off|debug} which allows enabling or
+                disabling telnet support. The debug option is the same as
+                #config {debug telnet} on and will eventually replace it. To
+                disable debug mode use #config telnet on.
+
+help.c          Added #help button
+
+button.c        Added #button.
+
+Jul 2019        2.01.90
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 mapper.c        Added MAP FOLLOWED MAP event which triggers on map movement.
 mapper.c        Added MAP FOLLOWED MAP event which triggers on map movement.
                 %0 = new vnum %1 = old vnum %2 = exit name. Keep in mind
                 %0 = new vnum %1 = old vnum %2 = exit name. Keep in mind
@@ -118,8 +169,6 @@ mapper.c        Further improved unicodegraphics mode.
 
 
 mapper.c        Further improved blockgraphics mode.
 mapper.c        Further improved blockgraphics mode.
 
 
-mapper.c        Hidden rooms are now shown to avoid confusion.
-
 mapper.c        Added #map color avoid
 mapper.c        Added #map color avoid
 
 
 mapper.c        Added #map color hide
 mapper.c        Added #map color hide
@@ -176,10 +225,6 @@ event.c         Changed all MOUSE events to %0=row %1=col %2=-row %3=-row
                 and because I've repeatedly swapped row and col in VT100 which
                 and because I've repeatedly swapped row and col in VT100 which
                 can be a tricky bug to track down.
                 can be a tricky bug to track down.
 
 
-Jul 2019        2.01.9 (beta)
-------------------------------------------------------------------------------
-
-
 session.c       Added the 'ats' keyword to the session find routine to return
 session.c       Added the 'ats' keyword to the session find routine to return
                 the active tintin session.
                 the active tintin session.
 
 

+ 8 - 9
src/Makefile.in

@@ -57,15 +57,14 @@ DEFAULT_FILE_DIR = $(HOME)
 FFLAGS= $(F1) $(F6)
 FFLAGS= $(F1) $(F6)
 
 
 
 
-OFILES = action.o alias.o files.o help.o highlight.o strhash.o input.o log.o \
-         main.o misc.o net.o parse.o path.o update.o history.o tab.o vt102.o \
-         terminal.o session.o function.o text.o substitute.o tick.o memory.o \
-         math.o split.o debug.o tinexp.o mapper.o tables.o buffer.o prompt.o \
-         class.o event.o tokenize.o chat.o utf8.o config.o gag.o advertise.o \
-         list.o forkpty.o cursor.o system.o line.o data.o variable.o macro.o \
-         msdp.o ssl.o port.o scan.o telopt_client.o screen.o telopt_server.o \
-         utils.o nest.o show.o mccp.o
-
+OFILES = \
+files.o help.o strhash.o input.o main.o misc.o net.o parse.o debug.o \
+update.o history.o vt102.o terminal.o text.o memory.o math.o split.o \
+system.o mapper.o tables.o buffer.o event.o tokenize.o chat.o utf8.o \
+advertise.o list.o forkpty.o utils.o line.o data.o variable.o msdp.o \
+port.o scan.o telopt_client.o screen.o cursor.o nest.o show.o mccp.o \
+telopt_server.o draw.o log.o path.o session.o class.o config.o ssl.o \
+regex.o trigger.o substitute.o
 
 
 default: all
 default: all
 
 

+ 0 - 89
src/action.c

@@ -1,89 +0,0 @@
-/******************************************************************************
-*   This file is part of TinTin++                                             *
-*                                                                             *
-*   Copyright 2004-2019 Igor van den Hoven                                    *
-*                                                                             *
-*   TinTin++ is free software; you can redistribute it and/or modify          *
-*   it under the terms of the GNU General Public License as published by      *
-*   the Free Software Foundation; either version 3 of the License, or         *
-*   (at your option) any later version.                                       *
-*                                                                             *
-*   This program is distributed in the hope that it will be useful,           *
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
-*   GNU General Public License for more details.                              *
-*                                                                             *
-*                                                                             *
-*   You should have received a copy of the GNU General Public License         *
-*   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
-******************************************************************************/
-
-/******************************************************************************
-*                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
-*                                                                             *
-*                         coded by Peter Unold 1992                           *
-******************************************************************************/
-
-#include "tintin.h"
-
-DO_COMMAND(do_action)
-{
-	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE];
-
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
-	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
-	arg = get_arg_in_braces(ses, arg, arg3, GET_ALL);
-
-	if (*arg3 == 0)
-	{
-		strcpy(arg3, "5");
-	}
-
-	if (*arg1 == 0)
-	{
-		show_list(ses->list[LIST_ACTION], 0);
-	}
-	else if (*arg1 && *arg2 == 0)
-	{
-		if (show_node_with_wild(ses, arg1, ses->list[LIST_ACTION]) == FALSE)
-		{
-			show_message(ses, LIST_ACTION, "#ACTION: NO MATCH(ES) FOUND FOR {%s}.", arg1);
-		}
-	}
-	else
-	{
-		update_node_list(ses->list[LIST_ACTION], arg1, arg2, arg3, "");
-
-		show_message(ses, LIST_ACTION, "#OK. #ACTION {%s} NOW TRIGGERS {%s} @ {%s}.", arg1, arg2, arg3);
-	}
-	return ses;
-}
-
-
-DO_COMMAND(do_unaction)
-{
-	delete_node_with_wild(ses, LIST_ACTION, arg);
-
-	return ses;
-}
-
-
-void check_all_actions(struct session *ses, char *original, char *line)
-{
-	struct listroot *root = ses->list[LIST_ACTION];
-	char buf[BUFFER_SIZE];
-
-	for (root->update = 0 ; root->update < root->used ; root->update++)
-	{
-		if (check_one_regexp(ses, root->list[root->update], line, original, 0))
-		{
-			show_debug(ses, LIST_ACTION, "#DEBUG ACTION {%s}", root->list[root->update]->arg1);
-
-			substitute(ses, root->list[root->update]->arg2, buf, SUB_ARG|SUB_SEC);
-
-			script_driver(ses, LIST_ACTION, buf);
-
-			return;
-		}
-	}
-}

+ 0 - 151
src/alias.c

@@ -1,151 +0,0 @@
-/******************************************************************************
-*   This file is part of TinTin++                                             *
-*                                                                             *
-*   Copyright 2004-2019 Igor van den Hoven                                    *
-*                                                                             *
-*   TinTin++ is free software; you can redistribute it and/or modify          *
-*   it under the terms of the GNU General Public License as published by      *
-*   the Free Software Foundation; either version 3 of the License, or         *
-*   (at your option) any later version.                                       *
-*                                                                             *
-*   This program is distributed in the hope that it will be useful,           *
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
-*   GNU General Public License for more details.                              *
-*                                                                             *
-*                                                                             *
-*   You should have received a copy of the GNU General Public License         *
-*   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
-******************************************************************************/
-
-/******************************************************************************
-*               (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                  *
-*                                                                             *
-*                        coded by Peter Unold 1992                            *
-*                   recoded by Igor van den Hoven 2009                        *
-******************************************************************************/
-
-#include "tintin.h"
-
-
-DO_COMMAND(do_alias)
-{
-	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE];
-
-	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
-	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
-	arg = get_arg_in_braces(ses, arg, arg3, GET_ALL);
-
-	if (*arg3 == 0)
-	{
-		strcpy(arg3, "5");
-	}
-
-	if (*arg1 == 0)
-	{
-		show_list(ses->list[LIST_ALIAS], 0);
-	}
-	else if (*arg2 == 0)
-	{
-		if (show_node_with_wild(ses, arg1, ses->list[LIST_ALIAS]) == FALSE)
-		{
-			show_message(ses, LIST_ALIAS, "#ALIAS: NO MATCH(ES) FOUND FOR {%s}.", arg1);
-		}
-	}
-	else
-	{
-		update_node_list(ses->list[LIST_ALIAS], arg1, arg2, arg3, "");
-
-		show_message(ses, LIST_ALIAS, "#ALIAS {%s} NOW TRIGGERS {%s} @ {%s}.", arg1, arg2, arg3);
-	}
-	return ses;
-}
-
-
-DO_COMMAND(do_unalias)
-{
-	delete_node_with_wild(ses, LIST_ALIAS, arg);
-
-	return ses;
-}
-
-int check_all_aliases(struct session *ses, char *input)
-{
-	struct listnode *node;
-	struct listroot *root;
-	char tmp[BUFFER_SIZE], line[BUFFER_SIZE], *arg;
-	int i;
-
-	root = ses->list[LIST_ALIAS];
-
-	if (HAS_BIT(root->flags, LIST_FLAG_IGNORE))
-	{
-		return FALSE;
-	}
-
-	substitute(ses, input, line, SUB_VAR|SUB_FUN);
-
-	for (root->update = 0 ; root->update < root->used ; root->update++)
-	{
-		if (check_one_regexp(ses, root->list[root->update], line, line, PCRE_ANCHORED))
-		{
-			node = root->list[root->update];
-
-			i = strlen(node->arg1);
-
-			if (!strncmp(node->arg1, line, i))
-			{
-				if (line[i])
-				{
-					if (line[i] != ' ')
-					{
-						continue;
-					}
-					arg = &line[i + 1];
-				}
-				else
-				{
-					arg = &line[i];
-				}
-
-				RESTRING(gtd->vars[0], arg)
-
-				for (i = 1 ; i < 100 ; i++)
-				{
-					arg = get_arg_in_braces(ses, arg, tmp, GET_ONE);
-
-					RESTRING(gtd->vars[i], tmp);
-
-					if (*arg == 0)
-					{
-						while (++i < 100)
-						{
-							if (*gtd->vars[i])
-							{
-								RESTRING(gtd->vars[i], "");
-							}
-						}
-						break;
-					}
-
-				}
-			}
-
-			substitute(ses, node->arg2, tmp, SUB_ARG);
-
-			if (!strncmp(node->arg1, line, strlen(node->arg1)) && !strcmp(node->arg2, tmp) && *gtd->vars[0])
-			{
-				sprintf(input, "%s %s", tmp, gtd->vars[0]);
-			}
-			else
-			{
-				sprintf(input, "%s", tmp);
-			}
-
-			show_debug(ses, LIST_ALIAS, "#DEBUG ALIAS {%s} {%s}", node->arg1, gtd->vars[0]);
-
-			return TRUE;
-		}
-	}
-	return FALSE;
-}

+ 12 - 15
src/buffer.c

@@ -200,11 +200,11 @@ void add_line_buffer(struct session *ses, char *line, int prompt)
 		str_hash_grep(ses->scroll->buffer[ses->scroll->row], TRUE);
 		str_hash_grep(ses->scroll->buffer[ses->scroll->row], TRUE);
 	}
 	}
 
 
-	if (!HAS_BIT(ses->flags, SES_FLAG_LOGLEVEL)) // flag name could be clearer
+	if (!HAS_BIT(ses->logmode, LOG_FLAG_LOW))
 	{
 	{
 		if (ses->logfile)
 		if (ses->logfile)
 		{
 		{
-			logit(ses, linebuf, ses->logfile, TRUE);
+			logit(ses, linebuf, ses->logfile, LOG_FLAG_LINEFEED);
 		}
 		}
 	}
 	}
 
 
@@ -321,7 +321,7 @@ DO_COMMAND(do_grep)
 				continue;
 				continue;
 			}
 			}
 
 
-			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE))
+			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE, SUB_NONE))
 			{
 			{
 				grep_add = str_hash_lines(ses->scroll->buffer[scroll_cnt]);
 				grep_add = str_hash_lines(ses->scroll->buffer[scroll_cnt]);
 
 
@@ -363,7 +363,7 @@ DO_COMMAND(do_grep)
 				continue;
 				continue;
 			}
 			}
 
 
-			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE))
+			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE, SUB_NONE))
 			{
 			{
 				grep_add = str_hash_lines(ses->scroll->buffer[scroll_cnt]);
 				grep_add = str_hash_lines(ses->scroll->buffer[scroll_cnt]);
 
 
@@ -404,7 +404,7 @@ DO_COMMAND(do_grep)
 				continue;
 				continue;
 			}
 			}
 
 
-			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE))
+			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE, SUB_NONE))
 			{
 			{
 				grep_add = str_hash_lines(ses->scroll->buffer[scroll_cnt]);
 				grep_add = str_hash_lines(ses->scroll->buffer[scroll_cnt]);
 
 
@@ -507,7 +507,7 @@ int show_buffer(struct session *ses)
 
 
 	if (ses->scroll->buffer[scroll_cnt] && scroll_cut)
 	if (ses->scroll->buffer[scroll_cnt] && scroll_cut)
 	{
 	{
-		word_wrap_split(ses, ses->scroll->buffer[scroll_cnt], temp, TRUE, scroll_cut, scroll_tmp - ses->scroll->base);
+		word_wrap_split(ses, ses->scroll->buffer[scroll_cnt], temp, ses->wrap, scroll_cut, scroll_tmp - ses->scroll->base);
 
 
 		printf("%s\n", temp);
 		printf("%s\n", temp);
 
 
@@ -550,7 +550,7 @@ int show_buffer(struct session *ses)
 
 
 	if (ses->scroll->buffer[scroll_cnt] && scroll_cut)
 	if (ses->scroll->buffer[scroll_cnt] && scroll_cut)
 	{
 	{
-		word_wrap_split(ses, ses->scroll->buffer[scroll_cnt], temp, TRUE, 0, scroll_cut);
+		word_wrap_split(ses, ses->scroll->buffer[scroll_cnt], temp, ses->wrap, 0, scroll_cut);
 
 
 		printf("%s\n", temp);
 		printf("%s\n", temp);
 
 
@@ -925,7 +925,7 @@ DO_BUFFER(buffer_find)
 				continue;
 				continue;
 			}
 			}
 
 
-			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE))
+			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE, SUB_NONE))
 			{
 			{
 				grep_cnt++;
 				grep_cnt++;
 
 
@@ -962,7 +962,7 @@ DO_BUFFER(buffer_find)
 				continue;
 				continue;
 			}
 			}
 
 
-			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE))
+			if (find(ses, ses->scroll->buffer[scroll_cnt], arg2, SUB_NONE, SUB_NONE))
 			{
 			{
 				grep_cnt--;
 				grep_cnt--;
 
 
@@ -1067,10 +1067,7 @@ DO_BUFFER(buffer_write)
 		{
 		{
 			show_message(ses, LIST_COMMAND, "#OK: WRITING BUFFER TO '%s'.", arg1);
 			show_message(ses, LIST_COMMAND, "#OK: WRITING BUFFER TO '%s'.", arg1);
 
 
-			if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
-			{
-				write_html_header(ses, fp);
-			}
+			loginit(ses, fp, LOG_FLAG_OVERWRITE | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
 
 
 			cnt = ses->scroll->row;
 			cnt = ses->scroll->row;
 
 
@@ -1090,11 +1087,11 @@ DO_BUFFER(buffer_write)
 					continue;
 					continue;
 				}
 				}
 
 
-				if (HAS_BIT(ses->flags, SES_FLAG_LOGPLAIN))
+				if (HAS_BIT(ses->logmode, LOG_FLAG_PLAIN))
 				{
 				{
 					strip_vt102_codes(ses->scroll->buffer[cnt], out);
 					strip_vt102_codes(ses->scroll->buffer[cnt], out);
 				}
 				}
-				else if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+				else if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
 				{
 				{
 					vt102_to_html(ses, ses->scroll->buffer[cnt], out);
 					vt102_to_html(ses, ses->scroll->buffer[cnt], out);
 				}
 				}

+ 3 - 1
src/chat.c

@@ -81,6 +81,8 @@ DO_COMMAND(do_chat)
 		arg = sub_arg_in_braces(ses, arg, arg1,  chat_table[cnt].lval, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg1,  chat_table[cnt].lval, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, chat_table[cnt].rval, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, chat_table[cnt].rval, SUB_VAR|SUB_FUN);
 
 
+		chat_table[cnt].fun(arg1, arg2);
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -2197,7 +2199,7 @@ DO_CHAT(chat_cancelfile)
 
 
 DO_CHAT(chat_color)
 DO_CHAT(chat_color)
 {
 {
-	if (*arg1 == 0 || get_highlight_codes(gtd->ses, arg1, arg2) == FALSE)
+	if (*arg1 == 0 || get_color_names(gtd->ses, arg1, arg2) == FALSE)
 	{
 	{
 		chat_printf("Valid colors are:\n\nreset, bold, dim, light, dark, underscore, blink, reverse, black, red, green, yellow, blue, magenta, cyan, white, b black, b red, b green, b yellow, b blue, b magenta, b cyan, b white");
 		chat_printf("Valid colors are:\n\nreset, bold, dim, light, dark, underscore, blink, reverse, black, red, green, yellow, blue, magenta, cyan, white, b black, b red, b green, b yellow, b blue, b magenta, b cyan, b white");
 
 

+ 8 - 1
src/class.c

@@ -75,6 +75,8 @@ DO_COMMAND(do_class)
 		{
 		{
 			if (!search_node_list(ses->list[LIST_CLASS], arg1))
 			if (!search_node_list(ses->list[LIST_CLASS], arg1))
 			{
 			{
+				check_all_events(ses, SUB_ARG, 0, 1, "CLASS CREATED", arg1);
+
 				update_node_list(ses->list[LIST_CLASS], arg1, arg2, arg3, "");
 				update_node_list(ses->list[LIST_CLASS], arg1, arg2, arg3, "");
 			}
 			}
 			class_table[i].group(ses, arg1, arg3);
 			class_table[i].group(ses, arg1, arg3);
@@ -285,8 +287,11 @@ DO_CLASS(class_kill)
 
 
 	if (!search_node_list(ses->list[LIST_CLASS], arg1))
 	if (!search_node_list(ses->list[LIST_CLASS], arg1))
 	{
 	{
-		update_node_list(ses->list[LIST_CLASS], arg1, "", "0", "");
+		show_error(ses, LIST_CLASS, "#CLASS {%s} DOES NOT EXIST.", arg1);
+
+		return ses;
 	}
 	}
+
 	group = search_index_list(ses->list[LIST_CLASS], arg1, NULL);
 	group = search_index_list(ses->list[LIST_CLASS], arg1, NULL);
 
 
 	for (type = 0 ; type < LIST_MAX ; type++)
 	for (type = 0 ; type < LIST_MAX ; type++)
@@ -305,6 +310,8 @@ DO_CLASS(class_kill)
 		}
 		}
 	}
 	}
 
 
+	check_all_events(ses, SUB_ARG, 0, 1, "CLASS DESTROYED", arg1);
+
 	delete_index_list(ses->list[LIST_CLASS], group);
 	delete_index_list(ses->list[LIST_CLASS], group);
 
 
 	show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN KILLED.", arg1);
 	show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN KILLED.", arg1);

+ 54 - 12
src/config.c

@@ -203,18 +203,29 @@ DO_CONFIG(config_wordwrap)
 {
 {
 	if (!strcasecmp(arg, "ON"))
 	if (!strcasecmp(arg, "ON"))
 	{
 	{
-		SET_BIT(ses->flags, SES_FLAG_WORDWRAP);
+		ses->wrap = -1;
 	}
 	}
 	else if (!strcasecmp(arg, "OFF"))
 	else if (!strcasecmp(arg, "OFF"))
 	{
 	{
-		DEL_BIT(ses->flags, SES_FLAG_WORDWRAP);
+		ses->wrap = 0;
+	}
+	else if (is_number(arg))
+	{
+		if (atoi(arg) < 1 || atoi(arg) > 10000)
+		{
+			show_error(ses, LIST_CONFIG, "#ERROR: #CONFIG BUFFER: PROVIDE A NUMBER BETWEEN 1 and 10000");
+
+			return NULL;
+		}
+		ses->wrap = atoi(arg);
 	}
 	}
 	else
 	else
 	{
 	{
-		show_error(ses, LIST_CONFIG, "#SYNTAX: #CONFIG {%s} <ON|OFF>", config_table[index].name);
+		show_error(ses, LIST_CONFIG, "#SYNTAX: #CONFIG {%s} <ON|OFF|NUMBER>", config_table[index].name);
 
 
 		return NULL;
 		return NULL;
 	}
 	}
+
 	update_node_list(ses->list[LIST_CONFIG], config_table[index].name, capitalize(arg), "", "");
 	update_node_list(ses->list[LIST_CONFIG], config_table[index].name, capitalize(arg), "", "");
 
 
 	SET_BIT(gtd->flags, TINTIN_FLAG_RESETBUFFER);
 	SET_BIT(gtd->flags, TINTIN_FLAG_RESETBUFFER);
@@ -222,22 +233,25 @@ DO_CONFIG(config_wordwrap)
 	return ses;
 	return ses;
 }
 }
 
 
-DO_CONFIG(config_log)
+DO_CONFIG(config_logmode)
 {
 {
 	if (!strcasecmp(arg, "HTML"))
 	if (!strcasecmp(arg, "HTML"))
 	{
 	{
-		DEL_BIT(ses->flags, SES_FLAG_LOGPLAIN);
-		SET_BIT(ses->flags, SES_FLAG_LOGHTML);
+		SET_BIT(ses->logmode, LOG_FLAG_HTML);
+		DEL_BIT(ses->logmode, LOG_FLAG_PLAIN);
+		DEL_BIT(ses->logmode, LOG_FLAG_RAW);
 	}
 	}
 	else if (!strcasecmp(arg, "PLAIN"))
 	else if (!strcasecmp(arg, "PLAIN"))
 	{
 	{
-		SET_BIT(ses->flags, SES_FLAG_LOGPLAIN);
-		DEL_BIT(ses->flags, SES_FLAG_LOGHTML);
+		DEL_BIT(ses->logmode, LOG_FLAG_HTML);
+		SET_BIT(ses->logmode, LOG_FLAG_PLAIN);
+		DEL_BIT(ses->logmode, LOG_FLAG_RAW);
 	}
 	}
 	else if (!strcasecmp(arg, "RAW"))
 	else if (!strcasecmp(arg, "RAW"))
 	{
 	{
-		DEL_BIT(ses->flags, SES_FLAG_LOGPLAIN);
-		DEL_BIT(ses->flags, SES_FLAG_LOGHTML);
+		DEL_BIT(ses->logmode, LOG_FLAG_HTML);
+		DEL_BIT(ses->logmode, LOG_FLAG_PLAIN);
+		SET_BIT(ses->logmode, LOG_FLAG_RAW);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -416,6 +430,34 @@ DO_CONFIG(config_debugtelnet)
 	return ses;
 	return ses;
 }
 }
 
 
+DO_CONFIG(config_telnet)
+{
+	if (!strcasecmp(arg, "ON"))
+	{
+		DEL_BIT(ses->telopts, TELOPT_FLAG_DEBUG);
+		SET_BIT(ses->flags, SES_FLAG_TELNET);
+	}
+	else if (!strcasecmp(arg, "OFF"))
+	{
+		DEL_BIT(ses->telopts, TELOPT_FLAG_DEBUG);
+		DEL_BIT(ses->flags, SES_FLAG_TELNET);
+	}
+	else if (!strcasecmp(arg, "DEBUG"))
+	{
+		SET_BIT(ses->telopts, TELOPT_FLAG_DEBUG);
+		SET_BIT(ses->flags, SES_FLAG_TELNET);
+	}
+	else
+	{
+		show_error(ses, LIST_CONFIG, "#SYNTAX: #CONFIG {%s} <ON|OFF|DEBUG>", config_table[index].name);
+
+		return NULL;
+	}
+	update_node_list(ses->list[LIST_CONFIG], config_table[index].name, capitalize(arg), "", "");
+
+	return ses;
+}
+
 DO_CONFIG(config_convertmeta)
 DO_CONFIG(config_convertmeta)
 {
 {
 	if (!strcasecmp(arg, "ON"))
 	if (!strcasecmp(arg, "ON"))
@@ -441,11 +483,11 @@ DO_CONFIG(config_loglevel)
 {
 {
 	if (!strcasecmp(arg, "LOW"))
 	if (!strcasecmp(arg, "LOW"))
 	{
 	{
-		SET_BIT(ses->flags, SES_FLAG_LOGLEVEL);
+		SET_BIT(ses->logmode, LOG_FLAG_LOW);
 	}
 	}
 	else if (!strcasecmp(arg, "HIGH"))
 	else if (!strcasecmp(arg, "HIGH"))
 	{
 	{
-		DEL_BIT(ses->flags, SES_FLAG_LOGLEVEL);
+		DEL_BIT(ses->logmode, LOG_FLAG_LOW);
 	}
 	}
 	else
 	else
 	{
 	{

+ 10 - 3
src/cursor.c

@@ -694,7 +694,7 @@ DO_CURSOR(cursor_history_next)
 
 
 		for (root->update++ ; root->update < root->used ; root->update++)
 		for (root->update++ ; root->update < root->used ; root->update++)
 		{
 		{
-			if (*gtd->input_buf && find(ses, root->list[root->update]->arg1, gtd->input_buf, SUB_NONE))
+			if (*gtd->input_buf && find(ses, root->list[root->update]->arg1, gtd->input_buf, SUB_NONE, SUB_NONE))
 			{
 			{
 				break;
 				break;
 			}
 			}
@@ -758,7 +758,7 @@ DO_CURSOR(cursor_history_prev)
 
 
 		for (root->update-- ; root->update >= 0 ; root->update--)
 		for (root->update-- ; root->update >= 0 ; root->update--)
 		{
 		{
-			if (*gtd->input_buf && find(ses, root->list[root->update]->arg1, gtd->input_buf, SUB_NONE))
+			if (*gtd->input_buf && find(ses, root->list[root->update]->arg1, gtd->input_buf, SUB_NONE, SUB_NONE))
 			{
 			{
 				break;
 				break;
 			}
 			}
@@ -877,14 +877,18 @@ DO_CURSOR(cursor_history_find)
 		}
 		}
 	}
 	}
 
 
+	gtd->quiet_level++;
+
 	for (root->update = root->used - 1 ; root->update >= 0 ; root->update--)
 	for (root->update = root->used - 1 ; root->update >= 0 ; root->update--)
 	{
 	{
-		if (*gtd->input_buf && find(ses, root->list[root->update]->arg1, gtd->input_buf, SUB_NONE))
+		if (*gtd->input_buf && find(ses, root->list[root->update]->arg1, gtd->input_buf, SUB_NONE, SUB_NONE))
 		{
 		{
 			break;
 			break;
 		}
 		}
 	}
 	}
 
 
+	gtd->quiet_level--;
+
 	if (root->update >= 0)
 	if (root->update >= 0)
 	{
 	{
 		input_printf("\e[%dG ]  %.*s\e[%dG", gtd->input_off + inputline_cur_str_len(), gtd->input_off + inputline_max_str_len() - inputline_cur_str_len() - 4, root->list[root->update]->arg1, gtd->input_off + gtd->input_pos - gtd->input_hid);
 		input_printf("\e[%dG ]  %.*s\e[%dG", gtd->input_off + inputline_cur_str_len(), gtd->input_off + inputline_max_str_len() - inputline_cur_str_len() - 4, root->list[root->update]->arg1, gtd->input_off + gtd->input_pos - gtd->input_hid);
@@ -1066,11 +1070,14 @@ DO_CURSOR(cursor_redraw_input)
 	}
 	}
 	else
 	else
 	{
 	{
+//		cursor_redraw_line(ses, "");
+
 		input_printf("\e[1G\e[0K%s%s\e[0K", ses->more_output, gtd->input_buf);
 		input_printf("\e[1G\e[0K%s%s\e[0K", ses->more_output, gtd->input_buf);
 
 
 		gtd->input_cur = gtd->input_len;
 		gtd->input_cur = gtd->input_len;
 
 
 		gtd->input_pos = gtd->input_len % gtd->screen->cols;
 		gtd->input_pos = gtd->input_len % gtd->screen->cols;
+
 	}
 	}
 }
 }
 
 

+ 39 - 14
src/data.c

@@ -121,6 +121,11 @@ struct listnode *insert_node_list(struct listroot *root, char *arg1, char *arg2,
 
 
 	node = (struct listnode *) calloc(1, sizeof(struct listnode));
 	node = (struct listnode *) calloc(1, sizeof(struct listnode));
 
 
+	if (HAS_BIT(root->flags, LIST_FLAG_PRIORITY) && *arg3 == 0)
+	{
+		strcpy(arg3, "5");
+	}
+
 	node->arg1 = strdup(arg1);
 	node->arg1 = strdup(arg1);
 	node->arg2 = strdup(arg2);
 	node->arg2 = strdup(arg2);
 	node->arg3 = strdup(arg3);
 	node->arg3 = strdup(arg3);
@@ -179,6 +184,11 @@ struct listnode *update_node_list(struct listroot *root, char *arg1, char *arg2,
 				break;
 				break;
 		}
 		}
 
 
+		if (HAS_BIT(root->flags, LIST_FLAG_PRIORITY) && *arg3 == 0)
+		{
+			strcpy(arg3, "5");
+		}
+
 		switch (list_table[root->type].mode)
 		switch (list_table[root->type].mode)
 		{
 		{
 			case SORT_PRIORITY:
 			case SORT_PRIORITY:
@@ -495,26 +505,33 @@ int nsearch_list(struct listroot *root, char *text)
 
 
 void show_node(struct listroot *root, struct listnode *node, int level)
 void show_node(struct listroot *root, struct listnode *node, int level)
 {
 {
-	char *str = str_dup("");
+	char *str_arg2 = str_dup("");
 
 
-	show_nest_node(node, &str, TRUE);
+	show_nest_node(node, &str_arg2, TRUE);
 
 
 	switch (list_table[root->type].args)
 	switch (list_table[root->type].args)
 	{
 	{
 		case 4:
 		case 4:
-			tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str, node->arg3, node->arg4);
+			tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str_arg2, node->arg3, node->arg4);
 			break;
 			break;
 		case 3:
 		case 3:
-			tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str, node->arg3);
+			if (HAS_BIT(list_table[root->type].flags, LIST_FLAG_PRIORITY) && !strcmp(node->arg3, "5"))
+			{
+				tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str_arg2);
+			}
+			else
+			{
+				tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str_arg2, node->arg3);
+			}
 			break;
 			break;
 		case 2:
 		case 2:
-			tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str);
+			tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1, str_arg2);
 			break;
 			break;
 		case 1:
 		case 1:
 			tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1);
 			tintin_printf2(root->ses, "%s" COLOR_TINTIN "#" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", indent(level), list_table[root->type].name, node->arg1);
 			break;
 			break;
 	}
 	}
-	str_free(str);
+	str_free(str_arg2);
 }
 }
 
 
 /*
 /*
@@ -554,16 +571,24 @@ int show_node_with_wild(struct session *ses, char *text, struct listroot *root)
 			case LIST_FUNCTION:
 			case LIST_FUNCTION:
 			case LIST_MACRO:
 			case LIST_MACRO:
 				tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2));
 				tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2));
-//				show_lines(ses, SUB_COL, "<138>%c<168>%s <258>{<278>%s<258>}\n<158>{\n<278>%s\n<258>}<088>\n\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2));
 				break;
 				break;
 
 
 			case LIST_ACTION:
 			case LIST_ACTION:
 			case LIST_ALIAS:
 			case LIST_ALIAS:
+			case LIST_BUTTON:
+				if (!strcmp(node->arg3, "5"))
+				{
+					tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2));
+				}
+				else
+				{
+					tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n{" COLOR_STRING "%s" COLOR_BRACE "}\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2), node->arg3);
+				}
+				break;
+
 			case LIST_DELAY:
 			case LIST_DELAY:
 			case LIST_TICKER:
 			case LIST_TICKER:
-			case LIST_SUBSTITUTE:
 				tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n{" COLOR_STRING "%s" COLOR_BRACE "}\n\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2), node->arg3);
 				tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s\n" COLOR_BRACE "}\n{" COLOR_STRING "%s" COLOR_BRACE "}\n\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2), node->arg3);
-//				show_lines(ses, SUB_COL, "<138>%c<168>%s <258>{<278>%s<258>}\n<258>{\n<278>%s\n<258>}\n<258>{<278>%s<258>}<088>\n\n", gtd->tintin_char, list_table[root->type].name, node->arg1, script_viewer(ses, node->arg2), node->arg3);
 				break;
 				break;
 
 
 			default:
 			default:
@@ -998,7 +1023,7 @@ DO_COMMAND(do_info)
 
 
 					add_nest_node(ses->list[LIST_VARIABLE], name, "{CLIENT}{{NAME}{%s}{VERSION}{%-3s}}", CLIENT_NAME, CLIENT_VERSION);
 					add_nest_node(ses->list[LIST_VARIABLE], name, "{CLIENT}{{NAME}{%s}{VERSION}{%-3s}}", CLIENT_NAME, CLIENT_VERSION);
 
 
-					add_nest_node(ses->list[LIST_VARIABLE], name, "{SCROLL}{{BASE}{%d}{LINE}{%d}{MAX}{%d}{ROW}{%d}}", ses->scroll->base, ses->scroll->line, ses->scroll->max, ses->scroll->row);
+					add_nest_node(ses->list[LIST_VARIABLE], name, "{HOME}{%s}{LANG}{%s}{OS}{%s}{TERM}{%s}", gtd->home, gtd->lang, gtd->os, gtd->term);
 
 
 					show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SYSTEM]}");
 					show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SYSTEM]}");
 				}
 				}
@@ -1006,10 +1031,10 @@ DO_COMMAND(do_info)
 				{
 				{
 					tintin_printf2(ses, "#INFO SYSTEM: CLIENT_NAME = %s", CLIENT_NAME);
 					tintin_printf2(ses, "#INFO SYSTEM: CLIENT_NAME = %s", CLIENT_NAME);
 					tintin_printf2(ses, "#INFO SYSTEM: CLIENT_VERSION = %s", CLIENT_VERSION);
 					tintin_printf2(ses, "#INFO SYSTEM: CLIENT_VERSION = %s", CLIENT_VERSION);
-					tintin_printf2(ses, "#INFO SYSTEM: SCROLL_BASE = %d", ses->scroll->base);
-					tintin_printf2(ses, "#INFO SYSTEM: SCROLL_LINE = %d", ses->scroll->line);
-					tintin_printf2(ses, "#INFO SYSTEM: SCROLL_MAX = %d", ses->scroll->max);
-					tintin_printf2(ses, "#INFO SYSTEM: SCROLL_ROW = %d", ses->scroll->row);
+					tintin_printf2(ses, "#INFO SYSTEM: HOME = %s", gtd->home);
+					tintin_printf2(ses, "#INFO SYSTEM: LANG = %s", gtd->lang);
+					tintin_printf2(ses, "#INFO SYSTEM: OS = %s", gtd->os);
+					tintin_printf2(ses, "#INFO SYSTEM: TERM = %s", gtd->term);
 				}
 				}
 			}
 			}
 			else
 			else

+ 10 - 0
src/debug.c

@@ -90,6 +90,16 @@ void dump_stack(void)
 	}
 	}
 }
 }
 
 
+void dump_stack_fatal(void)
+{
+	unsigned char i;
+
+	for (i = 0 ; i < debug_index && i < MAX_STACK_SIZE ; i++)
+	{
+		printf("\e[1;32mDEBUG_STACK[\e[1;31m%03d\e[1;32m] = \e[1;31m%s\e[0m\n", i, debug_stack[i]);
+	}
+}
+
 void dump_full_stack(void)
 void dump_full_stack(void)
 {
 {
 	unsigned char i;
 	unsigned char i;

+ 10 - 0
src/event.c

@@ -282,6 +282,8 @@ void mouse_handler(struct session *ses, int flags, int row, int col, char type)
 		}
 		}
 	}
 	}
 
 
+	check_all_buttons(ses, row, col, arg1, arg2, word, line);
+
 	check_all_events(ses, SUB_ARG, 2, 6, "%s %s", arg1, arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 	check_all_events(ses, SUB_ARG, 2, 6, "%s %s", arg1, arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 
 
 	check_all_events(ses, SUB_ARG, 3, 6, "%s %s %d", arg1, arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 	check_all_events(ses, SUB_ARG, 3, 6, "%s %s %d", arg1, arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
@@ -304,6 +306,8 @@ void mouse_handler(struct session *ses, int flags, int row, int col, char type)
 			{
 			{
 				if (click[0] - click[2] < 500000)
 				if (click[0] - click[2] < 500000)
 				{
 				{
+					check_all_buttons(ses, row, col, "TRIPLE-CLICKED", arg2, word, line);
+
 					check_all_events(ses, SUB_ARG, 1, 6, "TRIPLE-CLICKED %s", arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 					check_all_events(ses, SUB_ARG, 1, 6, "TRIPLE-CLICKED %s", arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 
 
 					check_all_events(ses, SUB_ARG, 2, 6, "TRIPLE-CLICKED %s %d", arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 					check_all_events(ses, SUB_ARG, 2, 6, "TRIPLE-CLICKED %s %d", arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
@@ -316,6 +320,8 @@ void mouse_handler(struct session *ses, int flags, int row, int col, char type)
 				}
 				}
 				else
 				else
 				{
 				{
+					check_all_buttons(ses, row, col, "DOUBLE-CLICKED", arg2, word, line);
+
 					check_all_events(ses, SUB_ARG, 1, 6, "DOUBLE-CLICKED %s", arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 					check_all_events(ses, SUB_ARG, 1, 6, "DOUBLE-CLICKED %s", arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 
 
 					check_all_events(ses, SUB_ARG, 2, 6, "DOUBLE-CLICKED %s %d", arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 					check_all_events(ses, SUB_ARG, 2, 6, "DOUBLE-CLICKED %s %d", arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
@@ -339,6 +345,8 @@ void mouse_handler(struct session *ses, int flags, int row, int col, char type)
 	{
 	{
 		if (utime() - click[0] >= 500000)
 		if (utime() - click[0] >= 500000)
 		{
 		{
+			check_all_buttons(ses, row, col, "LONG-CLICKED", arg2, word, line);
+
 			check_all_events(ses, SUB_ARG, 1, 6, "LONG-CLICKED %s", arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 			check_all_events(ses, SUB_ARG, 1, 6, "LONG-CLICKED %s", arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 
 
 			check_all_events(ses, SUB_ARG, 2, 6, "LONG-CLICKED %s %d", arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 			check_all_events(ses, SUB_ARG, 2, 6, "LONG-CLICKED %s %d", arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
@@ -349,6 +357,8 @@ void mouse_handler(struct session *ses, int flags, int row, int col, char type)
 		}
 		}
 		else if (click[0] - click[1] >= 500000)
 		else if (click[0] - click[1] >= 500000)
 		{
 		{
+			check_all_buttons(ses, row, col, "SHORT-CLICKED", arg2, word, line);
+
 			check_all_events(ses, SUB_ARG, 1, 6, "SHORT-CLICKED %s", arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 			check_all_events(ses, SUB_ARG, 1, 6, "SHORT-CLICKED %s", arg2, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 
 
 			check_all_events(ses, SUB_ARG, 2, 6, "SHORT-CLICKED %s %d", arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);
 			check_all_events(ses, SUB_ARG, 2, 6, "SHORT-CLICKED %s %d", arg2, row, ntos(row), ntos(col), ntos(-1 - (gtd->screen->rows - row)), ntos(-1 - (gtd->screen->cols - col)), word, line);

+ 21 - 5
src/files.c

@@ -287,7 +287,7 @@ DO_COMMAND(do_read)
 
 
 	sprintf(temp, "{TINTIN CHAR} {%c}", bufo[0]);
 	sprintf(temp, "{TINTIN CHAR} {%c}", bufo[0]);
 
 
-	gtd->quiet++;
+	gtd->quiet_level++;
 
 
 	do_configure(ses, temp);
 	do_configure(ses, temp);
 
 
@@ -306,7 +306,7 @@ DO_COMMAND(do_read)
 
 
 		if (strlen(bufi) >= BUFFER_SIZE)
 		if (strlen(bufi) >= BUFFER_SIZE)
 		{
 		{
-/*			gtd->quiet--;
+/*			gtd->quiet_level--;
 
 
 			bufi[20] = 0;
 			bufi[20] = 0;
 */
 */
@@ -329,7 +329,7 @@ DO_COMMAND(do_read)
 		pti++;
 		pti++;
 	}
 	}
 
 
-	gtd->quiet--;
+	gtd->quiet_level--;
 
 
 	if (!HAS_BIT(ses->flags, SES_FLAG_VERBOSE))
 	if (!HAS_BIT(ses->flags, SES_FLAG_VERBOSE))
 	{
 	{
@@ -367,7 +367,7 @@ DO_COMMAND(do_write)
 	FILE *file;
 	FILE *file;
 	char filename[BUFFER_SIZE], forceful[BUFFER_SIZE];
 	char filename[BUFFER_SIZE], forceful[BUFFER_SIZE];
 	struct listroot *root;
 	struct listroot *root;
-	int i, j, cnt = 0;
+	int i, j, fix, cnt = 0;
 
 
 	arg = get_arg_in_braces(ses, arg, filename, GET_ONE);
 	arg = get_arg_in_braces(ses, arg, filename, GET_ONE);
 	arg = get_arg_in_braces(ses, arg, forceful, GET_ONE);
 	arg = get_arg_in_braces(ses, arg, forceful, GET_ONE);
@@ -402,6 +402,8 @@ DO_COMMAND(do_write)
 			continue;
 			continue;
 		}
 		}
 
 
+		fix = 0;
+
 		for (j = 0 ; j < root->used ; j++)
 		for (j = 0 ; j < root->used ; j++)
 		{
 		{
 			if (*root->list[j]->group == 0)
 			if (*root->list[j]->group == 0)
@@ -409,8 +411,14 @@ DO_COMMAND(do_write)
 				write_node(ses, i, root->list[j], file);
 				write_node(ses, i, root->list[j], file);
 
 
 				cnt++;
 				cnt++;
+				fix++;
 			}
 			}
 		}
 		}
+
+		if (fix)
+		{
+			fputs("\n", file);
+		}
 	}
 	}
 
 
 	fclose(file);
 	fclose(file);
@@ -440,7 +448,15 @@ void write_node(struct session *ses, int list, struct listnode *node, FILE *file
 
 
 		case LIST_ACTION:
 		case LIST_ACTION:
 		case LIST_ALIAS:
 		case LIST_ALIAS:
-			asprintf(&result, "%c%s {%s}\n{\n%s\n}\n{%s}\n\n", gtd->tintin_char, list_table[list].name, node->arg1, script_writer(ses, node->arg2), node->arg3);
+		case LIST_BUTTON:
+			if (!strcmp(node->arg3, "5"))
+			{
+				asprintf(&result, "%c%s {%s}\n{\n%s\n}\n\n", gtd->tintin_char, list_table[list].name, node->arg1, script_writer(ses, node->arg2));
+			}
+			else
+			{
+				asprintf(&result, "%c%s {%s}\n{\n%s\n}\n{%s}\n\n", gtd->tintin_char, list_table[list].name, node->arg1, script_writer(ses, node->arg2), node->arg3);
+			}
 			break;
 			break;
 
 
 		case LIST_VARIABLE:
 		case LIST_VARIABLE:

+ 0 - 72
src/gag.c

@@ -1,72 +0,0 @@
-/******************************************************************************
-*   This file is part of TinTin++                                             *
-*                                                                             *
-*   Copyright 2004-2019 Igor van den Hoven                                    *
-*                                                                             *
-*   TinTin++ is free software; you can redistribute it and/or modify          *
-*   it under the terms of the GNU General Public License as published by      *
-*   the Free Software Foundation; either version 3 of the License, or         *
-*   (at your option) any later version.                                       *
-*                                                                             *
-*   This program is distributed in the hope that it will be useful,           *
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
-*   GNU General Public License for more details.                              *
-*                                                                             *
-*                                                                             *
-*   You should have received a copy of the GNU General Public License         *
-*   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
-******************************************************************************/
-
-/******************************************************************************
-*                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
-*                                                                             *
-*                       coded by Igor van den Hoven 2007                      *
-******************************************************************************/
-
-
-#include "tintin.h"
-
-DO_COMMAND(do_gag)
-{
-	char arg1[BUFFER_SIZE];
-
-	arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
-
-	if (*arg1 == 0)
-	{
-		show_list(ses->list[LIST_GAG], 0);
-	}
-	else
-	{
-		update_node_list(ses->list[LIST_GAG], arg1, "", "", "");
-
-		show_message(ses, LIST_GAG, "#OK. {%s} IS NOW GAGGED.", arg1);
-	}
-	return ses;
-}
-
-
-DO_COMMAND(do_ungag)
-{
-	delete_node_with_wild(ses, LIST_GAG, arg);
-
-	return ses;
-}
-
-void check_all_gags(struct session *ses, char *original, char *line)
-{
-	struct listroot *root = ses->list[LIST_GAG];
-
-	for (root->update = 0 ; root->update < root->used ; root->update++)
-	{
-		if (check_one_regexp(ses, root->list[root->update], line, original, 0))
-		{
-			show_debug(ses, LIST_GAG, "#DEBUG GAG {%s}", root->list[root->update]->arg1);
-
-			SET_BIT(ses->flags, SES_FLAG_GAG);
-
-			return;
-		}
-	}
-}

+ 109 - 20
src/help.c

@@ -41,6 +41,8 @@ char *help_related(struct session *ses, int index, int html)
 	char tmp[BUFFER_SIZE], link[BUFFER_SIZE];
 	char tmp[BUFFER_SIZE], link[BUFFER_SIZE];
 	static char buf[BUFFER_SIZE];
 	static char buf[BUFFER_SIZE];
 
 
+	push_call("help_related(%p,%d,%d)",ses,index,html);
+
 	arg = help_table[index].also;
 	arg = help_table[index].also;
 
 
 	buf[0] = 0;
 	buf[0] = 0;
@@ -67,10 +69,11 @@ char *help_related(struct session *ses, int index, int html)
 			}
 			}
 			else
 			else
 			{
 			{
-				cat_sprintf(buf, " and %s.");
+				cat_sprintf(buf, " and %s.", tmp);
 			}
 			}
 		}
 		}
 	}
 	}
+	pop_call();
 	return buf;
 	return buf;
 }
 }
 
 
@@ -89,7 +92,7 @@ DO_COMMAND(do_help)
 		{
 		{
 			if (strlen(buf) + 19 > gtd->screen->cols)
 			if (strlen(buf) + 19 > gtd->screen->cols)
 			{
 			{
-				show_lines(ses, SUB_COL, "<088>%s<088>\n", buf);
+				print_lines(ses, SUB_COL, "<088>%s<088>\n", buf);
 
 
 				*buf = 0;
 				*buf = 0;
 			}
 			}
@@ -98,7 +101,7 @@ DO_COMMAND(do_help)
 
 
 		if (*buf)
 		if (*buf)
 		{
 		{
-			show_lines(ses, SUB_COL, "<088>%s<088>\n", buf);
+			print_lines(ses, SUB_COL, "<088>%s<088>\n", buf);
 		}
 		}
 	}
 	}
 	else if (!strcasecmp(arg1, "dump"))
 	else if (!strcasecmp(arg1, "dump"))
@@ -107,7 +110,7 @@ DO_COMMAND(do_help)
 
 
 		do_configure(ses, "{log} {html}");
 		do_configure(ses, "{log} {html}");
 
 
-		if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+		if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
 		{
 		{
 			write_html_header(ses, logfile);
 			write_html_header(ses, logfile);
 		}
 		}
@@ -213,11 +216,11 @@ DO_COMMAND(do_help)
 		{
 		{
 			if (is_abbrev(arg1, help_table[cnt].name))
 			if (is_abbrev(arg1, help_table[cnt].name))
 			{
 			{
-				show_lines(ses, SUB_COL, "%s<088>\n", help_table[cnt].text);
+				print_lines(ses, SUB_COL, "%s<088>\n", help_table[cnt].text);
 				
 				
 				if (*help_table[cnt].also)
 				if (*help_table[cnt].also)
 				{
 				{
-					show_lines(ses, SUB_COL, "%s<088>\n\n", help_related(ses, cnt, 0));
+					print_lines(ses, SUB_COL, "%s<088>\n\n", help_related(ses, cnt, 0));
 				}
 				}
 				return ses;
 				return ses;
 			}
 			}
@@ -228,11 +231,11 @@ DO_COMMAND(do_help)
 		{
 		{
 			if (match(ses, help_table[cnt].name, arg1, SUB_VAR|SUB_FUN))
 			if (match(ses, help_table[cnt].name, arg1, SUB_VAR|SUB_FUN))
 			{
 			{
-				show_lines(ses, SUB_COL, "%s<088>\n", help_table[cnt].text);
+				print_lines(ses, SUB_COL, "%s<088>\n", help_table[cnt].text);
 
 
 				if (*help_table[cnt].also)
 				if (*help_table[cnt].also)
 				{
 				{
-					show_lines(ses, SUB_COL, "%s<088>\n\n", help_related(ses, cnt, 0));
+					print_lines(ses, SUB_COL, "%s<088>\n\n", help_related(ses, cnt, 0));
 				}
 				}
 				found = TRUE;
 				found = TRUE;
 			}
 			}
@@ -455,6 +458,47 @@ struct help_type help_table[] =
 
 
 		"echo grep macro showme screen"
 		"echo grep macro showme screen"
 	},
 	},
+	{
+		"BUTTON",
+
+		"<178>Command<278>: #button <178>{<278>square<178>} {<278>commands<178>} {<278>priority<178>}<278>\n"
+		"\n"
+		"         The #button command can be used to respond with one or several\n"
+		"         commands to a mouse click received within the specified square.\n"
+		"         The click coordinates are stored in %0-%3 and can be used in the\n"
+		"         command part of the button.\n"
+		"\n"
+		"         The square part should exists of two coordinates defining the\n"
+		"         upper left and bottom right corner using row, col, row, col syntax.\n"
+		"         The square arguments should be separated by spaces, semi-colons or\n"
+		"         braces.\n"
+		"\n"
+		"         By default the button is set to respond to a mouse button press, to\n"
+		"         respond to other button presses you must add a 5th argument to the\n"
+		"         square that defines the button press type. You can enable #info\n"
+		"         button on to see button events and their type as they happen.\n"
+		"\n"
+		"         The priority part is optional and determines the priority of the\n"
+		"         button, it defaults to 5.\n"
+		"\n"
+		"         You must enable #config {mouse tracking} on for buttons to work.\n"
+		"\n"
+		"         This command draws no visible button, you'll have to do so separately\n"
+		"         if needed.\n"
+		"\n"
+		"<178>Example<278>: #button {1;1;2;2} {#showme You clicked the upper left corner.}\n"
+		"\n"
+		"         Buttons are ordered alphabetically and only one button can trigger at\n"
+		"         a time. To change the order you can assign a priority, which defaults\n"
+		"         to 5, with a lower number indicating a higher priority. The priority\n"
+		"         can be a floating point number.\n"
+		"\n"
+		"<178>Comment<278>: To see button clicks trigger use #info button on.\n"
+		"\n"
+		"<178>Comment<278>: You can remove a button with the #unbutton command.\n",
+
+		"delay event ticker"
+	},
 	{
 	{
 		"CASE",
 		"CASE",
 
 
@@ -764,6 +808,33 @@ struct help_type help_table[] =
 		
 		
 		"event ticker"
 		"event ticker"
 	},
 	},
+	{
+		"DRAW",
+		
+		"<178>Command<278>: #draw <178>{<278>option<178>} {<278>square<178>} {<278>argument<178>}\n"
+		"<278>\n"
+		"         The draw commands allows you to draw various lines and shapes on the\n"
+		"         screen. Available options and a brief description are provided when\n"
+		"         you type #draw without an argument.\n"
+		"\n"
+		"         The square argument should exists of two coordinates defining the\n"
+		"         upper left and bottom right corner using row, col, row, col syntax.\n"
+		"\n"
+		"         You can prefix the option as following:\n"
+		"\n"
+		"         PRUNED  will prune the corners of any drawn shape.\n"
+		"         ROUNDED will round the corners.\n"
+		"         CROSSED will cross the corners.\n"
+		"\n"
+		"         Some draw options take an additional argument, most notably the\n"
+		"         BOX TEXT option which allows you to place the given text inside\n"
+		"         the drawn box.\n"
+		"\n"
+		"<178>Example<278>: #draw {box text} 1 1 3 20 {Hello world!}\n",
+
+		"buffer echo grep showme"
+	},
+
 	{
 	{
 		"ECHO",
 		"ECHO",
 
 
@@ -904,7 +975,7 @@ struct help_type help_table[] =
 		"         SCAN CSV LINE         %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
 		"         SCAN CSV LINE         %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
 		"         SCAN TSV HEADER       %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
 		"         SCAN TSV HEADER       %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
 		"         SCAN TSV LINE         %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
 		"         SCAN TSV LINE         %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
-		"         SCREEN RESIZE         %0 rows %1 cols\n"
+		"         SCREEN RESIZE         %0 rows %1 cols %1 height %2 width\n"
 		"         SCROLLED <VAR>        %0 row %1 col %2 -row %3 -col %4 word %5 line\n"
 		"         SCROLLED <VAR>        %0 row %1 col %2 -row %3 -col %4 word %5 line\n"
 		"         SECOND                %6 second\n"
 		"         SECOND                %6 second\n"
 		"         SEND OUTPUT           %0 raw text %1 size\n"
 		"         SEND OUTPUT           %0 raw text %1 size\n"
@@ -921,17 +992,20 @@ struct help_type help_table[] =
 		"         TRIPLE-CLICKED <VAR>  %0 row %1 col %2 -row %3 -col %4 word %5 line\n"
 		"         TRIPLE-CLICKED <VAR>  %0 row %1 col %2 -row %3 -col %4 word %5 line\n"
 		"         UNKNOWN COMMAND       %0 raw text\n"
 		"         UNKNOWN COMMAND       %0 raw text\n"
 		"         VARIABLE UPDATE <VAR> %0 name %1 value\n"
 		"         VARIABLE UPDATE <VAR> %0 name %1 value\n"
-		"         VT100 SCROLL REGION   %0 top row %1 bot row\n"
+		"         VT100 SCROLL REGION   %0 top row %1 bot row %2 rows %3 cols %4 wrap\n"
 		"         WEEK <DAY>            %2 day of the week\n"
 		"         WEEK <DAY>            %2 day of the week\n"
 		"         WINDOW FOCUS IN       %0 name\n"
 		"         WINDOW FOCUS IN       %0 name\n"
 		"         WINDOW FOCUS OUT      %0 name\n"
 		"         WINDOW FOCUS OUT      %0 name\n"
 		"         YEAR                  %0 year\n"
 		"         YEAR                  %0 year\n"
 		"\n"
 		"\n"
+		"         To see all events trigger use #event info on. Since this can quite\n"
+		"         spammy it's possible to gag event info messages.\n"
+		"\n"
 		"<178>Example<278>: #event {SESSION CONNECTED} {#read mychar.tin}\n"
 		"<178>Example<278>: #event {SESSION CONNECTED} {#read mychar.tin}\n"
 		"\n"
 		"\n"
 		"<178>Comment<278>: You can remove an event with the #unevent command.\n",
 		"<178>Comment<278>: You can remove an event with the #unevent command.\n",
 		
 		
-		"delay ticker"
+		"button delay ticker"
 	},
 	},
 	{
 	{
 		"FORALL",
 		"FORALL",
@@ -1556,16 +1630,19 @@ struct help_type help_table[] =
 
 
 		"<178>Command<278>: #line <178>{<278>option<178>} {<278>argument<178>}<278>\n"
 		"<178>Command<278>: #line <178>{<278>option<178>} {<278>argument<178>}<278>\n"
 		"\n"
 		"\n"
-		"         #line log {filename} {[text]}          Log the current or given line to\n"
-		"                                                file.\n"
-		"\n"
-		"         #line logverbatim {filename} {[text]}  Log text without variable\n"
-		"                                                substitution.\n"
+		"         #line background                       Prevent new session activation.\n"
 		"\n"
 		"\n"
 		"         #line gag                              Gag the next line.\n"
 		"         #line gag                              Gag the next line.\n"
 		"\n"
 		"\n"
 		"         #line ignore {argument}                Argument is executed without\n"
 		"         #line ignore {argument}                Argument is executed without\n"
 		"                                                any triggers being checked.\n"
 		"                                                any triggers being checked.\n"
+		"\n"
+		"         #line log {filename} {[text]}          Log the current or given line to\n"
+		"                                                file.\n"
+		"\n"
+		"         #line logverbatim {filename} {[text]}  Log text without variable\n"
+		"                                                substitution.\n"
+
 		"\n"
 		"\n"
 		"         #line quiet {argument}                 Argument is executed with\n"
 		"         #line quiet {argument}                 Argument is executed with\n"
 		"                                                suppression of system messages.\n"
 		"                                                suppression of system messages.\n"
@@ -1690,6 +1767,9 @@ struct help_type help_table[] =
 		"         Another option is pressing ctrl-v, which will enable CONVERT META for\n"
 		"         Another option is pressing ctrl-v, which will enable CONVERT META for\n"
 		"         the next key pressed.\n"
 		"         the next key pressed.\n"
 		"\n"
 		"\n"
+		"         If you only want a key sequence to trigger at the start of an input\n"
+		"         line prefix the key sequence with ^.\n"
+		"\n"
 		"<178>Example<278>: #macro {(press ctrl-v)(press F1)} {#showme \\e[2J;#buffer lock}\n"
 		"<178>Example<278>: #macro {(press ctrl-v)(press F1)} {#showme \\e[2J;#buffer lock}\n"
 		"         Clear the screen and lock the window when you press F1, useful when the\n"
 		"         Clear the screen and lock the window when you press F1, useful when the\n"
 		"         boss is near.\n"
 		"         boss is near.\n"
@@ -1697,6 +1777,9 @@ struct help_type help_table[] =
 		"<178>Example<278>: #macro {\\eOM} {#cursor enter}\n"
 		"<178>Example<278>: #macro {\\eOM} {#cursor enter}\n"
 		"         Makes the keypad's enter key work as an enter in keypad mode.\n"
 		"         Makes the keypad's enter key work as an enter in keypad mode.\n"
 		"\n"
 		"\n"
+		"<178>Example<278>: #macro {^nn} {n}\n"
+		"         Makes pressing n twice on an empty line execute north.\n"
+		"\n"
 		"<178>Comment<278>: Not all terminals properly initialize the keypad key sequences.\n"
 		"<178>Comment<278>: Not all terminals properly initialize the keypad key sequences.\n"
 		"         If this is the case you can still use the keypad, but instead of the\n"
 		"         If this is the case you can still use the keypad, but instead of the\n"
 		"         arrow keys use ctrl b, f, p, and n.\n"
 		"         arrow keys use ctrl b, f, p, and n.\n"
@@ -1712,8 +1795,8 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"         The map command is the backbone of the auto mapping feature.\n"
 		"         The map command is the backbone of the auto mapping feature.\n"
 		"\n"
 		"\n"
-		"         <178>#map at <location> <command>\n"
-		"         <278>  Execute the command at the location.\n"
+		"         <178>#map at <exit|vnum> <command>\n"
+		"         <278>  Execute the command at the given exit or vnum.\n"
 		"\n"
 		"\n"
 		"         <178>#map color <field> [value]\n"
 		"         <178>#map color <field> [value]\n"
 		"         <278>  Sets the map color for the given color field.\n"
 		"         <278>  Sets the map color for the given color field.\n"
@@ -1851,6 +1934,11 @@ struct help_type help_table[] =
 		"         <278>  If {rows} or {cols} are a negative number this number is\n"
 		"         <278>  If {rows} or {cols} are a negative number this number is\n"
 		"         <278>  subtracted from the scrolling window size.\n"
 		"         <278>  subtracted from the scrolling window size.\n"
 		"\n"
 		"\n"
+		"         <178>#map map <rows> <cols> draw <square>\n"
+		"         <278>  Display a drawing of the map of the given height and width.\n"
+		"         <278>  The square argument exists of 4 numbers formulating the top\n"
+		"         <278>  left corner and bottom right corner of a square.\n"
+		"\n"
 		"         <278>  If you use {append|overwrite} the map is written to the specified\n"
 		"         <278>  If you use {append|overwrite} the map is written to the specified\n"
 		"         <278>  file name which must be given as the 4th argument.\n"
 		"         <278>  file name which must be given as the 4th argument.\n"
 		"         <278>  If you use {list|variable} the map is saved to the specified\n"
 		"         <278>  If you use {list|variable} the map is saved to the specified\n"
@@ -1877,6 +1965,8 @@ struct help_type help_table[] =
 		"         <278>  Returns you to your last known room after leaving the map\n"
 		"         <278>  Returns you to your last known room after leaving the map\n"
 		"         <278>  or loading a map.\n"
 		"         <278>  or loading a map.\n"
 		"\n"
 		"\n"
+		"         <178>#map roomflag <flags> <get|on|off>\n"
+		"         <278>\n"
 		"         <178>#map roomflag avoid\n"
 		"         <178>#map roomflag avoid\n"
 		"         <278>  When set, '#map find' will avoid a route leading\n"
 		"         <278>  When set, '#map find' will avoid a route leading\n"
 		"         <278>  through that room. Useful when you want to avoid death traps.\n"
 		"         <278>  through that room. Useful when you want to avoid death traps.\n"
@@ -2759,8 +2849,7 @@ struct help_type help_table[] =
 		"<178>Comment<278>: The #prompt helpfile contains more information on using the\n"
 		"<178>Comment<278>: The #prompt helpfile contains more information on using the\n"
 		"         option {row} and {col} arguments.\n",
 		"         option {row} and {col} arguments.\n",
 
 
-		"buffer echo grep"
-		
+		"buffer draw echo grep"
 	},
 	},
 	{
 	{
 		"SNOOP",
 		"SNOOP",

+ 0 - 211
src/highlight.c

@@ -1,211 +0,0 @@
-/******************************************************************************
-*   This file is part of TinTin++                                             *
-*                                                                             *
-*   Copyright 2004-2019 Igor van den Hoven                                    *
-*                                                                             *
-*   TinTin++ is free software; you can redistribute it and/or modify          *
-*   it under the terms of the GNU General Public License as published by      *
-*   the Free Software Foundation; either version 3 of the License, or         *
-*   (at your option) any later version.                                       *
-*                                                                             *
-*   This program is distributed in the hope that it will be useful,           *
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
-*   GNU General Public License for more details.                              *
-*                                                                             *
-*                                                                             *
-*   You should have received a copy of the GNU General Public License         *
-*   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
-******************************************************************************/
-
-/******************************************************************************
-*                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
-*                                                                             *
-*                          coded by Bill Reiss 1993                           *
-*                     recoded by Igor van den Hoven 2004                      *
-******************************************************************************/
-
-
-#include "tintin.h"
-
-
-DO_COMMAND(do_highlight)
-{
-	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE], temp[BUFFER_SIZE];
-
-	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
-	arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
-	arg = get_arg_in_braces(ses, arg, arg3, GET_ALL);
-
-	if (*arg3 == 0)
-	{
-		strcpy(arg3, "5");
-	}
-
-	if (*arg1 == 0)
-	{
-		show_list(ses->list[LIST_HIGHLIGHT], 0);
-	}
-	else if (*arg1 && *arg2 == 0)
-	{
-		if (show_node_with_wild(ses, arg1, ses->list[LIST_HIGHLIGHT]) == FALSE)
-		{
-			show_message(ses, LIST_HIGHLIGHT, "#HIGHLIGHT: NO MATCH(ES) FOUND FOR {%s}.", arg1);
-		}
-	}
-	else
-	{
-		if (get_highlight_codes(ses, arg2, temp) == FALSE)
-		{
-			tintin_printf2(ses, "#HIGHLIGHT: VALID COLORS ARE:\n");
-			tintin_printf2(ses, "reset, bold, light, faint, dim, dark, underscore, blink, reverse, black, red, green, yellow, blue, magenta, cyan, white, b black, b red, b green, b yellow, b blue, b magenta, b cyan, b white, azure, ebony, jade, lime, orange, pink, silver, tan, violet.");
-		}
-		else
-		{
-			update_node_list(ses->list[LIST_HIGHLIGHT], arg1, arg2, arg3, "");
-
-			show_message(ses, LIST_HIGHLIGHT, "#OK. {%s} NOW HIGHLIGHTS {%s} @ {%s}.", arg1, arg2, arg3);
-		}
-	}
-	return ses;
-}
-
-
-DO_COMMAND(do_unhighlight)
-{
-	delete_node_with_wild(ses, LIST_HIGHLIGHT, arg);
-
-	return ses;
-}
-
-void check_all_highlights(struct session *ses, char *original, char *line)
-{
-	struct listroot *root = ses->list[LIST_HIGHLIGHT];
-	struct listnode *node;
-	char *pto, *ptl, *ptm;
-	char match[BUFFER_SIZE], color[BUFFER_SIZE], reset[BUFFER_SIZE], output[BUFFER_SIZE], plain[BUFFER_SIZE];
-	int len;
-
-	push_call("check_all_highlights(%p,%p,%p)",ses,original,line);
-
-	for (root->update = 0 ; root->update < root->used ; root->update++)
-	{
-		if (check_one_regexp(ses, root->list[root->update], line, original, 0))
-		{
-			node = root->list[root->update];
-
-			get_highlight_codes(ses, node->arg2, color);
-
-			*output = *reset = 0;
-
-			pto = original;
-			ptl = line;
-
-			do
-			{
-				if (*gtd->vars[0] == 0)
-				{
-					break;
-				}
-
-				strcpy(match, gtd->vars[0]);
-
-				strip_vt102_codes(match, plain);
-
-				if (*node->arg1 == '~')
-				{
-					ptm = strstr(pto, match);
-
-					len = strlen(match);
-				}
-				else
-				{
-					ptm = strip_vt102_strstr(pto, match, &len);
-
-					ptl = strstr(ptl, match) + strlen(match);
-				}
-
-				*ptm = 0;
-
-				get_color_codes(reset, pto, reset);
-
-				cat_sprintf(output, "%s%s%s\e[0m%s", pto, color, plain, reset);
-
-				pto = ptm + len;
-
-				show_debug(ses, LIST_HIGHLIGHT, "#DEBUG HIGHLIGHT {%s}", node->arg1);
-			}
-			while (check_one_regexp(ses, node, ptl, pto, 0));
-
-			strcat(output, pto);
-
-			strcpy(original, output);
-		}
-	}
-	pop_call();
-	return;
-}
-
-int get_highlight_codes(struct session *ses, char *string, char *result)
-{
-	int cnt;
-
-	*result = 0;
-
-	if (*string == '<')
-	{
-		substitute(ses, string, result, SUB_COL);
-
-		return TRUE;
-	}
-
-	if (*string == '\\')
-	{
-		substitute(ses, string, result, SUB_ESC);
-
-		return TRUE;
-	}
-
-	while (*string)
-	{
-		if (isalpha((int) *string))
-		{
-			for (cnt = 0 ; *color_table[cnt].name ; cnt++)
-			{
-				if (is_abbrev(color_table[cnt].name, string))
-				{
-					substitute(ses, color_table[cnt].code, result, SUB_COL);
-
-					result += strlen(result);
-
-					break;
-				}
-			}
-
-			if (*color_table[cnt].name == 0)
-			{
-				return FALSE;
-			}
-
-			string += strlen(color_table[cnt].name);
-		}
-
-		switch (*string)
-		{
-			case ' ':
-			case ';':
-			case ',':
-			case '{':
-			case '}':
-				string++;
-				break;
-
-			case 0:
-				return TRUE;
-
-			default:
-				return FALSE;
-		}
-	}
-	return TRUE;
-}

+ 1 - 1
src/history.c

@@ -71,7 +71,7 @@ void add_line_history(struct session *ses, char *line)
 
 
 	root = ses->list[LIST_HISTORY];
 	root = ses->list[LIST_HISTORY];
 
 
-	if (HAS_BIT(root->flags, LIST_FLAG_IGNORE))
+	if (HAS_BIT(root->flags, LIST_FLAG_IGNORE) || gtd->ignore_level)
 	{
 	{
 		return;
 		return;
 	}
 	}

+ 30 - 92
src/input.c

@@ -107,10 +107,14 @@ void read_line()
 
 
 	buffer[len] = 0;
 	buffer[len] = 0;
 
 
-	if (HAS_BIT(gtd->ses->flags, SES_FLAG_CONVERTMETA) || HAS_BIT(gtd->flags, TINTIN_FLAG_CONVERTMETACHAR))
+	if (HAS_BIT(gtd->ses->flags, SES_FLAG_CONVERTMETA))
 	{
 	{
 		convert_meta(buffer, &gtd->macro_buf[strlen(gtd->macro_buf)], FALSE);
 		convert_meta(buffer, &gtd->macro_buf[strlen(gtd->macro_buf)], FALSE);
 	}
 	}
+	else if (HAS_BIT(gtd->flags, TINTIN_FLAG_CONVERTMETACHAR))
+	{
+		convert_meta(buffer, &gtd->macro_buf[strlen(gtd->macro_buf)], TRUE);
+	}
 	else
 	else
 	{
 	{
 		strcat(gtd->macro_buf, buffer);
 		strcat(gtd->macro_buf, buffer);
@@ -127,7 +131,11 @@ void read_line()
 			{
 			{
 				node = root->list[root->update];
 				node = root->list[root->update];
 
 
-				if (!strcmp(gtd->macro_buf, node->arg3))
+				if (*node->arg1 == '^' && gtd->input_len)
+				{
+					continue;
+				}
+				else if (!strcmp(gtd->macro_buf, node->arg3))
 				{
 				{
 					script_driver(gtd->ses, LIST_MACRO, node->arg2);
 					script_driver(gtd->ses, LIST_MACRO, node->arg2);
 
 
@@ -165,7 +173,7 @@ void read_line()
 			return;
 			return;
 		}
 		}
 
 
-		if (gtd->macro_buf[0] == ESCAPE)
+		if (gtd->macro_buf[0] == ASCII_ESC)
 		{
 		{
 			if (gtd->macro_buf[1] == '[')
 			if (gtd->macro_buf[1] == '[')
 			{
 			{
@@ -291,7 +299,7 @@ void read_line()
 		}
 		}
 	}
 	}
 
 
-	if (gtd->macro_buf[0] == ESCAPE)
+	if (gtd->macro_buf[0] == ASCII_ESC)
 	{
 	{
 		strcpy(buffer, gtd->macro_buf);
 		strcpy(buffer, gtd->macro_buf);
 
 
@@ -312,8 +320,8 @@ void read_line()
 	{
 	{
 		switch (gtd->macro_buf[0])
 		switch (gtd->macro_buf[0])
 		{
 		{
-			case '\r':
-			case '\n':
+			case ASCII_CR:
+			case ASCII_LF:
 				cursor_enter(gtd->ses, "");
 				cursor_enter(gtd->ses, "");
 
 
 				memmove(gtd->macro_buf, &gtd->macro_buf[1], 1 + strlen(&gtd->macro_buf[1]));
 				memmove(gtd->macro_buf, &gtd->macro_buf[1], 1 + strlen(&gtd->macro_buf[1]));
@@ -430,7 +438,11 @@ void read_key(void)
 			{
 			{
 				node = root->list[root->update];
 				node = root->list[root->update];
 
 
-				if (!strcmp(gtd->macro_buf, node->arg3))
+				if (*node->arg1 == '^' && gtd->input_buf[0])
+				{
+					continue;
+				}
+				else if (!strcmp(gtd->macro_buf, node->arg3))
 				{
 				{
 					script_driver(gtd->ses, LIST_MACRO, node->arg2);
 					script_driver(gtd->ses, LIST_MACRO, node->arg2);
 
 
@@ -454,7 +466,8 @@ void read_key(void)
 	{
 	{
 		switch (gtd->macro_buf[cnt])
 		switch (gtd->macro_buf[cnt])
 		{
 		{
-			case '\n':
+			case ASCII_CR:
+			case ASCII_LF:
 				gtd->input_buf[0] = 0;
 				gtd->input_buf[0] = 0;
 				gtd->macro_buf[0] = 0;
 				gtd->macro_buf[0] = 0;
 				gtd->input_len = 0;
 				gtd->input_len = 0;
@@ -514,13 +527,13 @@ void convert_meta(char *input, char *output, int eol)
 	{
 	{
 		switch (*pti)
 		switch (*pti)
 		{
 		{
-			case ESCAPE:
+			case ASCII_ESC:
 				*pto++ = '\\';
 				*pto++ = '\\';
 				*pto++ = 'e';
 				*pto++ = 'e';
 				pti++;
 				pti++;
 				break;
 				break;
 
 
-			case 127:
+			case ASCII_DEL:
 				*pto++ = '\\';
 				*pto++ = '\\';
 				*pto++ = 'x';
 				*pto++ = 'x';
 				*pto++ = '7';
 				*pto++ = '7';
@@ -528,31 +541,31 @@ void convert_meta(char *input, char *output, int eol)
 				pti++;
 				pti++;
 				break;
 				break;
 
 
-			case '\a':
+			case ASCII_BEL:
 				*pto++ = '\\';
 				*pto++ = '\\';
 				*pto++ = 'a';
 				*pto++ = 'a';
 				pti++;
 				pti++;
 				break;
 				break;
 
 
-			case '\b':
+			case ASCII_BS:
 				*pto++ = '\\';
 				*pto++ = '\\';
 				*pto++ = 'b';
 				*pto++ = 'b';
 				pti++;
 				pti++;
 				break;
 				break;
 
 
-			case '\f':
+			case ASCII_FF:
 				*pto++ = '\\';
 				*pto++ = '\\';
 				*pto++ = 'f';
 				*pto++ = 'f';
 				pti++;
 				pti++;
 				break;
 				break;
 
 
-			case '\t':
+			case ASCII_HTAB:
 				*pto++ = '\\';
 				*pto++ = '\\';
 				*pto++ = 't';
 				*pto++ = 't';
 				pti++;
 				pti++;
 				break;
 				break;
 
 
-			case '\r':
+			case ASCII_CR:
 				if (eol)
 				if (eol)
 				{
 				{
 					*pto++ = '\\';
 					*pto++ = '\\';
@@ -561,13 +574,13 @@ void convert_meta(char *input, char *output, int eol)
 				*pto++ = *pti++;
 				*pto++ = *pti++;
 				break;
 				break;
 
 
-			case '\v':
+			case ASCII_VTAB:
 				*pto++ = '\\';
 				*pto++ = '\\';
 				*pto++ = 'v';
 				*pto++ = 'v';
 				pti++;
 				pti++;
 				break;
 				break;
 
 
-			case '\n':
+			case ASCII_LF:
 				if (eol)
 				if (eol)
 				{
 				{
 					*pto++ = '\\';
 					*pto++ = '\\';
@@ -614,81 +627,6 @@ char *str_convert_meta(char *input, int eol)
 	return buf;
 	return buf;
 }
 }
 
 
-void unconvert_meta(char *input, char *output)
-{
-	char *pti, *pto;
-
-	pti = input;
-	pto = output;
-
-	while (*pti)
-	{
-		switch (pti[0])
-		{
-			case '\\':
-				switch (pti[1])
-				{
-					case 'C':
-						if (pti[2] == '-' && pti[3])
-						{
-							*pto++  = pti[3] - 'a' + 1;
-							pti    += 4;
-						}
-						else
-						{
-							*pto++ = *pti++;
-						}
-						break;
-
-					case 'c':
-						*pto++ = pti[2] % 32;
-						pti += 3;
-						break;
-
-					case 'a':
-						*pto++  = '\a';
-						pti += 2;
-						break;
-
-					case 'b':
-						*pto++  = 127;
-						pti    += 2;
-						break;
-
-					case 'e':
-						*pto++  = ESCAPE;
-						pti    += 2;
-						break;
-
-					case 't':
-						*pto++  = '\t';
-						pti    += 2;
-						break;
-
-					case 'x':
-						if (pti[2] && pti[3])
-						{
-							*pto++ = hex_number_8bit(&pti[2]);
-							pti += 4;
-						}
-						else
-						{
-							*pto++ = *pti++;
-						}
-						break;
-					default:
-						*pto++ = *pti++;
-						break;
-				}
-				break;
-
-			default:
-				*pto++ = *pti++;
-				break;
-		}
-	}
-	*pto = 0;
-}
 
 
 /*
 /*
 	Currenly only used in split mode.
 	Currenly only used in split mode.

+ 142 - 69
src/line.c

@@ -59,6 +59,27 @@ DO_COMMAND(do_line)
 	return ses;
 	return ses;
 }
 }
 
 
+DO_LINE(line_background)
+{
+	char arg1[BUFFER_SIZE];
+
+	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
+
+	if (*arg1 == 0)
+	{
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {BACKGROUND} {command}.");
+
+		return ses;
+	}
+
+	gtd->background_level++;
+
+	ses = script_driver(ses, LIST_COMMAND, arg1);
+
+	gtd->background_level--;
+
+	return ses;
+}
 
 
 DO_LINE(line_gag)
 DO_LINE(line_gag)
 {
 {
@@ -73,6 +94,28 @@ DO_LINE(line_gag)
 	return ses;
 	return ses;
 }
 }
 
 
+DO_LINE(line_ignore)
+{
+	char arg1[BUFFER_SIZE];
+
+	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
+
+	if (*arg1 == 0)
+	{
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {IGNORE} {command}.");
+		
+		return ses;
+	}
+
+	gtd->ignore_level++;
+
+	ses = script_driver(ses, LIST_COMMAND, arg1);
+
+	gtd->ignore_level--;
+
+	return ses;
+}
+
 // Without an argument mark next line to be logged, otherwise log the given line to file.
 // Without an argument mark next line to be logged, otherwise log the given line to file.
 
 
 DO_LINE(line_log)
 DO_LINE(line_log)
@@ -89,7 +132,7 @@ DO_LINE(line_log)
 
 
 		if (ses->logline_time == gtd->time && !strcmp(ses->logline_name, arg1))
 		if (ses->logline_time == gtd->time && !strcmp(ses->logline_name, arg1))
 		{
 		{
-			logit(ses, arg2, ses->logline_file, FALSE);
+			logit(ses, arg2, ses->logline_file, LOG_FLAG_NONE);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -105,17 +148,9 @@ DO_LINE(line_log)
 				ses->logline_file = logfile;
 				ses->logline_file = logfile;
 				ses->logline_time = gtd->time;
 				ses->logline_time = gtd->time;
 
 
-				if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
-				{
-					fseek(logfile, 0, SEEK_END);
+				loginit(ses, ses->logline_file, LOG_FLAG_APPEND | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
 
 
-					if (ftell(logfile) == 0)
-					{
-						write_html_header(ses, logfile);
-					}
-				}
-
-				logit(ses, arg2, ses->logline_file, FALSE);
+				logit(ses, arg2, ses->logline_file, LOG_FLAG_NONE);
 			}
 			}
 			else
 			else
 			{
 			{
@@ -127,7 +162,7 @@ DO_LINE(line_log)
 	{
 	{
 		if (ses->lognext_time == gtd->time && !strcmp(ses->lognext_name, arg1))
 		if (ses->lognext_time == gtd->time && !strcmp(ses->lognext_name, arg1))
 		{
 		{
-			SET_BIT(ses->flags, SES_FLAG_LOGNEXT);
+			SET_BIT(ses->logmode, LOG_FLAG_NEXT);
 		}
 		}
 		else if ((logfile = fopen(arg1, "a")))
 		else if ((logfile = fopen(arg1, "a")))
 		{
 		{
@@ -141,7 +176,7 @@ DO_LINE(line_log)
 			ses->lognext_file = logfile;
 			ses->lognext_file = logfile;
 			ses->lognext_time = gtd->time;
 			ses->lognext_time = gtd->time;
 
 
-			SET_BIT(ses->flags, SES_FLAG_LOGNEXT);
+			SET_BIT(ses->logmode, LOG_FLAG_NEXT);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -151,6 +186,72 @@ DO_LINE(line_log)
 	return ses;
 	return ses;
 }
 }
 
 
+DO_LINE(line_logmode)
+{
+	struct session *active_ses;
+
+	char arg1[BUFFER_SIZE];
+
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
+
+	DEL_BIT(ses->logmode, LOG_FLAG_OLD_HTML|LOG_FLAG_OLD_PLAIN|LOG_FLAG_OLD_RAW);
+
+	switch (HAS_BIT(ses->logmode, LOG_FLAG_HTML|LOG_FLAG_PLAIN|LOG_FLAG_RAW))
+	{
+		case LOG_FLAG_HTML:
+			SET_BIT(ses->logmode, LOG_FLAG_OLD_HTML);
+			break;
+		case LOG_FLAG_PLAIN:
+			SET_BIT(ses->logmode, LOG_FLAG_OLD_PLAIN);
+			break;
+		case LOG_FLAG_RAW:
+			SET_BIT(ses->logmode, LOG_FLAG_OLD_RAW);
+			break;
+	}
+
+	DEL_BIT(ses->logmode, LOG_FLAG_HTML|LOG_FLAG_PLAIN|LOG_FLAG_RAW);
+
+	if (is_abbrev(arg1, "HTML"))
+	{
+		SET_BIT(ses->logmode, LOG_FLAG_HTML);
+	}
+	else if (is_abbrev(arg1, "PLAIN"))
+	{
+		SET_BIT(ses->logmode, LOG_FLAG_PLAIN);
+	}
+	else if (is_abbrev(arg1, "RAW"))
+	{
+		SET_BIT(ses->logmode, LOG_FLAG_RAW);
+	}
+	else
+	{
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {LOGMODE} {HTML|PLAIN|RAW} {command}.");
+
+		return ses;
+	}
+
+	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
+
+	active_ses = script_driver(ses, LIST_COMMAND, arg1);
+
+	DEL_BIT(ses->logmode, LOG_FLAG_HTML|LOG_FLAG_PLAIN|LOG_FLAG_RAW);
+
+	switch (HAS_BIT(ses->logmode, LOG_FLAG_OLD_HTML|LOG_FLAG_OLD_PLAIN|LOG_FLAG_OLD_RAW))
+	{
+		case LOG_FLAG_OLD_HTML:
+			SET_BIT(ses->logmode, LOG_FLAG_HTML);
+			break;
+		case LOG_FLAG_OLD_PLAIN:
+			SET_BIT(ses->logmode, LOG_FLAG_PLAIN);
+			break;
+		case LOG_FLAG_OLD_RAW:
+			SET_BIT(ses->logmode, LOG_FLAG_RAW);
+			break;
+	}
+
+	return ses = active_ses;
+}
+
 DO_LINE(line_logverbatim)
 DO_LINE(line_logverbatim)
 {
 {
 	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
 	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE];
@@ -163,7 +264,7 @@ DO_LINE(line_logverbatim)
 	{
 	{
 		if (!strcmp(ses->logline_name, arg1))
 		if (!strcmp(ses->logline_name, arg1))
 		{
 		{
-			logit(ses, arg2, ses->logline_file, TRUE);
+			logit(ses, arg2, ses->logline_file, LOG_FLAG_LINEFEED);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -177,17 +278,9 @@ DO_LINE(line_logverbatim)
 				ses->logline_name = strdup(arg1);
 				ses->logline_name = strdup(arg1);
 				ses->logline_file = logfile;
 				ses->logline_file = logfile;
 
 
-				if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
-				{
-					fseek(logfile, 0, SEEK_END);
+				loginit(ses, ses->logline_file, LOG_FLAG_APPEND | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
 
 
-					if (ftell(logfile) == 0)
-					{
-						write_html_header(ses, logfile);
-					}
-				}
-
-				logit(ses, arg2, ses->logline_file, TRUE);
+				logit(ses, arg2, ses->logline_file, LOG_FLAG_LINEFEED);
 			}
 			}
 			else
 			else
 			{
 			{
@@ -199,7 +292,7 @@ DO_LINE(line_logverbatim)
 	{
 	{
 		if (!strcmp(ses->lognext_name, arg1))
 		if (!strcmp(ses->lognext_name, arg1))
 		{
 		{
-			SET_BIT(ses->flags, SES_FLAG_LOGNEXT);
+			SET_BIT(ses->logmode, LOG_FLAG_NEXT);
 		}
 		}
 		else if ((logfile = fopen(arg1, "a")))
 		else if ((logfile = fopen(arg1, "a")))
 		{
 		{
@@ -211,7 +304,7 @@ DO_LINE(line_logverbatim)
 			ses->lognext_name = strdup(arg1);
 			ses->lognext_name = strdup(arg1);
 			ses->lognext_file = logfile;
 			ses->lognext_file = logfile;
 
 
-			SET_BIT(ses->flags, SES_FLAG_LOGNEXT);
+			SET_BIT(ses->logmode, LOG_FLAG_NEXT);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -221,6 +314,29 @@ DO_LINE(line_logverbatim)
 	return ses;
 	return ses;
 }
 }
 
 
+
+DO_LINE(line_quiet)
+{
+	char arg1[BUFFER_SIZE];
+
+	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
+
+	if (*arg1 == 0)
+	{
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {QUIET} {command}.");
+		
+		return ses;
+	}
+
+	gtd->quiet_level++;
+
+	ses = script_driver(ses, LIST_COMMAND, arg1);
+
+	gtd->quiet_level--;
+
+	return ses;
+}
+
 DO_LINE(line_strip)
 DO_LINE(line_strip)
 {
 {
 	char arg1[BUFFER_SIZE], strip[BUFFER_SIZE];
 	char arg1[BUFFER_SIZE], strip[BUFFER_SIZE];
@@ -327,47 +443,4 @@ DO_LINE(line_verbose)
 	return ses;
 	return ses;
 }
 }
 
 
-DO_LINE(line_ignore)
-{
-	char arg1[BUFFER_SIZE];
-
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
-
-	if (*arg1 == 0)
-	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {IGNORE} {command}.");
-		
-		return ses;
-	}
-
-	gtd->ignore_level++;
-
-	ses = script_driver(ses, LIST_COMMAND, arg1);
-
-	gtd->ignore_level--;
-
-	return ses;
-}
-
-DO_LINE(line_quiet)
-{
-	char arg1[BUFFER_SIZE];
-
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
-
-	if (*arg1 == 0)
-	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {QUIET} {command}.");
-		
-		return ses;
-	}
-
-	gtd->quiet++;
-
-	ses = script_driver(ses, LIST_COMMAND, arg1);
-
-	gtd->quiet--;
-
-	return ses;
-}
 	
 	

+ 40 - 14
src/log.c

@@ -27,17 +27,17 @@
 #include "tintin.h"
 #include "tintin.h"
 
 
 
 
-void logit(struct session *ses, char *txt, FILE *file, int newline)
+void logit(struct session *ses, char *txt, FILE *file, int flags)
 {
 {
 	char out[BUFFER_SIZE];
 	char out[BUFFER_SIZE];
 
 
-	push_call("logit(%p,%p,%p,%d)",ses,txt,file,newline);
+	push_call("logit(%p,%p,%p,%d)",ses,txt,file,flags);
 
 
-	if (HAS_BIT(ses->flags, SES_FLAG_LOGPLAIN))
+	if (HAS_BIT(ses->logmode, LOG_FLAG_PLAIN))
 	{
 	{
 		strip_vt102_codes(txt, out);
 		strip_vt102_codes(txt, out);
 	}
 	}
-	else if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
+	else if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
 	{
 	{
 		vt102_to_html(ses, txt, out);
 		vt102_to_html(ses, txt, out);
 	}
 	}
@@ -46,7 +46,7 @@ void logit(struct session *ses, char *txt, FILE *file, int newline)
 		strcpy(out, txt);
 		strcpy(out, txt);
 	}
 	}
 
 
-	if (newline)
+	if (HAS_BIT(flags, LOG_FLAG_LINEFEED))
 	{
 	{
 		strcat(out, "\n");
 		strcat(out, "\n");
 	}
 	}
@@ -58,6 +58,32 @@ void logit(struct session *ses, char *txt, FILE *file, int newline)
 	return;
 	return;
 }
 }
 
 
+void loginit(struct session *ses, FILE *file, int flags)
+{
+	push_call("loginit(%p,%p,%d)",ses,file,flags);
+
+	if (HAS_BIT(flags, LOG_FLAG_APPEND))
+	{
+		if (HAS_BIT(flags, LOG_FLAG_HTML))
+		{
+			fseek(file, 0, SEEK_END);
+
+			if (ftell(file) == 0)
+			{
+				write_html_header(ses, file);
+			}
+		}
+	}
+	else if (HAS_BIT(flags, LOG_FLAG_OVERWRITE) && HAS_BIT(flags, LOG_FLAG_HTML))
+	{
+		if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
+		{
+			write_html_header(ses, ses->logfile);
+		}
+	}
+	pop_call();
+	return;
+}
 
 
 DO_COMMAND(do_log)
 DO_COMMAND(do_log)
 {
 {
@@ -80,12 +106,10 @@ DO_COMMAND(do_log)
 
 
 		if ((ses->logfile = fopen(arg2, "a")))
 		if ((ses->logfile = fopen(arg2, "a")))
 		{
 		{
-			fseek(ses->logfile, 0, SEEK_END);
+			SET_BIT(ses->logmode, LOG_FLAG_APPEND);
+
+			loginit(ses, ses->logfile, ses->logmode);
 
 
-			if (ftell(ses->logfile) == 0 && HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
-			{
-				write_html_header(ses, ses->logfile);
-			}
 			show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s' FILESIZE: %ld", arg2, ftell(ses->logfile));
 			show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s' FILESIZE: %ld", arg2, ftell(ses->logfile));
 		}
 		}
 		else
 		else
@@ -102,10 +126,10 @@ DO_COMMAND(do_log)
 
 
 		if ((ses->logfile = fopen(arg2, "w")))
 		if ((ses->logfile = fopen(arg2, "w")))
 		{
 		{
-			if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
-			{
-				write_html_header(ses, ses->logfile);
-			}
+			SET_BIT(ses->logmode, LOG_FLAG_OVERWRITE);
+
+			loginit(ses, ses->logfile, ses->logmode);
+
 			show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s'", arg2);
 			show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s'", arg2);
 		}
 		}
 		else
 		else
@@ -117,6 +141,8 @@ DO_COMMAND(do_log)
 	{
 	{
 		if (ses->logfile)
 		if (ses->logfile)
 		{
 		{
+			DEL_BIT(ses->logmode, LOG_FLAG_APPEND|LOG_FLAG_OVERWRITE);
+
 			fclose(ses->logfile);
 			fclose(ses->logfile);
 			ses->logfile = NULL;
 			ses->logfile = NULL;
 			show_message(ses, LIST_COMMAND, "#LOG: LOGGING TURNED OFF.");
 			show_message(ses, LIST_COMMAND, "#LOG: LOGGING TURNED OFF.");

+ 0 - 66
src/macro.c

@@ -1,66 +0,0 @@
-/******************************************************************************
-*   This file is part of TinTin++                                             *
-*                                                                             *
-*   Copyright 2004-2019 Igor van den Hoven                                    *
-*                                                                             *
-*   TinTin++ is free software; you can redistribute it and/or modify          *
-*   it under the terms of the GNU General Public License as published by      *
-*   the Free Software Foundation; either version 3 of the License, or         *
-*   (at your option) any later version.                                       *
-*                                                                             *
-*   This program is distributed in the hope that it will be useful,           *
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
-*   GNU General Public License for more details.                              *
-*                                                                             *
-*                                                                             *
-*   You should have received a copy of the GNU General Public License         *
-*   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
-******************************************************************************/
-
-/******************************************************************************
-*                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
-*                                                                             *
-*                      coded by Igor van den Hoven 2006                       *
-******************************************************************************/
-
-
-#include "tintin.h"
-
-DO_COMMAND(do_macro)
-{
-	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE];
-
-	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
-	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
-
-	if (*arg1 == 0)
-	{
-		show_list(ses->list[LIST_MACRO], 0);
-	}
-	else if (*arg1 && *arg2 == 0)
-	{
-		if (show_node_with_wild(ses, arg1, ses->list[LIST_MACRO]) == FALSE)
-		{
-			show_message(ses, LIST_MACRO, "#MACRO: NO MATCH(ES) FOUND FOR {%s}.", arg1);
-		}
-	}
-	else
-	{
-		unconvert_meta(arg1, arg3);
-
-		update_node_list(ses->list[LIST_MACRO], arg1, arg2, arg3, "");
-
-		show_message(ses, LIST_MACRO, "#OK. MACRO {%s} HAS BEEN SET TO {%s}.", arg1, arg2);
-	}
-	return ses;
-}
-
-
-DO_COMMAND(do_unmacro)
-{
-	delete_node_with_wild(ses, LIST_MACRO, arg);
-
-	return ses;
-}
-

+ 13 - 13
src/main.c

@@ -239,9 +239,9 @@ int main(int argc, char **argv)
 					break;
 					break;
 
 
 				case 'e':
 				case 'e':
-					gtd->quiet++;
+					gtd->quiet_level++;
 					gtd->ses = script_driver(gtd->ses, LIST_COMMAND, optarg);
 					gtd->ses = script_driver(gtd->ses, LIST_COMMAND, optarg);
-					gtd->quiet--;
+					gtd->quiet_level--;
 					break;
 					break;
 
 
 				case 'G':
 				case 'G':
@@ -351,7 +351,8 @@ void init_tintin(int greeting)
 
 
 	gtd->input_off      = 1;
 	gtd->input_off      = 1;
 
 
-	gtd->home           = strdup(getenv("HOME") ? getenv("HOME") : ".");
+	gtd->os             = strdup(getenv("OS") ? getenv("OS") : "UNKNOWN");
+	gtd->home           = strdup(getenv("HOME") ? getenv("HOME") : "~/");
 	gtd->lang           = strdup(getenv("LANG") ? getenv("LANG") : "UNKNOWN");
 	gtd->lang           = strdup(getenv("LANG") ? getenv("LANG") : "UNKNOWN");
 	gtd->term           = strdup(getenv("TERM") ? getenv("TERM") : "UNKNOWN");
 	gtd->term           = strdup(getenv("TERM") ? getenv("TERM") : "UNKNOWN");
 
 
@@ -414,7 +415,7 @@ void init_tintin(int greeting)
 	do_configure(gts, "{CONNECT RETRY}       {0}");
 	do_configure(gts, "{CONNECT RETRY}       {0}");
 	do_configure(gts, "{CHARSET}          {AUTO}");
 	do_configure(gts, "{CHARSET}          {AUTO}");
 	do_configure(gts, "{HISTORY SIZE}     {1000}");
 	do_configure(gts, "{HISTORY SIZE}     {1000}");
-	do_configure(gts, "{LOG}               {RAW}");
+	do_configure(gts, "{LOG MODE}          {RAW}");
 	do_configure(gts, "{MOUSE TRACKING}    {OFF}");
 	do_configure(gts, "{MOUSE TRACKING}    {OFF}");
 	do_configure(gts, "{PACKET PATCH}     {AUTO}");
 	do_configure(gts, "{PACKET PATCH}     {AUTO}");
 	do_configure(gts, "{RANDOM SEED}      {AUTO}");
 	do_configure(gts, "{RANDOM SEED}      {AUTO}");
@@ -431,6 +432,7 @@ void init_tintin(int greeting)
 	}
 	}
 	do_configure(gts, "{SCROLL LOCK}        {ON}");
 	do_configure(gts, "{SCROLL LOCK}        {ON}");
 	do_configure(gts, "{SPEEDWALK}         {OFF}");
 	do_configure(gts, "{SPEEDWALK}         {OFF}");
+	do_configure(gts, "{TELNET}             {ON}");
 	do_configure(gts, "{TINTIN CHAR}         {#}");
 	do_configure(gts, "{TINTIN CHAR}         {#}");
 	do_configure(gts, "{VERBATIM}          {OFF}");
 	do_configure(gts, "{VERBATIM}          {OFF}");
 	do_configure(gts, "{VERBATIM CHAR}      {\\}");
 	do_configure(gts, "{VERBATIM CHAR}      {\\}");
@@ -601,12 +603,12 @@ void syserr_signal(int signal, char *msg)
 		exit(-1);
 		exit(-1);
 	}
 	}
 
 
-	dump_stack();
-
 	reset_terminal(gts);
 	reset_terminal(gts);
 
 
 	reset_screen(gts);
 	reset_screen(gts);
 
 
+	dump_stack_fatal();
+
 	sprintf(buf, "\e[1;31mFATAL SIGNAL FROM (%s): %s\e[0m\n", msg, strsignal(signal));
 	sprintf(buf, "\e[1;31mFATAL SIGNAL FROM (%s): %s\e[0m\n", msg, strsignal(signal));
 
 
 	printf("%s", buf);
 	printf("%s", buf);
@@ -639,18 +641,16 @@ void syserr_fatal(int signal, char *msg)
 		sprintf(errstr, "(signal %d: %s)", signal, strsignal(signal));
 		sprintf(errstr, "(signal %d: %s)", signal, strsignal(signal));
 	}
 	}
 
 
-	if (gtd->quiet)
+	if (gtd->quiet_level)
 	{
 	{
-		gtd->quiet = 0;
+		gtd->quiet_level = 0;
 	}
 	}
 
 
-	reset_terminal(gtd->ses);
-
-	reset_screen(gtd->ses);
+	reset_terminal(gts);
 
 
-	DEL_BIT(gtd->ses->flags, SES_FLAG_SPLIT);
+	reset_screen(gts);
 
 
-	dump_stack();
+	dump_stack_fatal();
 
 
 	sprintf(buf, "\n\e[1;31mFATAL ERROR \e[1;32m%s %s\e[0m\n", msg, errstr);
 	sprintf(buf, "\n\e[1;31mFATAL ERROR \e[1;32m%s %s\e[0m\n", msg, errstr);
 
 

+ 292 - 183
src/mapper.c

@@ -72,6 +72,7 @@ DO_COMMAND(do_map)
 		tintin_printf2(ses, "#map list     <location>               (shows list of matching rooms)");
 		tintin_printf2(ses, "#map list     <location>               (shows list of matching rooms)");
 		tintin_printf2(ses, "#map map      <radius> <filename>      (shows an ascii map)");
 		tintin_printf2(ses, "#map map      <radius> <filename>      (shows an ascii map)");
 		tintin_printf2(ses, "#map move     <direction>              (move to given direction)");
 		tintin_printf2(ses, "#map move     <direction>              (move to given direction)");
+		tintin_printf2(ses, "#map offset   <square>                 (place vtmap in given square)");
 		tintin_printf2(ses, "#map read     <filename>               (load a map from file)");
 		tintin_printf2(ses, "#map read     <filename>               (load a map from file)");
 		tintin_printf2(ses, "#map resize   <size>                   (resize the maximum size)");
 		tintin_printf2(ses, "#map resize   <size>                   (resize the maximum size)");
 		tintin_printf2(ses, "#map roomflag <room flag>              (set room based flags)");
 		tintin_printf2(ses, "#map roomflag <room flag>              (set room based flags)");
@@ -131,6 +132,7 @@ DO_COMMAND(do_map)
 
 
 DO_MAP(map_at)
 DO_MAP(map_at)
 {
 {
+	struct exit_data *exit;
 	int new_room;
 	int new_room;
 
 
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
@@ -140,9 +142,15 @@ DO_MAP(map_at)
 
 
 	if (new_room == 0)
 	if (new_room == 0)
 	{
 	{
-		show_message(ses, LIST_COMMAND, "#MAP AT: Couldn't find room {%s}.", arg1);
+		exit = find_exit(ses, ses->map->in_room, arg1);
 
 
-		return;
+		if (exit == NULL)
+		{
+			show_error(ses, LIST_COMMAND, "#MAP AT: Couldn't find room or exit {%s}.", arg1);
+
+			return;
+		}
+		new_room = exit->vnum;
 	}
 	}
 
 
 	ses->map->at_room = ses->map->in_room;
 	ses->map->at_room = ses->map->in_room;
@@ -188,7 +196,7 @@ DO_MAP(map_color)
 				{
 				{
 					strncpy(ses->map->color[index], arg2, COLOR_SIZE - 1);
 					strncpy(ses->map->color[index], arg2, COLOR_SIZE - 1);
 				}
 				}
-				get_highlight_codes(ses, ses->map->color[index], buf);
+				get_color_names(ses, ses->map->color[index], buf);
 
 
 				show_message(ses, LIST_COMMAND, "#MAP COLOR %s%10s\e[0m SET TO {%s}", buf, map_color_table[index].name, ses->map->color[index]);
 				show_message(ses, LIST_COMMAND, "#MAP COLOR %s%10s\e[0m SET TO {%s}", buf, map_color_table[index].name, ses->map->color[index]);
 
 
@@ -208,7 +216,7 @@ DO_MAP(map_color)
 	{
 	{
 		for (index = 0 ; map_color_table[index].name ; index++)
 		for (index = 0 ; map_color_table[index].name ; index++)
 		{
 		{
-			get_highlight_codes(ses, ses->map->color[index], buf);
+			get_color_names(ses, ses->map->color[index], buf);
 
 
 			show_message(ses, LIST_COMMAND, "#MAP COLOR %s%10s\e[0m SET TO {%s}", buf, map_color_table[index].name, ses->map->color[index]);
 			show_message(ses, LIST_COMMAND, "#MAP COLOR %s%10s\e[0m SET TO {%s}", buf, map_color_table[index].name, ses->map->color[index]);
 		}
 		}
@@ -265,7 +273,7 @@ DO_MAP(map_delete)
 
 
 		if (room == 0)
 		if (room == 0)
 		{
 		{
-			show_error(ses, LIST_COMMAND, "#MAP DELETE {%d} - No room with that vnum found", arg1);
+			show_error(ses, LIST_COMMAND, "#MAP DELETE {%s} - No room with that vnum found", arg1);
 
 
 			return;
 			return;
 		}
 		}
@@ -1447,7 +1455,7 @@ DO_MAP(map_map)
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN);
-	arg = sub_arg_in_braces(ses, arg, arg4, GET_ONE, SUB_VAR|SUB_FUN);
+	arg = sub_arg_in_braces(ses, arg, arg4, GET_ALL, SUB_VAR|SUB_FUN);
 
 
 	push_call("map_map(%p,%p)",ses,arg);
 	push_call("map_map(%p,%p)",ses,arg);
 
 
@@ -1485,18 +1493,24 @@ DO_MAP(map_map)
 		{
 		{
 			case 'a':
 			case 'a':
 			case 'A':
 			case 'A':
+
 				strcpy(arg3, "APPEND");
 				strcpy(arg3, "APPEND");
 
 
 				logfile = fopen(arg4, "a");
 				logfile = fopen(arg4, "a");
 
 
-				if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
-				{
-					fseek(logfile, 0, SEEK_END);
+				loginit(ses, logfile, LOG_FLAG_APPEND | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
 
 
-					if (ftell(logfile) == 0)
-					{
-						write_html_header(ses, logfile);
-					}
+				break;
+
+			case 'd':
+			case 'D':
+				strcpy(arg3, "DRAW");
+
+				if (*arg4 == 0)
+				{
+					show_error(ses, LIST_COMMAND, "#SYNTAX: #MAP MAP {%s} {%s} {%s} {square}", arg1, arg2, arg3);
+					pop_call();
+					return;
 				}
 				}
 				break;
 				break;
 
 
@@ -1506,10 +1520,8 @@ DO_MAP(map_map)
 
 
 				logfile = fopen(arg4, "w");
 				logfile = fopen(arg4, "w");
 
 
-				if (HAS_BIT(ses->flags, SES_FLAG_LOGHTML))
-				{
-					write_html_header(ses, logfile);
-				}
+				loginit(ses, logfile, LOG_FLAG_OVERWRITE | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
+
 				break;
 				break;
 
 
 			case 'l':
 			case 'l':
@@ -1523,10 +1535,11 @@ DO_MAP(map_map)
 				break;
 				break;
 
 
 			default:
 			default:
-				show_error(ses, LIST_COMMAND, "#SYNTAX: #MAP MAP {rows} {cols} {append|write|list|variable} {name}");
+				show_error(ses, LIST_COMMAND, "#SYNTAX: #MAP MAP {rows} {cols} {append|overwrite|list|variable} {name}");
 				pop_call();
 				pop_call();
 				return;
 				return;
 		}
 		}
+
 		if (*arg4 == 0)
 		if (*arg4 == 0)
 		{
 		{
 			show_error(ses, LIST_COMMAND, "#SYNTAX: #MAP MAP {%s} {%s} {%s} {name}", arg1, arg2, arg3);
 			show_error(ses, LIST_COMMAND, "#SYNTAX: #MAP MAP {%s} {%s} {%s} {name}", arg1, arg2, arg3);
@@ -1593,32 +1606,19 @@ DO_MAP(map_map)
 					str_cat(&gtd->buf, draw_room(ses, ses->map->grid_rooms[x + map_grid_x * y], line, x, y));
 					str_cat(&gtd->buf, draw_room(ses, ses->map->grid_rooms[x + map_grid_x * y], line, x, y));
 				}
 				}
 
 
-/*				if (*ses->map->color[MAP_COLOR_BACK] == 0)
-				{
-					for (x = strlen(buf) - 1 ; x > 0 ; x--)
-					{
-						if (buf[x] != ' ')
-						{
-							break;
-						}
-					}
-					buf[x+1] = 0;
-					strcat(buf, "<088>");
-				}
-*/
 				str_clone(&gtd->out, gtd->buf);
 				str_clone(&gtd->out, gtd->buf);
 
 
 				substitute(ses, gtd->buf, gtd->out, SUB_COL|SUB_CMP|SUB_LIT);
 				substitute(ses, gtd->buf, gtd->out, SUB_COL|SUB_CMP|SUB_LIT);
 
 
 				if (logfile)
 				if (logfile)
 				{
 				{
-					logit(ses, gtd->out, logfile, TRUE);
+					logit(ses, gtd->out, logfile, LOG_FLAG_LINEFEED);
 				}
 				}
 				else if (*arg3 == 'L')
 				else if (*arg3 == 'L')
 				{
 				{
 					cat_sprintf(arg1, "{%02d}{%s}", ++row, gtd->out);
 					cat_sprintf(arg1, "{%02d}{%s}", ++row, gtd->out);
 				}
 				}
-				else if (*arg3 == 'V')
+				else if (*arg3 == 'V' || *arg3 == 'D')
 				{
 				{
 					cat_sprintf(arg1, "%s\n", gtd->out);
 					cat_sprintf(arg1, "%s\n", gtd->out);
 				}
 				}
@@ -1642,19 +1642,6 @@ DO_MAP(map_map)
 					str_cat(&gtd->buf, draw_room(ses, ses->map->grid_rooms[x + map_grid_x * y], line, x, y));
 					str_cat(&gtd->buf, draw_room(ses, ses->map->grid_rooms[x + map_grid_x * y], line, x, y));
 				}
 				}
 
 
-/*				if (*ses->map->color[MAP_COLOR_BACK] == 0)
-				{
-					for (x = strlen(buf) - 1 ; x > 0 ; x--)
-					{
-						if (buf[x] != ' ')
-						{
-							break;
-						}
-					}
-					buf[x+1] = 0;
-					str_cat(&buf, "<088>");
-				}
-*/
 				str_clone(&gtd->out, gtd->buf);
 				str_clone(&gtd->out, gtd->buf);
 
 
 				substitute(ses, gtd->buf, gtd->out, SUB_COL|SUB_CMP|SUB_LIT);
 				substitute(ses, gtd->buf, gtd->out, SUB_COL|SUB_CMP|SUB_LIT);
@@ -1667,7 +1654,7 @@ DO_MAP(map_map)
 				{
 				{
 					cat_sprintf(arg1, "{%02d}{%s\e[0m}", ++row, gtd->out);
 					cat_sprintf(arg1, "{%02d}{%s\e[0m}", ++row, gtd->out);
 				}
 				}
-				else if (*arg3 == 'V')
+				else if (*arg3 == 'V' || *arg3 == 'D')
 				{
 				{
 					cat_sprintf(arg1, "%s\e[0m\n", gtd->out);
 					cat_sprintf(arg1, "%s\e[0m\n", gtd->out);
 				}
 				}
@@ -1688,22 +1675,6 @@ DO_MAP(map_map)
 			{
 			{
 				str_cat(&gtd->buf, draw_room(ses, ses->map->grid_rooms[x + map_grid_x * y], 0, x, y));
 				str_cat(&gtd->buf, draw_room(ses, ses->map->grid_rooms[x + map_grid_x * y], 0, x, y));
 			}
 			}
-/*
-			if (*ses->map->color[MAP_COLOR_BACK] == 0)
-			{
-				for (x = strlen(buf) - 1 ; x > 0 ; x--)
-				{
-					if (buf[x] != ' ')
-					{
-						break;
-					}
-				}
-				buf[x+1] = 0;
-
-				strcat(buf, "<088>");
-			}
-*/
-			str_clone(&gtd->out, gtd->buf);
 
 
 			substitute(ses, gtd->buf, gtd->out, SUB_COL|SUB_CMP|SUB_LIT);
 			substitute(ses, gtd->buf, gtd->out, SUB_COL|SUB_CMP|SUB_LIT);
 
 
@@ -1715,7 +1686,7 @@ DO_MAP(map_map)
 			{
 			{
 				cat_sprintf(arg1, "{%02d}{%s}", ++row, gtd->out);
 				cat_sprintf(arg1, "{%02d}{%s}", ++row, gtd->out);
 			}
 			}
-			else if (*arg3 == 'V')
+			else if (*arg3 == 'V' || *arg3 == 'D')
 			{
 			{
 				cat_sprintf(arg1, "%s\n", gtd->out);
 				cat_sprintf(arg1, "%s\n", gtd->out);
 			}
 			}
@@ -1730,6 +1701,10 @@ DO_MAP(map_map)
 	{
 	{
 		fclose(logfile);
 		fclose(logfile);
 	}
 	}
+	else if (*arg3 == 'D')
+	{
+		draw_map(ses, 1, 2, 3, 4, 5, 6, 7, arg4, arg2, arg1);
+	}
 	else if (*arg3 == 'L')
 	else if (*arg3 == 'L')
 	{
 	{
 		set_nest_node(ses->list[LIST_VARIABLE], arg4, "%s", arg1);
 		set_nest_node(ses->list[LIST_VARIABLE], arg4, "%s", arg1);
@@ -1795,7 +1770,7 @@ DO_MAP(map_offset)
 
 
 	if (ses->map->bot_row == 0)
 	if (ses->map->bot_row == 0)
 	{
 	{
-		ses->map->bot_row = ses->top_row;
+		ses->map->bot_row = ses->top_row - 1;
 	}
 	}
 	else if (ses->map->bot_row < 0)
 	else if (ses->map->bot_row < 0)
 	{
 	{
@@ -1833,7 +1808,7 @@ DO_MAP(map_read)
 		return;
 		return;
 	}
 	}
 
 
-	gtd->quiet++;
+	gtd->quiet_level++;
 
 
 	if (fgets(buffer, BUFFER_SIZE - 1, myfile))
 	if (fgets(buffer, BUFFER_SIZE - 1, myfile))
 	{
 	{
@@ -1857,7 +1832,7 @@ DO_MAP(map_read)
 		}
 		}
 		else
 		else
 		{
 		{
-			gtd->quiet--;
+			gtd->quiet_level--;
 
 
 			show_error(ses, LIST_COMMAND, "#MAP READ {%s}: INVALID START OF FILE. ABORTING READ..", file);
 			show_error(ses, LIST_COMMAND, "#MAP READ {%s}: INVALID START OF FILE. ABORTING READ..", file);
 
 
@@ -1868,7 +1843,7 @@ DO_MAP(map_read)
 	}
 	}
 	else
 	else
 	{
 	{
-		gtd->quiet--;
+		gtd->quiet_level--;
 
 
 		show_error(ses, LIST_COMMAND, "#MAP: INVALID READ ON LINE %d. ABORTING READ..", line);
 		show_error(ses, LIST_COMMAND, "#MAP: INVALID READ ON LINE %d. ABORTING READ..", line);
 
 
@@ -1901,7 +1876,7 @@ DO_MAP(map_read)
 				switch (buffer[1])
 				switch (buffer[1])
 				{
 				{
 					case ' ':
 					case ' ':
-						gtd->quiet--;
+						gtd->quiet_level--;
 
 
 						show_error(ses, LIST_COMMAND, "#MAP: INVALID COMMAND {%d} {%s} ON LINE %d. ABORTING READ..", buffer[0], buffer, line);
 						show_error(ses, LIST_COMMAND, "#MAP: INVALID COMMAND {%d} {%s} ON LINE %d. ABORTING READ..", buffer[0], buffer, line);
 
 
@@ -1967,7 +1942,7 @@ DO_MAP(map_read)
 				break;
 				break;
 
 
 			default:
 			default:
-				gtd->quiet--;
+				gtd->quiet_level--;
 
 
 				show_error(ses, LIST_COMMAND, "#MAP: INVALID COMMAND {%d} {%s} ON LINE %d. ABORTING READ..", buffer[0], buffer, line);
 				show_error(ses, LIST_COMMAND, "#MAP: INVALID COMMAND {%d} {%s} ON LINE %d. ABORTING READ..", buffer[0], buffer, line);
 
 
@@ -1979,7 +1954,7 @@ DO_MAP(map_read)
 		}
 		}
 	}
 	}
 
 
-	gtd->quiet--;
+	gtd->quiet_level--;
 
 
 	fclose(myfile);
 	fclose(myfile);
 
 
@@ -2080,11 +2055,12 @@ DO_MAP(map_return)
 
 
 DO_MAP(map_roomflag)
 DO_MAP(map_roomflag)
 {
 {
-	char buf[BUFFER_SIZE];
+	char buf[BUFFER_SIZE], *str, arg3[BUFFER_SIZE];
 	int flag = 0;
 	int flag = 0;
 
 
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
-	arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
+	arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
+	arg = sub_arg_in_braces(ses, arg, arg3, GET_ALL, SUB_VAR|SUB_FUN);
 
 
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
@@ -2099,9 +2075,11 @@ DO_MAP(map_roomflag)
 		return;
 		return;
 	}
 	}
 
 
-	while (*arg1)
+	str = arg1;
+
+	while (*str)
 	{
 	{
-		arg1 = get_arg_in_braces(ses, arg1, buf, GET_ONE);
+		str = get_arg_in_braces(ses, str, buf, GET_ONE);
 
 
 		if (is_abbrev(buf, "avoid"))
 		if (is_abbrev(buf, "avoid"))
 		{
 		{
@@ -2141,8 +2119,11 @@ DO_MAP(map_roomflag)
 
 
 			return;
 			return;
 		}
 		}
-		
-		if (*arg1 == COMMAND_SEPARATOR) arg1++;
+
+		if (*str == COMMAND_SEPARATOR)
+		{
+			str++;
+		}
 	}
 	}
 
 
 	if (*arg2 == 0)
 	if (*arg2 == 0)
@@ -2157,9 +2138,21 @@ DO_MAP(map_roomflag)
 	{
 	{
 		DEL_BIT(ses->map->room_list[ses->map->in_room]->flags, flag);
 		DEL_BIT(ses->map->room_list[ses->map->in_room]->flags, flag);
 	}
 	}
+	else if (is_abbrev(arg2, "GET"))
+	{
+		if (*arg3 == 0)
+		{
+			show_error(ses, LIST_COMMAND, "#SYNTAX #MAP ROOMFLAG {%s} {GET} {<VARIABLE>}.", buf);
+		}
+		else
+		{
+			set_nest_node(ses->list[LIST_VARIABLE], arg3, "%d", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, flag));
+		}
+		return;
+	}
 	else
 	else
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX #MAP ROOMFLAG {%s} {[ON|OFF]}.", buf);
+		show_error(ses, LIST_COMMAND, "#SYNTAX #MAP ROOMFLAG {%s} {[GET|ON|OFF]}.", buf);
 	}
 	}
 
 
 
 
@@ -2513,7 +2506,28 @@ DO_MAP(map_unlink)
 
 
 DO_MAP(map_update)
 DO_MAP(map_update)
 {
 {
-	show_message(ses, LIST_COMMAND, "#MAP UPDATE: OK.");
+	if (ses->map == NULL)
+	{
+		show_message(ses, LIST_COMMAND, "#MAP UPDATE: NO MAP DATA.");
+	}
+	else if (ses->map->room_list[ses->map->in_room] == NULL)
+	{
+		show_message(ses, LIST_COMMAND, "#MAP UPDATE: NOT INSIDE MAP.");
+	}
+	else if (!HAS_BIT(ses->map->flags, MAP_FLAG_VTMAP))
+	{
+		show_message(ses, LIST_COMMAND, "#MAP UPDATE: VTMAP FLAG NOT SET.");
+	}
+	else if (ses != gtd->ses)
+	{
+		show_message(ses, LIST_COMMAND, "#MAP UPDATE: NOT THE ACTIVE SESSION.");
+	}
+	else
+	{
+		show_message(ses, LIST_COMMAND, "#MAP UPDATE: OK.");
+		
+		SET_BIT(ses->flags, SES_FLAG_UPDATEVTMAP);
+	}
 }
 }
 
 
 DO_MAP(map_run)
 DO_MAP(map_run)
@@ -2756,9 +2770,9 @@ void create_map(struct session *ses, char *arg)
 		map_group_table[group].end = legend;
 		map_group_table[group].end = legend;
 	}
 	}
 				
 				
-	gtd->quiet++;
+	gtd->quiet_level++;
 	do_map(ses, "LEGEND RESET");
 	do_map(ses, "LEGEND RESET");
-	gtd->quiet--;
+	gtd->quiet_level--;
 
 
 	pop_call();
 	pop_call();
 	return;
 	return;
@@ -2874,13 +2888,14 @@ void delete_room(struct session *ses, int room, int exits)
 	}
 	}
 }
 }
 
 
-struct exit_data *create_exit(struct session *ses, int room, char *format, ...)
+struct exit_data *create_exit(struct session *ses, int vnum, char *format, ...)
 {
 {
 	struct exit_data *newexit;
 	struct exit_data *newexit;
+	struct room_data *room;
 	va_list args;
 	va_list args;
 	char *arg, buf[BUFFER_SIZE];
 	char *arg, buf[BUFFER_SIZE];
 
 
-	push_call("create_exit(%p,%d,%p)",ses,room,format);
+	push_call("create_exit(%p,%d,%p)",ses,vnum,format);
 
 
 	va_start(args, format);
 	va_start(args, format);
 	vsprintf(buf, format, args);
 	vsprintf(buf, format, args);
@@ -2888,6 +2903,8 @@ struct exit_data *create_exit(struct session *ses, int room, char *format, ...)
 
 
 	newexit = (struct exit_data *) calloc(1, sizeof(struct exit_data));
 	newexit = (struct exit_data *) calloc(1, sizeof(struct exit_data));
 
 
+	room = ses->map->room_list[vnum];
+
 	arg = buf;
 	arg = buf;
 
 
 	arg = get_arg_in_braces(ses, arg, buf, GET_ONE);	newexit->vnum   = atoi(buf);
 	arg = get_arg_in_braces(ses, arg, buf, GET_ONE);	newexit->vnum   = atoi(buf);
@@ -2903,17 +2920,25 @@ struct exit_data *create_exit(struct session *ses, int room, char *format, ...)
 		newexit->dir = get_exit_dir(ses, newexit->name);
 		newexit->dir = get_exit_dir(ses, newexit->name);
 	}
 	}
 
 
+	newexit->grid = get_exit_grid(ses, newexit->dir);
+
+	if (room->exit_grid[newexit->grid] == NULL)
+	{
+		room->exit_grid[newexit->grid] = newexit;
+	}
+
 	if (newexit->weight <= 0)
 	if (newexit->weight <= 0)
 	{
 	{
 		newexit->weight = 1;
 		newexit->weight = 1;
 	}
 	}
 
 
-	LINK(newexit, ses->map->room_list[room]->f_exit, ses->map->room_list[room]->l_exit);
+	LINK(newexit, room->f_exit, room->l_exit);
+
+	room->exit_size++;
 
 
-	ses->map->room_list[room]->exit_size++;
-	SET_BIT(ses->map->room_list[room]->exit_dirs, (1LL << newexit->dir));
+	SET_BIT(room->exit_dirs, (1LL << newexit->dir));
 
 
-	show_message(ses, LIST_COMMAND, "#MAP CREATE EXIT %5d {%s} {%s}.", newexit->vnum, newexit->name, newexit->cmd);
+	show_message(ses, LIST_COMMAND, "#MAP CREATE EXIT {%s} {%s} TO ROOM %d.", newexit->name, newexit->cmd, newexit->vnum);
 
 
 	pop_call();
 	pop_call();
 	return newexit;
 	return newexit;
@@ -2948,23 +2973,69 @@ int get_exit_dir(struct session *ses, char *arg)
 	}
 	}
 }
 }
 
 
+int get_exit_grid(struct session *ses, int dir)
+{
+	switch (dir)
+	{
+		case 0:
+			return EXIT_GRID_0;
+		case MAP_EXIT_N:
+			return EXIT_GRID_N;
+		case MAP_EXIT_E:
+			return EXIT_GRID_E;
+		case MAP_EXIT_S:
+			return EXIT_GRID_S;
+		case MAP_EXIT_W:
+			return EXIT_GRID_W;
+		case MAP_EXIT_N|MAP_EXIT_E:
+			return EXIT_GRID_NE;
+		case MAP_EXIT_N|MAP_EXIT_W:
+			return EXIT_GRID_NW;
+		case MAP_EXIT_S|MAP_EXIT_E:
+			return EXIT_GRID_SE;
+		case MAP_EXIT_S|MAP_EXIT_W:
+			return EXIT_GRID_SW;
+	}
+
+	if (HAS_BIT(dir, MAP_EXIT_D))
+	{
+		return EXIT_GRID_D;
+	}
+
+	if (HAS_BIT(dir, MAP_EXIT_U))
+	{
+		return EXIT_GRID_U;
+	}
+
+	return EXIT_GRID_0;
+}
+
 int get_room_exits(struct session *ses, int room)
 int get_room_exits(struct session *ses, int room)
 {
 {
 	return ses->map->room_list[room]->exit_size;
 	return ses->map->room_list[room]->exit_size;
 }
 }
 
 
-void set_room_exits(struct session *ses, int room)
+void set_room_exits(struct session *ses, int vnum)
 {
 {
 	struct exit_data *exit;
 	struct exit_data *exit;
+	struct room_data *room;
 
 
-	ses->map->room_list[room]->exit_dirs = 0;
-	ses->map->room_list[room]->exit_size = 0;
+	room = ses->map->room_list[vnum];
 
 
-	for (exit = ses->map->room_list[room]->f_exit ; exit ; exit = exit->next)
+	room->exit_dirs = 0;
+	room->exit_size = 0;
+
+	memset(room->exit_grid, 0, sizeof(struct exit_data *) * 11);
+
+	for (exit = room->f_exit ; exit ; exit = exit->next)
 	{
 	{
-		SET_BIT(ses->map->room_list[room]->exit_dirs, 1LL << exit->dir);
+		SET_BIT(room->exit_dirs, 1LL << exit->dir);
 
 
-		ses->map->room_list[room]->exit_size++;
+		if (room->exit_grid[exit->grid] == NULL)
+		{
+			room->exit_grid[exit->grid] = exit;
+		}
+		room->exit_size++;
 	}
 	}
 }
 }
 
 
@@ -3356,7 +3427,9 @@ void show_vtmap(struct session *ses)
 		cols    = gtd->screen->cols;
 		cols    = gtd->screen->cols;
 	}
 	}
 
 
-	printf("\e[%d;%d;%d;%d${", top_row, top_col, bot_row, bot_col);
+	erase_square(ses, top_row, top_col, bot_row, bot_col);
+
+//	printf("\e[%d;%d;%d;%d${", top_row, top_col, bot_row, bot_col);
 
 
 	if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS))
 	if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS))
 	{
 	{
@@ -3489,13 +3562,19 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 	static char buf[201], *room_color, room_left[101], room_right[101];
 	static char buf[201], *room_color, room_left[101], room_right[101];
 	int index, flags, exits, exit1, exit2, room1, room2, offset;
 	int index, flags, exits, exit1, exit2, room1, room2, offset;
 
 
-	push_call("draw_room(%p,%p,%p,%d,%d)",ses,room,line,x,y);
+	push_call("draw_room(%p,%p,%d,%d,%d)",ses,room,line,x,y);
 
 
 	offset = HAS_BIT(ses->flags, SES_FLAG_UTF8) ? LEGEND_UNICODE : LEGEND_ASCII;
 	offset = HAS_BIT(ses->flags, SES_FLAG_UTF8) ? LEGEND_UNICODE : LEGEND_ASCII;
 
 
+	room_color = ses->map->color[MAP_COLOR_ROOM];
+
 	if (room)
 	if (room)
 	{
 	{
-		if (*room->color)
+		if (HAS_BIT(room->flags, ROOM_FLAG_PATH) && room->search_stamp == ses->map->search->stamp)
+		{
+			room_color = ses->map->color[MAP_COLOR_PATH];
+		}
+		else if (*room->color)
 		{
 		{
 			room_color = room->color;
 			room_color = room->color;
 		}
 		}
@@ -3521,18 +3600,10 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 			{
 			{
 				room_color = ses->map->color[MAP_COLOR_AVOID];
 				room_color = ses->map->color[MAP_COLOR_AVOID];
 			}
 			}
-			else if (HAS_BIT(room->flags, ROOM_FLAG_PATH) && room->search_stamp == ses->map->search->stamp)
-			{
-				room_color = ses->map->color[MAP_COLOR_PATH];
-			}
 			else if (HAS_BIT(ses->map->flags, MAP_FLAG_SYMBOLGRAPHICS))
 			else if (HAS_BIT(ses->map->flags, MAP_FLAG_SYMBOLGRAPHICS))
 			{
 			{
 				room_color = ses->map->color[MAP_COLOR_SYMBOL];
 				room_color = ses->map->color[MAP_COLOR_SYMBOL];
 			}
 			}
-			else
-			{
-				room_color = ses->map->color[MAP_COLOR_ROOM];
-			}
 		}
 		}
 
 
 		if (HAS_BIT(room->flags, ROOM_FLAG_CURVED))
 		if (HAS_BIT(room->flags, ROOM_FLAG_CURVED))
@@ -3554,36 +3625,36 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 
 
 				DEL_BIT(exits, MAP_EXIT_U|MAP_EXIT_D);
 				DEL_BIT(exits, MAP_EXIT_U|MAP_EXIT_D);
 
 
-					switch (exits)
-					{
-						case MAP_EXIT_N:
-							index = 24;
-							break;
-						case MAP_EXIT_N+MAP_EXIT_E:
-							index = 25;
-							break;
-						case MAP_EXIT_E:
-							index = 26;
-							break;
-						case MAP_EXIT_S+MAP_EXIT_E:
-							index = 27;
-							break;
-						case MAP_EXIT_S:
-							index = 28;
-							break;
-						case MAP_EXIT_W+MAP_EXIT_S:
-							index = 29;
-							break;
-						case MAP_EXIT_W:
-							index = 30;
-							break;
-						case MAP_EXIT_W+MAP_EXIT_N:
-							index = 31;
-							break;
-						default:
-							index = 17;
-							break;
-					}
+				switch (exits)
+				{
+					case MAP_EXIT_N:
+						index = 24;
+						break;
+					case MAP_EXIT_N+MAP_EXIT_E:
+						index = 25;
+						break;
+					case MAP_EXIT_E:
+						index = 26;
+						break;
+					case MAP_EXIT_S+MAP_EXIT_E:
+						index = 27;
+						break;
+					case MAP_EXIT_S:
+						index = 28;
+						break;
+					case MAP_EXIT_W+MAP_EXIT_S:
+						index = 29;
+						break;
+					case MAP_EXIT_W:
+						index = 30;
+						break;
+					case MAP_EXIT_W+MAP_EXIT_N:
+						index = 31;
+						break;
+					default:
+						index = 17;
+						break;
+				}
 			}
 			}
 			else
 			else
 			{
 			{
@@ -3603,14 +3674,16 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 
 
 		exit_n = exit_nw = exit_w = 0;
 		exit_n = exit_nw = exit_w = 0;
 
 
-		if (room && HAS_BIT(room->exit_dirs, MAP_DIR_N))
+		if (room && room->exit_grid[EXIT_GRID_N])
 		{
 		{
 			SET_BIT(exit_n, MAP_DIR_N);
 			SET_BIT(exit_n, MAP_DIR_N);
 		}
 		}
+
 		if (room_n && HAS_BIT(room_n->exit_dirs, MAP_DIR_S))
 		if (room_n && HAS_BIT(room_n->exit_dirs, MAP_DIR_S))
 		{
 		{
 			SET_BIT(exit_n, MAP_DIR_S);
 			SET_BIT(exit_n, MAP_DIR_S);
 		}
 		}
+
 		if (room_n && HAS_BIT(room_n->exit_dirs, MAP_DIR_D))
 		if (room_n && HAS_BIT(room_n->exit_dirs, MAP_DIR_D))
 		{
 		{
 			SET_BIT(exit_n, MAP_DIR_D);
 			SET_BIT(exit_n, MAP_DIR_D);
@@ -3620,6 +3693,7 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 		{
 		{
 			SET_BIT(exit_nw, MAP_DIR_SE);
 			SET_BIT(exit_nw, MAP_DIR_SE);
 		}
 		}
+
 		if (room_n && HAS_BIT(room_n->exit_dirs, MAP_DIR_SW))
 		if (room_n && HAS_BIT(room_n->exit_dirs, MAP_DIR_SW))
 		{
 		{
 			SET_BIT(exit_nw, MAP_DIR_NE);
 			SET_BIT(exit_nw, MAP_DIR_NE);
@@ -3628,18 +3702,20 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 		{
 		{
 			SET_BIT(exit_nw, MAP_DIR_NW);
 			SET_BIT(exit_nw, MAP_DIR_NW);
 		}
 		}
+
 		if (room_w && HAS_BIT(room_w->exit_dirs, MAP_DIR_NE))
 		if (room_w && HAS_BIT(room_w->exit_dirs, MAP_DIR_NE))
 		{
 		{
 			SET_BIT(exit_nw, MAP_DIR_SW);
 			SET_BIT(exit_nw, MAP_DIR_SW);
 		}
 		}
 
 
-		if (room && HAS_BIT(room->exit_dirs, MAP_DIR_W))
+		if (room && room->exit_grid[EXIT_GRID_W])
 		{
 		{
-			SET_BIT(exit_w, MAP_DIR_W);
+			SET_BIT(exit_w, MAP_DIR_E);
 		}
 		}
-		if (room_w && HAS_BIT(room_w->exit_dirs, MAP_DIR_E))
+
+		if (room_w && room_w->exit_grid[EXIT_GRID_E])
 		{
 		{
-			SET_BIT(exit_w, MAP_DIR_E);
+			SET_BIT(exit_w, MAP_DIR_W);
 		}
 		}
 
 
 		sprintf(buf, "%s", ses->map->color[MAP_COLOR_EXIT]);
 		sprintf(buf, "%s", ses->map->color[MAP_COLOR_EXIT]);
@@ -3746,9 +3822,9 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 						break;
 						break;
 				}
 				}
 
 
-				if (room && HAS_BIT(room->exit_dirs, MAP_DIR_U))
+				if (room && room->exit_grid[EXIT_GRID_U])
 				{
 				{
-					flags = dir_flags(ses, room->vnum, MAP_EXIT_U);
+					flags = room->exit_grid[EXIT_GRID_U]->flags;
 
 
 					if (HAS_BIT(flags, EXIT_FLAG_AVOID))
 					if (HAS_BIT(flags, EXIT_FLAG_AVOID))
 					{
 					{
@@ -3777,7 +3853,14 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 			case 2:
 			case 2:
 				if (room == NULL)
 				if (room == NULL)
 				{
 				{
-					strcpy(buf, "     ");
+					if (HAS_BIT(exit_w, MAP_DIR_W))
+					{
+						sprintf(buf, "%s→    ", ses->map->color[MAP_COLOR_EXIT]);
+					}
+					else
+					{
+						strcpy(buf, "     ");
+					}
 					pop_call();
 					pop_call();
 					return buf;
 					return buf;
 				}
 				}
@@ -3788,13 +3871,20 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 						strcpy(buf, "  ");
 						strcpy(buf, "  ");
 						break;
 						break;
 					case MAP_DIR_W:
 					case MAP_DIR_W:
-						sprintf(buf, "%s ", ses->map->color[MAP_COLOR_EXIT]);
+						sprintf(buf, "%s ", ses->map->color[MAP_COLOR_EXIT]);
 						break;
 						break;
 					case MAP_DIR_E:
 					case MAP_DIR_E:
-						sprintf(buf, "%s ", ses->map->color[MAP_COLOR_EXIT]);
+						sprintf(buf, "%s ", ses->map->color[MAP_COLOR_EXIT]);
 						break;
 						break;
 					case MAP_DIR_W|MAP_DIR_E:
 					case MAP_DIR_W|MAP_DIR_E:
-						sprintf(buf, "%s‒‒", ses->map->color[MAP_COLOR_EXIT]);
+						if (room->exit_grid[EXIT_GRID_W]->vnum == room_w->vnum && room_w->exit_grid[EXIT_GRID_E]->vnum == room->vnum)
+						{
+							sprintf(buf, "%s‒‒", ses->map->color[MAP_COLOR_EXIT]);
+						}
+						else
+						{
+							sprintf(buf, "%s→←", ses->map->color[MAP_COLOR_EXIT]);
+						}
 						break;
 						break;
 					default:
 					default:
 						strcat(buf, "??");
 						strcat(buf, "??");
@@ -4101,7 +4191,7 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 				break;
 				break;
 
 
 			case 2:
 			case 2:
-				if (!HAS_BIT(room->flags, ROOM_FLAG_VOID) && !HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS))
+				if (!HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS))
 				{
 				{
 					strcat(buf, HAS_BIT(room->exit_dirs, MAP_DIR_W) ? "-" : " ");
 					strcat(buf, HAS_BIT(room->exit_dirs, MAP_DIR_W) ? "-" : " ");
 				}
 				}
@@ -4157,7 +4247,7 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 					}
 					}
 				}
 				}
 
 
-				if (HAS_BIT(room->flags, ROOM_FLAG_VOID) || !HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS))
+				if (!HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS))
 				{
 				{
 					strcat(buf, HAS_BIT(room->exit_dirs, MAP_DIR_E) ? "--" : "  ");
 					strcat(buf, HAS_BIT(room->exit_dirs, MAP_DIR_E) ? "--" : "  ");
 				}
 				}
@@ -4271,22 +4361,18 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 		if (HAS_BIT(room->exit_dirs, MAP_DIR_NW))
 		if (HAS_BIT(room->exit_dirs, MAP_DIR_NW))
 		{
 		{
 			SET_BIT(exit1, 1 << 1);
 			SET_BIT(exit1, 1 << 1);
-			SET_BIT(exits, MAP_EXIT_NW);
 		}
 		}
 		if (HAS_BIT(room->exit_dirs, MAP_DIR_NE))
 		if (HAS_BIT(room->exit_dirs, MAP_DIR_NE))
 		{
 		{
 			SET_BIT(exit2, 1 << 1);
 			SET_BIT(exit2, 1 << 1);
-			SET_BIT(exits, MAP_EXIT_NE);
 		}
 		}
 		if (HAS_BIT(room->exit_dirs, MAP_DIR_SW))
 		if (HAS_BIT(room->exit_dirs, MAP_DIR_SW))
 		{
 		{
 			SET_BIT(exit1, 1 << 3);
 			SET_BIT(exit1, 1 << 3);
-			SET_BIT(exits, MAP_EXIT_SW);
 		}
 		}
 		if (HAS_BIT(room->exit_dirs, MAP_DIR_SE))
 		if (HAS_BIT(room->exit_dirs, MAP_DIR_SE))
 		{
 		{
 			SET_BIT(exit2, 1 << 3);
 			SET_BIT(exit2, 1 << 3);
-			SET_BIT(exits, MAP_EXIT_SE);
 		}
 		}
 
 
 		room1 = exit1 + LEGEND_MUDFONT_NWS;
 		room1 = exit1 + LEGEND_MUDFONT_NWS;
@@ -4300,22 +4386,22 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 
 
 		if (HAS_BIT(room->flags, ROOM_FLAG_CURVED))
 		if (HAS_BIT(room->flags, ROOM_FLAG_CURVED))
 		{
 		{
-			switch (exits)
+			switch (room->exit_dirs)
 			{
 			{
-				case MAP_EXIT_N|MAP_EXIT_E:
-				case MAP_EXIT_N|MAP_EXIT_SE:
+				case MAP_DIR_N|MAP_DIR_E:
+				case MAP_DIR_N|MAP_DIR_SE:
 					room1 = LEGEND_MUDFONT_CURVED + 0;
 					room1 = LEGEND_MUDFONT_CURVED + 0;
 					break;
 					break;
-				case MAP_EXIT_S|MAP_EXIT_E:
-				case MAP_EXIT_S|MAP_EXIT_NE:
+				case MAP_DIR_S|MAP_DIR_E:
+				case MAP_DIR_S|MAP_DIR_NE:
 					room1 = LEGEND_MUDFONT_CURVED + 1;
 					room1 = LEGEND_MUDFONT_CURVED + 1;
 					break;
 					break;
-				case MAP_EXIT_S|MAP_EXIT_W:
-				case MAP_EXIT_S|MAP_EXIT_NW:
+				case MAP_DIR_S|MAP_DIR_W:
+				case MAP_DIR_S|MAP_DIR_NW:
 					room2 = LEGEND_MUDFONT_CURVED + 2;
 					room2 = LEGEND_MUDFONT_CURVED + 2;
 					break;
 					break;
-				case MAP_EXIT_N|MAP_EXIT_W:
-				case MAP_EXIT_N|MAP_EXIT_SW:
+				case MAP_DIR_N|MAP_DIR_W:
+				case MAP_DIR_N|MAP_DIR_SW:
 					room2 = LEGEND_MUDFONT_CURVED + 3;
 					room2 = LEGEND_MUDFONT_CURVED + 3;
 					break;
 					break;
 			}
 			}
@@ -4339,18 +4425,18 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 			{
 			{
 				if (HAS_BIT(room->flags, ROOM_FLAG_CURVED))
 				if (HAS_BIT(room->flags, ROOM_FLAG_CURVED))
 				{
 				{
-					switch (exits)
+					switch (room->exit_dirs)
 					{
 					{
-						case MAP_EXIT_N|MAP_EXIT_E:
+						case MAP_DIR_N|MAP_DIR_E:
 							exits = 16 + 4;
 							exits = 16 + 4;
 							break;
 							break;
-						case MAP_EXIT_S|MAP_EXIT_E:
+						case MAP_DIR_S|MAP_DIR_E:
 							exits = 16 + 5;
 							exits = 16 + 5;
 							break;
 							break;
-						case MAP_EXIT_S|MAP_EXIT_W:
+						case MAP_DIR_S|MAP_DIR_W:
 							exits = 16 + 6;
 							exits = 16 + 6;
 							break;
 							break;
-						case MAP_EXIT_N|MAP_EXIT_W:
+						case MAP_DIR_N|MAP_DIR_W:
 							exits = 16 + 7;
 							exits = 16 + 7;
 							break;
 							break;
 					}
 					}
@@ -4449,7 +4535,14 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 
 
 	arg = sub_arg_in_braces(ses, tmp, buf, GET_ALL, SUB_VAR|SUB_FUN); // name
 	arg = sub_arg_in_braces(ses, tmp, buf, GET_ALL, SUB_VAR|SUB_FUN); // name
 
 
-	ses->map->search->vnum = (int) get_number(ses, buf);
+	if (is_math(ses, buf))
+	{
+		ses->map->search->vnum = (int) get_number(ses, buf);
+	}
+	else
+	{
+		ses->map->search->vnum = 0;
+	}
 
 
 	if (ses->map->search->vnum)
 	if (ses->map->search->vnum)
 	{
 	{
@@ -4491,30 +4584,46 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 
 
 		tmp[0] = 0;
 		tmp[0] = 0;
 
 
-		ses->map->search->exit_dirs = get_number(ses, buf);
+		if (is_math(ses, buf))
+		{
+			ses->map->search->exit_dirs = get_number(ses, buf);
 
 
-		while (*ptb)
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_N))  ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_E))  ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_S))  ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_W))  ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_U))  ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_D))  ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_NE)) ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_NW)) ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_SE)) ses->map->search->exit_size++;
+			if (HAS_BIT(ses->map->search->exit_dirs, MAP_DIR_SW)) ses->map->search->exit_size++;
+		}
+		else
 		{
 		{
-			ptb = get_arg_in_braces(ses, ptb, exit, GET_ONE);
+			while (*ptb)
+			{
+				ptb = get_arg_in_braces(ses, ptb, exit, GET_ONE);
 
 
-			node = search_node_list(ses->list[LIST_PATHDIR], exit);
+				node = search_node_list(ses->list[LIST_PATHDIR], exit);
 
 
-			ses->map->search->exit_size++;
+				ses->map->search->exit_size++;
 
 
-			if (node)
-			{
-				SET_BIT(ses->map->search->exit_dirs, 1LL << atoi(node->arg3));
-			}
-			else
-			{
-				SET_BIT(ses->map->search->exit_dirs, 1); // flag indicates no exits
+				if (node)
+				{
+					SET_BIT(ses->map->search->exit_dirs, 1LL << atoi(node->arg3));
+				}
+				else
+				{
+					SET_BIT(ses->map->search->exit_dirs, 1); // flag indicates no exits
 
 
-				cat_sprintf(tmp, "{%s}", exit);
-			}
+					cat_sprintf(tmp, "{%s}", exit);
+				}
 
 
-			if (*ptb == COMMAND_SEPARATOR)
-			{
-				ptb++;
+				if (*ptb == COMMAND_SEPARATOR)
+				{
+					ptb++;
+				}
 			}
 			}
 		}
 		}
 		ses->map->search->exit_list = strdup(tmp);
 		ses->map->search->exit_list = strdup(tmp);

+ 3 - 1
src/math.c

@@ -109,7 +109,9 @@ long double get_double(struct session *ses, char *str)
 	
 	
 void get_number_string(struct session *ses, char *str, char *result)
 void get_number_string(struct session *ses, char *str, char *result)
 {
 {
-	sprintf(result, "%.*Lf", precision, get_number(ses, str));
+	long double val = get_number(ses, str);
+
+	sprintf(result, "%.*Lf", precision, val);
 }
 }
 
 
 long double mathswitch(struct session *ses, char *left, char *right)
 long double mathswitch(struct session *ses, char *left, char *right)

+ 1 - 1
src/misc.c

@@ -96,7 +96,7 @@ DO_COMMAND(do_echo)
 
 
 			substitute(ses, left, temp, SUB_COL|SUB_ESC);
 			substitute(ses, left, temp, SUB_COL|SUB_ESC);
 
 
-			do_one_prompt(ses, temp, row, 0);
+			split_show(ses, temp, row, 0);
 
 
 			return ses;
 			return ses;
 		}
 		}

+ 14 - 5
src/net.c

@@ -69,7 +69,7 @@ int connect_mud(struct session *ses, char *host, char *port)
 
 
 		if (error)
 		if (error)
 		{
 		{
-			tintin_printf(ses, "#SESSION '%s' COULD NOT CONNECT - UNKNOWN HOST.", ses->name);
+			tintin_printf2(ses, "#SESSION '%s' COULD NOT CONNECT - UNKNOWN HOST.", ses->name);
 
 
 			return -1;
 			return -1;
 		}
 		}
@@ -96,7 +96,7 @@ int connect_mud(struct session *ses, char *host, char *port)
 
 
 		freeaddrinfo(address);
 		freeaddrinfo(address);
 
 
-		return 0;
+		return -1;
 	}
 	}
 
 
 	if (fcntl(sock, F_SETFL, O_NDELAY|O_NONBLOCK) == -1)
 	if (fcntl(sock, F_SETFL, O_NDELAY|O_NONBLOCK) == -1)
@@ -107,12 +107,19 @@ int connect_mud(struct session *ses, char *host, char *port)
 
 
 		freeaddrinfo(address);
 		freeaddrinfo(address);
 
 
-		return 0;
+		return -1;
 	}
 	}
 
 
-	getnameinfo(address->ai_addr, address->ai_addrlen, ip, 100, NULL, 0, NI_NUMERICHOST);
+	error = getnameinfo(address->ai_addr, address->ai_addrlen, ip, 100, NULL, 0, NI_NUMERICHOST);
 
 
-	RESTRING(ses->session_ip, ip);
+	if (error)
+	{
+		syserr_printf(ses, "connect_mud: getnameinfo:");
+	}
+	else
+	{
+		RESTRING(ses->session_ip, ip);
+	}
 
 
 	freeaddrinfo(address);
 	freeaddrinfo(address);
 
 
@@ -126,6 +133,8 @@ int connect_mud(struct session *ses, char *host, char *port)
 	int sock, d;
 	int sock, d;
 	struct sockaddr_in sockaddr;
 	struct sockaddr_in sockaddr;
 
 
+	printf("debug: NO ADDRESS INFO?\n");
+
 	if (sscanf(host, "%d.%d.%d.%d", &d, &d, &d, &d) == 4)
 	if (sscanf(host, "%d.%d.%d.%d", &d, &d, &d, &d) == 4)
 	{
 	{
 		sockaddr.sin_addr.s_addr = inet_addr(host);
 		sockaddr.sin_addr.s_addr = inet_addr(host);

+ 3 - 3
src/parse.c

@@ -849,11 +849,11 @@ void do_one_line(char *line, struct session *ses)
 		check_all_highlights(ses, line, strip);
 		check_all_highlights(ses, line, strip);
 	}
 	}
 
 
-	if (HAS_BIT(ses->flags, SES_FLAG_LOGNEXT))
+	if (HAS_BIT(ses->logmode, LOG_FLAG_NEXT))
 	{
 	{
-		logit(ses, line, ses->lognext_file, TRUE);
+		logit(ses, line, ses->lognext_file, LOG_FLAG_LINEFEED);
 
 
-		DEL_BIT(ses->flags, SES_FLAG_LOGNEXT);
+		DEL_BIT(ses->logmode, LOG_FLAG_NEXT);
 	}
 	}
 	pop_call();
 	pop_call();
 	return;
 	return;

+ 5 - 2
src/port.c

@@ -277,7 +277,10 @@ int port_new(struct session *ses, int sock)
 
 
 	port_printf(ses, "New connection: %s D%d.", new_buddy->ip, new_buddy->fd);
 	port_printf(ses, "New connection: %s D%d.", new_buddy->ip, new_buddy->fd);
 
 
-	announce_support(ses, new_buddy);
+	if (HAS_BIT(ses->flags, SES_FLAG_TELNET))
+	{
+		announce_support(ses, new_buddy);
+	}
 
 
 	check_all_events(ses, SUB_ARG|SUB_SEC, 0, 3, "PORT CONNECTION", new_buddy->name, new_buddy->ip, ntos(new_buddy->port));
 	check_all_events(ses, SUB_ARG|SUB_SEC, 0, 3, "PORT CONNECTION", new_buddy->name, new_buddy->ip, ntos(new_buddy->port));
 
 
@@ -916,7 +919,7 @@ DO_PORT(port_zap)
 
 
 DO_PORT(port_color)
 DO_PORT(port_color)
 {
 {
-	if (*arg1 == 0 || get_highlight_codes(gtd->ses, arg1, arg2) == FALSE)
+	if (*arg1 == 0 || get_color_names(gtd->ses, arg1, arg2) == FALSE)
 	{
 	{
 		port_printf(ses, "Valid colors are:\n\nreset, bold, dim, light, dark, underscore, blink, reverse, black, red, green, yellow, blue, magenta, cyan, white, b black, b red, b green, b yellow, b blue, b magenta, b cyan, b white");
 		port_printf(ses, "Valid colors are:\n\nreset, bold, dim, light, dark, underscore, blink, reverse, black, red, green, yellow, blue, magenta, cyan, white, b black, b red, b green, b yellow, b blue, b magenta, b cyan, b white");
 
 

+ 0 - 197
src/prompt.c

@@ -1,197 +0,0 @@
-/******************************************************************************
-*   This file is part of TinTin++                                             *
-*                                                                             *
-*   Copyright 2004-2019 Igor van den Hoven                                    *
-*                                                                             *
-*   TinTin++ is free software; you can redistribute it and/or modify          *
-*   it under the terms of the GNU General Public License as published by      *
-*   the Free Software Foundation; either version 3 of the License, or         *
-*   (at your option) any later version.                                       *
-*                                                                             *
-*   This program is distributed in the hope that it will be useful,           *
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
-*   GNU General Public License for more details.                              *
-*                                                                             *
-*                                                                             *
-*   You should have received a copy of the GNU General Public License         *
-*   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
-******************************************************************************/
-
-/******************************************************************************
-*                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
-*                                                                             *
-*                      coded by Igor van den Hoven 2004                       *
-******************************************************************************/
-
-#include "tintin.h"
-
-
-DO_COMMAND(do_prompt)
-{
-	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE], arg4[BUFFER_SIZE];
-
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
-	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
-
-
-	if (*arg1 == 0)
-	{
-		show_list(ses->list[LIST_PROMPT], 0);
-	}
-	else if (*arg1 && *arg2 == 0)
-	{
-		if (show_node_with_wild(ses, arg1, ses->list[LIST_PROMPT]) == FALSE)
-		{
-			show_message(ses, LIST_PROMPT, "#PROMPT: NO MATCH(ES) FOUND FOR {%s}.", arg1);
-		}
-	}
-	else
-	{
-		arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN);
-		arg = sub_arg_in_braces(ses, arg, arg4, GET_ONE, SUB_VAR|SUB_FUN);
-
-		update_node_list(ses->list[LIST_PROMPT], arg1, arg2, arg3, arg4);
-
-		show_message(ses, LIST_PROMPT, "#OK. {%s} NOW PROMPTS {%s} @ {%s} {%s}.", arg1, arg2, arg3, arg4);
-	}
-	return ses;
-}
-
-
-DO_COMMAND(do_unprompt)
-{
-	delete_node_with_wild(ses, LIST_PROMPT, arg);
-
-	return ses;
-}
-
-
-void check_all_prompts(struct session *ses, char *original, char *line)
-{
-	struct listroot *root = ses->list[LIST_PROMPT];
-	struct listnode *node;
-
-	if (!HAS_BIT(ses->flags, SES_FLAG_SPLIT))
-	{
-		return;
-	}
-
-	for (root->update = 0 ; root->update < root->used ; root->update++)
-	{
-		if (check_one_regexp(ses, root->list[root->update], line, original, 0))
-		{
-			node = root->list[root->update];
-
-			if (*node->arg2)
-			{
-				substitute(ses, node->arg2, original, SUB_ARG);
-				substitute(ses, original, original, SUB_VAR|SUB_FUN|SUB_COL|SUB_ESC);
-			}
-
-			show_debug(ses, LIST_PROMPT, "#DEBUG PROMPT {%s}", node->arg1);
-			show_debug(ses, LIST_GAG, "#DEBUG GAG {%s}", node->arg1);
-
-			do_one_prompt(ses, original, atoi(node->arg3), atoi(node->arg4));
-
-			SET_BIT(ses->flags, SES_FLAG_GAG);
-		}
-	}
-}
-
-void do_one_prompt(struct session *ses, char *prompt, int row, int col)
-{
-	char temp[BUFFER_SIZE];
-	int original_row, original_col, len, clear;
-
-	original_row = row;
-	original_col = col;
-
-	if (row < 0)
-	{
-		row = 1 + gtd->screen->rows + row;
-	}
-	else if (row == 0)
-	{
-		row = gtd->screen->rows - 2;
-	}
-
-	clear = 0;
-
-	if (col < 0)
-	{
-		col = 1 + gtd->screen->cols + col;
-	}
-	else if (col == 0)
-	{
-		col = 1;
-		clear = 1;
-	}
-
-	if (row < 1 || row > gtd->screen->rows)
-	{
-		show_error(ses, LIST_PROMPT, "#ERROR: PROMPT ROW IS OUTSIDE THE SCREEN: {%s} {%d} {%d}.", prompt, original_row, original_col);
-
-		return;
-	}
-
-	if (col < 0 || col > gtd->screen->cols)
-	{
-		show_error(ses, LIST_PROMPT, "#ERROR: PROMPT COLUMN IS OUTSIDE THE SCREEN: {%s} {%d} {%d}.", prompt, original_row, original_col);
-
-		return;
-	}
-
-	if (row > ses->top_row && row < ses->bot_row)
-	{
-		show_error(ses, LIST_PROMPT, "#ERROR: PROMPT ROW IS INSIDE THE SCROLLING REGION: {%s} {%d}.", prompt, original_row);
-
-		return;
-	}
-
-	if (ses != gtd->ses)
-	{
-		return;
-	}
-
-	len = strip_vt102_strlen(ses, prompt);
-
-	if (len == 0)
-	{
-		sprintf(temp, "%.*s", gtd->screen->cols + 4, "\e[0m--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
-	}
-	else if (col - 1 + len <= gtd->screen->cols)
-	{
-		sprintf(temp, "%s", prompt);
-	}
-	else
-	{
-		show_debug(ses, LIST_PROMPT, "#DEBUG PROMPT {%s}", prompt);
-
-		sprintf(temp, "#PROMPT SIZE (%d) LONGER THAN ROW SIZE (%d)", len, gtd->screen->cols);
-	}
-
-	if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
-	{
-		save_pos(ses);
-	}
-
-	if (row == gtd->screen->rows)
-	{
-		gtd->input_off = len + 1;
-
-		printf("\e[%d;1H\e[%d;1H\e[K%s%s\e[%d;%dH\e7\e[%d;1H", row, row, temp, gtd->input_buf, row, gtd->input_off + gtd->input_cur, ses->bot_row);
-	}
-	else
-	{
-		printf("\e[%d;%dH\e[%d;%dH%s%s\e[%d;1H", row, col, row, col, clear ? "\e[2K" : "", temp, ses->bot_row);
-	}
-
-	set_line_screen(temp, row - 1, col - 1);
-
-	if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
-	{
-		restore_pos(ses);
-	}
-
-}

+ 121 - 26
src/screen.c

@@ -56,23 +56,29 @@ DO_COMMAND(do_screen)
 		{
 		{
 			if (is_abbrev(arg1, screen_table[cnt].name))
 			if (is_abbrev(arg1, screen_table[cnt].name))
 			{
 			{
-				if (HAS_BIT(screen_table[cnt].get1, SCREEN_FLAG_GET_ONE))
+				if (!HAS_BIT(screen_table[cnt].get1, SCREEN_FLAG_GET_NONE))
 				{
 				{
-					arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
+					if (HAS_BIT(screen_table[cnt].get1, SCREEN_FLAG_GET_ONE))
+					{
+						arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
+					}
+					else
+					{
+						arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
+					}
 				}
 				}
-				else
-				{
-					arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
-				}
-				if (HAS_BIT(screen_table[cnt].get2, SCREEN_FLAG_GET_ONE))
-				{
-					arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
-				}
-				else
+
+				if (!HAS_BIT(screen_table[cnt].get2, SCREEN_FLAG_GET_NONE))
 				{
 				{
-					arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
+					if (HAS_BIT(screen_table[cnt].get2, SCREEN_FLAG_GET_ONE))
+					{
+						arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
+					}
+					else
+					{
+						arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
+					}
 				}
 				}
-
 				screen_table[cnt].fun(ses, cnt, arg, arg1, arg2);
 				screen_table[cnt].fun(ses, cnt, arg, arg1, arg2);
 
 
 				return ses;
 				return ses;
@@ -135,21 +141,31 @@ DO_SCREEN(screen_clear)
 	{
 	{
 		printf("\e[2J");
 		printf("\e[2J");
 	}
 	}
+	else if (is_abbrev(arg1, "BOTTOM SPLIT"))
+	{
+		erase_bot_region(ses);
+	}
+	else if (is_abbrev(arg1, "TOP SPLIT"))
+	{
+		erase_top_region(ses);
+	}
 	else if (is_abbrev(arg1, "SCROLL REGION"))
 	else if (is_abbrev(arg1, "SCROLL REGION"))
 	{
 	{
-//		erase_scroll_region(ses);
-
-		printf("\e[%d;%d;%d;%d${", ses->top_row, 1, ses->bot_row, gtd->screen->cols);
+		erase_scroll_region(ses);
+	}
+	else if (is_abbrev(arg1, "SPLIT REGION"))
+	{
+		erase_split_region(ses);
 	}
 	}
 	else if (is_abbrev(arg1, "SQUARE"))
 	else if (is_abbrev(arg1, "SQUARE"))
 	{
 	{
-		strcpy(arg1, arg2);
+		arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
 
 
 		top_row = get_row_index(ses, arg1);
 		top_row = get_row_index(ses, arg1);
 		top_col = get_col_index(ses, arg2);
 		top_col = get_col_index(ses, arg2);
 
 
-		tintin_printf2(ses, "debug: (%s) (%s) %d %d", arg1, arg2, top_row, top_col);
+//		tintin_printf2(ses, "debug: (%s) (%s) %d %d", arg1, arg2, top_row, top_col);
 
 
 		arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
@@ -157,7 +173,7 @@ DO_SCREEN(screen_clear)
 		bot_row = get_row_index(ses, arg1);
 		bot_row = get_row_index(ses, arg1);
 		bot_col = get_col_index(ses, arg2);
 		bot_col = get_col_index(ses, arg2);
 
 
-		tintin_printf2(ses, "debug: (%s) (%s) %d %d", arg1, arg2, bot_row, bot_col);
+//		tintin_printf2(ses, "debug: (%s) (%s) %d %d", arg1, arg2, bot_row, bot_col);
 
 
 		if (bot_col == 0)
 		if (bot_col == 0)
 		{
 		{
@@ -165,12 +181,14 @@ DO_SCREEN(screen_clear)
 		}
 		}
 		else
 		else
 		{
 		{
-			printf("\e[%d;%d;%d;%d${", top_row, top_col, bot_row, bot_col);
+			erase_square(ses, top_row, top_col, bot_row, bot_col);
+
+//			printf("\e[%d;%d;%d;%d${", top_row, top_col, bot_row, bot_col); VT400 not widely supported
 		}
 		}
 	}
 	}
 	else
 	else
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #SCREEN CLEAR {ALL|SCROLL REGION|SQUARE}");
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #SCREEN CLEAR {ALL|SCROLL|SPLIT|SQUARE}");
 	}
 	}
 }
 }
 
 
@@ -927,19 +945,96 @@ void set_line_screen(char *str, int row, int col)
 
 
 void erase_scroll_region(struct session *ses)
 void erase_scroll_region(struct session *ses)
 {
 {
-	push_call("erase_scroll_region(%p) (%d,%d)",ses,ses->top_row,ses->bot_row);
+	int row;
 
 
-//	printf("\e[%d;%d;%d;%d${", ses->top_row, 1, ses->bot_row, gtd->screen->cols); VT400
+	push_call("erase_scroll_region(%p) [%d,%d]",ses,ses->top_row,ses->bot_row);
 
 
-	printf("\e7\e[%d;1H\e[%dM\e8", ses->top_row, ses->bot_row - ses->top_row);
+	if (ses->wrap <= 0)
+	{
+		save_pos(ses);
+		goto_pos(ses, ses->top_row, 1);
+		erase_lines(ses, ses->bot_row - ses->top_row);
+		load_pos(ses);
+	}
+	else
+	{
+		save_pos(ses);
+		goto_pos(ses, ses->top_row, 1);
+
+		for (row = ses->top_row ; row < ses->bot_row ; row++)
+		{
+			printf("\e[%dX\n", ses->wrap);
+		}
+		load_pos(ses);
+	}
 
 
-	ses->sav_row = ses->cur_row;
-	ses->sav_col = ses->cur_col;
+//	printf("\e[%d;%d;%d;%d${", ses->top_row, 1, ses->bot_row, gtd->screen->cols); VT400 not widely supported
 
 
 	pop_call();
 	pop_call();
 	return;
 	return;
 }
 }
 
 
+void erase_split_region(struct session *ses)
+{
+	erase_top_region(ses);
+
+	erase_bot_region(ses);
+}
+
+void erase_top_region(struct session *ses)
+{
+	int row;
+
+	if (ses->top_row > 1)
+	{
+		save_pos(ses);
+		goto_pos(ses, 1, 1);
+
+		for (row = 1 ; row < ses->top_row ; row++)
+		{
+			printf("\e[K\n");
+		}
+		load_pos(ses);
+	}
+}
+
+void erase_bot_region(struct session *ses)
+{
+	int row;
+
+	if (ses->bot_row < gtd->screen->rows)
+	{
+		save_pos(ses);
+		goto_pos(ses, ses->bot_row + 1, 1);
+
+		for (row = ses->bot_row + 1 ; row < gtd->screen->rows ; row++)
+		{
+			printf("\e[K\n");
+		}
+		load_pos(ses);
+	}
+}
+
+void erase_square(struct session *ses, int top_row, int top_col, int bot_row, int bot_col)
+{
+	int row;
+
+	push_call("erase_square(%p,%d,%d,%d,%d)",ses,top_row,top_col,bot_row,bot_col);
+
+	save_pos(ses);
+
+	for (row = top_row ; row <= bot_row ; row++)
+	{
+		goto_pos(ses, row, top_col);
+		printf("\e[%dX", bot_col - top_col + 1);
+	}
+	load_pos(ses);
+
+	pop_call();
+	return;
+}
+
+
 void get_line_screen(char *result, int row)
 void get_line_screen(char *result, int row)
 {
 {
 	strcpy(result, gtd->screen->lines[row]->str);
 	strcpy(result, gtd->screen->lines[row]->str);

+ 23 - 8
src/session.c

@@ -380,9 +380,14 @@ struct session *new_session(struct session *ses, char *name, char *arg, int desc
 		}
 		}
 	}
 	}
 
 
+	newses->top_split = gts->top_split;
+	newses->bot_split = gts->bot_split;
+
 	newses->top_row = gts->top_row;
 	newses->top_row = gts->top_row;
 	newses->bot_row = gts->bot_row;
 	newses->bot_row = gts->bot_row;
 
 
+	newses->wrap    = gts->wrap;
+
 	init_buffer(newses, -1);
 	init_buffer(newses, -1);
 
 
 	memcpy(&newses->cur_terminal, &gts->cur_terminal, sizeof(gts->cur_terminal));
 	memcpy(&newses->cur_terminal, &gts->cur_terminal, sizeof(gts->cur_terminal));
@@ -400,10 +405,13 @@ struct session *new_session(struct session *ses, char *name, char *arg, int desc
 		tintin_printf(ses, "#TRYING TO LAUNCH '%s' RUNNING '%s'.", newses->name, newses->session_host);
 		tintin_printf(ses, "#TRYING TO LAUNCH '%s' RUNNING '%s'.", newses->name, newses->session_host);
 	}
 	}
 
 
-	gtd->ses = newses;
-
 	dirty_screen(newses);
 	dirty_screen(newses);
 
 
+	if (gtd->background_level == 0)
+	{
+		gtd->ses = newses;
+	}
+
 	if (desc == 0)
 	if (desc == 0)
 	{
 	{
 		newses = connect_session(newses);
 		newses = connect_session(newses);
@@ -425,7 +433,7 @@ struct session *new_session(struct session *ses, char *name, char *arg, int desc
 	if (newses == NULL)
 	if (newses == NULL)
 	{
 	{
 		pop_call();
 		pop_call();
-		return gtd->ses;
+		return ses;
 	}
 	}
 
 
 #ifdef HAVE_GNUTLS_H
 #ifdef HAVE_GNUTLS_H
@@ -443,16 +451,23 @@ struct session *new_session(struct session *ses, char *name, char *arg, int desc
 	}
 	}
 #endif
 #endif
 
 
-	gtd->ses = newses;
 
 
 	if (*file)
 	if (*file)
 	{
 	{
-		gtd->ses = do_read(newses, file);
+		newses = do_read(newses, file);
 	}
 	}
 	check_all_events(newses, SUB_ARG, 0, 4, "SESSION CREATED", newses->name, newses->session_host, newses->session_ip, newses->session_port);
 	check_all_events(newses, SUB_ARG, 0, 4, "SESSION CREATED", newses->name, newses->session_host, newses->session_ip, newses->session_port);
 
 
-	pop_call();
-	return gtd->ses;
+	if (gtd->background_level == 0)
+	{
+		pop_call();
+		return newses;
+	}
+	else
+	{
+		pop_call();
+		return ses;
+	}
 }
 }
 
 
 struct session *connect_session(struct session *ses)
 struct session *connect_session(struct session *ses)
@@ -470,7 +485,7 @@ struct session *connect_session(struct session *ses)
 
 
 	if (sock == -1)
 	if (sock == -1)
 	{
 	{
-		syserr_printf(ses, "connect_session: connect");
+//		syserr_printf(ses, "connect_session: connect");
 
 
 		cleanup_session(ses);
 		cleanup_session(ses);
 
 

+ 75 - 42
src/show.c

@@ -60,7 +60,7 @@ DO_COMMAND(do_showme)
 
 
 	if (*arg2)
 	if (*arg2)
 	{
 	{
-		do_one_prompt(ses, arg1, (int) get_number(ses, arg2), (int) get_number(ses, arg3));
+		split_show(ses, arg1, (int) get_number(ses, arg2), (int) get_number(ses, arg3));
 
 
 		return ses;
 		return ses;
 	}
 	}
@@ -117,14 +117,14 @@ void show_message(struct session *ses, int index, char *format, ...)
 		goto display;
 		goto display;
 	}
 	}
 
 
-	if (HAS_BIT(root->flags, LIST_FLAG_MESSAGE))
+	if (!HAS_BIT(root->flags, LIST_FLAG_MESSAGE))
 	{
 	{
-		if (gtd->input_level == 0)
-		{
-			goto display;
-		}
-		pop_call();
-		return;
+		goto end;
+	}
+
+	if (gtd->input_level)
+	{
+		goto end;
 	}
 	}
 
 
 	display:
 	display:
@@ -135,16 +135,28 @@ void show_message(struct session *ses, int index, char *format, ...)
 
 
 	tintin_puts2(ses, buffer);
 	tintin_puts2(ses, buffer);
 
 
+	free(buffer);
+
+	pop_call();
+	return;
+
+	end:
+
+
 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
 	{
 	{
 		if (ses->logfile)
 		if (ses->logfile)
 		{
 		{
-			logit(ses, buffer, ses->logfile, TRUE);
+			va_start(args, format);
+			vasprintf(&buffer, format, args);
+			va_end(args);
+
+			logit(ses, buffer, ses->logfile, LOG_FLAG_LINEFEED);
+
+			free(buffer);
 		}
 		}
 	}
 	}
 
 
-	free(buffer);
-
 	pop_call();
 	pop_call();
 	return;
 	return;
 }
 }
@@ -170,14 +182,6 @@ void show_error(struct session *ses, int index, char *format, ...)
 
 
 	root = ses->list[index];
 	root = ses->list[index];
 
 
-	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
-	{
-		if (ses->logfile)
-		{
-			logit(ses, buffer, ses->logfile, TRUE);
-		}
-	}
-
 	if (HAS_BIT(root->flags, LIST_FLAG_DEBUG))
 	if (HAS_BIT(root->flags, LIST_FLAG_DEBUG))
 	{
 	{
 		tintin_puts2(ses, buffer);
 		tintin_puts2(ses, buffer);
@@ -188,6 +192,16 @@ void show_error(struct session *ses, int index, char *format, ...)
 	if (HAS_BIT(root->flags, LIST_FLAG_MESSAGE))
 	if (HAS_BIT(root->flags, LIST_FLAG_MESSAGE))
 	{
 	{
 		tintin_puts2(ses, buffer);
 		tintin_puts2(ses, buffer);
+
+		goto end;
+	}
+
+	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
+	{
+		if (ses->logfile)
+		{
+			logit(ses, buffer, ses->logfile, LOG_FLAG_LINEFEED);
+		}
 	}
 	}
 
 
 	end:
 	end:
@@ -236,7 +250,7 @@ void show_debug(struct session *ses, int index, char *format, ...)
 	{
 	{
 		if (ses->logfile)
 		if (ses->logfile)
 		{
 		{
-			logit(ses, buf, ses->logfile, TRUE);
+			logit(ses, buf, ses->logfile, LOG_FLAG_LINEFEED);
 		}
 		}
 	}
 	}
 	pop_call();
 	pop_call();
@@ -275,27 +289,47 @@ void show_info(struct session *ses, int index, char *format, ...)
 	return;
 	return;
 }
 }
 
 
-void show_lines(struct session *ses, int flags, char *format, ...)
+void print_lines(struct session *ses, int flags, char *format, ...)
 {
 {
-	char *buffer, *str_buf, *pto, *ptf;
+	char *buffer, *str_buf;
 	va_list args;
 	va_list args;
 
 
-	push_call("show_lines(%p,%d,%p,...)",ses,flags,format);
+	push_call("print_lines(%p,%d,%p,...)",ses,flags,format);
 
 
 	va_start(args, format);
 	va_start(args, format);
 	vasprintf(&buffer, format, args);
 	vasprintf(&buffer, format, args);
 	va_end(args);
 	va_end(args);
 
 
-	str_buf = str_alloc(BUFFER_SIZE + strlen(buffer) * 2);
+	if (flags)
+	{
+		str_buf = str_alloc(BUFFER_SIZE + strlen(buffer) * 2);
+
+		substitute(ses, buffer, str_buf, flags);
+
+		show_lines(ses, str_buf);
+
+		str_free(str_buf);
+	}
+	else
+	{
+		show_lines(ses, buffer);
+	}
 
 
-	substitute(ses, buffer, str_buf, flags);
+	free(buffer);
+
+	pop_call();
+	return;
+}
 
 
+void show_lines(struct session *ses, char *str)
+{
+	char *ptf;
 
 
-	pto = str_buf;
+	push_call("show_lines(%p,%p,...)",ses,str);
 
 
-	while (*pto)
+	while (*str)
 	{
 	{
-		ptf = strchr(pto, '\n');
+		ptf = strchr(str, '\n');
 
 
 		if (ptf == NULL)
 		if (ptf == NULL)
 		{
 		{
@@ -303,14 +337,10 @@ void show_lines(struct session *ses, int flags, char *format, ...)
 		}
 		}
 		*ptf++ = 0;
 		*ptf++ = 0;
 
 
-		tintin_puts3(ses, pto);
+		tintin_puts3(ses, str);
 
 
-		pto = ptf;
+		str = ptf;
 	}
 	}
-
-	free(buffer);
-	str_free(str_buf);
-
 	pop_call();
 	pop_call();
 	return;
 	return;
 }
 }
@@ -320,28 +350,31 @@ void tintin_header(struct session *ses, char *format, ...)
 {
 {
 	char arg[BUFFER_SIZE], buf[BUFFER_SIZE];
 	char arg[BUFFER_SIZE], buf[BUFFER_SIZE];
 	va_list args;
 	va_list args;
+	int cols;
 
 
 	va_start(args, format);
 	va_start(args, format);
 	vsprintf(arg, format, args);
 	vsprintf(arg, format, args);
 	va_end(args);
 	va_end(args);
 
 
-	if ((int) strlen(arg) > gtd->screen->cols - 2)
+	cols = ses->wrap > 0 ? ses->wrap : gtd->screen->cols;
+
+	if ((int) strlen(arg) > cols - 2)
 	{
 	{
-		arg[gtd->screen->cols - 2] = 0;
+		arg[cols - 2] = 0;
 	}
 	}
 
 
 	if (HAS_BIT(ses->flags, SES_FLAG_SCREENREADER))
 	if (HAS_BIT(ses->flags, SES_FLAG_SCREENREADER))
 	{
 	{
-		memset(buf, ' ', gtd->screen->cols);
+		memset(buf, ' ', cols);
 	}
 	}
 	else
 	else
 	{
 	{
-		memset(buf, '#', gtd->screen->cols);
+		memset(buf, '#', cols);
 	}
 	}
 
 
-	memcpy(&buf[(gtd->screen->cols - strlen(arg)) / 2], arg, strlen(arg));
+	memcpy(&buf[(cols - strlen(arg)) / 2], arg, strlen(arg));
 
 
-	buf[gtd->screen->cols] = 0;
+	buf[cols] = 0;
 
 
 	tintin_puts2(ses, buf);
 	tintin_puts2(ses, buf);
 }
 }
@@ -427,7 +460,7 @@ void tintin_puts2(struct session *ses, char *string)
 		ses = gtd->ses;
 		ses = gtd->ses;
 	}
 	}
 
 
-	if (!HAS_BIT(gtd->ses->flags, SES_FLAG_VERBOSE) && gtd->quiet && gtd->verbose_level == 0)
+	if (!HAS_BIT(gtd->ses->flags, SES_FLAG_VERBOSE) && gtd->quiet_level && gtd->verbose_level == 0)
 	{
 	{
 		pop_call();
 		pop_call();
 		return;
 		return;
@@ -483,7 +516,7 @@ void tintin_puts3(struct session *ses, char *string)
 		ses = gtd->ses;
 		ses = gtd->ses;
 	}
 	}
 
 
-	if (!HAS_BIT(gtd->ses->flags, SES_FLAG_VERBOSE) && gtd->quiet && gtd->verbose_level == 0)
+	if (!HAS_BIT(gtd->ses->flags, SES_FLAG_VERBOSE) && gtd->quiet_level && gtd->verbose_level == 0)
 	{
 	{
 		pop_call();
 		pop_call();
 		return;
 		return;

+ 100 - 2
src/split.c

@@ -143,14 +143,14 @@ void init_split(struct session *ses, int top, int bot)
 
 
 	for (bot = 1 ; gtd->screen->rows - bot > ses->bot_row ; bot++)
 	for (bot = 1 ; gtd->screen->rows - bot > ses->bot_row ; bot++)
 	{
 	{
-		do_one_prompt(ses, "", gtd->screen->rows - bot, 0);
+		split_show(ses, "", gtd->screen->rows - bot, 0);
 	}
 	}
 
 
 	set_line_screen("", ses->bot_row - 1, 0);
 	set_line_screen("", ses->bot_row - 1, 0);
 
 
 	for (top = 1 ; top < ses->top_row ; top++)
 	for (top = 1 ; top < ses->top_row ; top++)
 	{
 	{
-		do_one_prompt(ses, "", top, 0);
+		split_show(ses, "", top, 0);
 	}
 	}
 
 
 	goto_rowcol(ses, gtd->screen->rows, 1);
 	goto_rowcol(ses, gtd->screen->rows, 1);
@@ -222,3 +222,101 @@ void dirty_screen(struct session *ses)
 	pop_call();
 	pop_call();
 	return;
 	return;
 }
 }
+
+
+void split_show(struct session *ses, char *prompt, int row, int col)
+{
+	char temp[BUFFER_SIZE];
+	int original_row, original_col, len, clear;
+
+	original_row = row;
+	original_col = col;
+
+	if (row < 0)
+	{
+		row = 1 + gtd->screen->rows + row;
+	}
+	else if (row == 0)
+	{
+		row = gtd->screen->rows - 2;
+	}
+
+	clear = 0;
+
+	if (col < 0)
+	{
+		col = 1 + gtd->screen->cols + col;
+	}
+	else if (col == 0)
+	{
+		col = 1;
+		clear = 1;
+	}
+
+	if (row < 1 || row > gtd->screen->rows)
+	{
+		show_error(ses, LIST_PROMPT, "#ERROR: PROMPT ROW IS OUTSIDE THE SCREEN: {%s} {%d} {%d}.", prompt, original_row, original_col);
+
+		return;
+	}
+
+	if (col < 0 || col > gtd->screen->cols)
+	{
+		show_error(ses, LIST_PROMPT, "#ERROR: PROMPT COLUMN IS OUTSIDE THE SCREEN: {%s} {%d} {%d}.", prompt, original_row, original_col);
+
+		return;
+	}
+
+	if (row > ses->top_row && row < ses->bot_row)
+	{
+		show_error(ses, LIST_PROMPT, "#ERROR: PROMPT ROW IS INSIDE THE SCROLLING REGION: {%s} {%d}.", prompt, original_row);
+
+		return;
+	}
+
+	if (ses != gtd->ses)
+	{
+		return;
+	}
+
+	len = strip_vt102_strlen(ses, prompt);
+
+	if (len == 0)
+	{
+		sprintf(temp, "%.*s", gtd->screen->cols + 4, "\e[0m--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------");
+	}
+	else if (col - 1 + len <= gtd->screen->cols)
+	{
+		sprintf(temp, "%s", prompt);
+	}
+	else
+	{
+		show_debug(ses, LIST_PROMPT, "#DEBUG PROMPT {%s}", prompt);
+
+		sprintf(temp, "#PROMPT SIZE (%d) LONGER THAN ROW SIZE (%d)", len, gtd->screen->cols);
+	}
+
+	if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
+	{
+		save_pos(ses);
+	}
+
+	if (row == gtd->screen->rows)
+	{
+		gtd->input_off = len + 1;
+
+		printf("\e[%d;1H\e[%d;1H\e[K%s%s\e[%d;%dH\e7\e[%d;1H", row, row, temp, gtd->input_buf, row, gtd->input_off + gtd->input_cur, ses->bot_row);
+	}
+	else
+	{
+		printf("\e[%d;%dH\e[%d;%dH%s%s\e[%d;1H", row, col, row, col, clear ? "\e[2K" : "", temp, ses->bot_row);
+	}
+
+	set_line_screen(temp, row - 1, col - 1);
+
+	if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
+	{
+		restore_pos(ses);
+	}
+
+}

+ 2 - 2
src/ssl.c

@@ -51,7 +51,7 @@ DO_COMMAND(do_ssl)
 	{
 	{
 		ses = new_session(ses, arg1, arg, 0, 1);
 		ses = new_session(ses, arg1, arg, 0, 1);
 	}
 	}
-	return gtd->ses;
+	return ses;
 }
 }
 
 
 gnutls_session_t ssl_negotiate(struct session *ses)
 gnutls_session_t ssl_negotiate(struct session *ses)
@@ -69,7 +69,7 @@ gnutls_session_t ssl_negotiate(struct session *ses)
 	gnutls_init(&ssl_ses, GNUTLS_CLIENT);
 	gnutls_init(&ssl_ses, GNUTLS_CLIENT);
 	gnutls_set_default_priority(ssl_ses);
 	gnutls_set_default_priority(ssl_ses);
 	gnutls_credentials_set(ssl_ses, GNUTLS_CRD_CERTIFICATE, ssl_cred);
 	gnutls_credentials_set(ssl_ses, GNUTLS_CRD_CERTIFICATE, ssl_cred);
-	gnutls_transport_set_ptr(ssl_ses, (gnutls_transport_ptr_t) ses->socket);
+	gnutls_transport_set_ptr(ssl_ses, (gnutls_transport_ptr_t) (long int) ses->socket);
 
 
 	do 
 	do 
 	{
 	{

+ 1040 - 56
src/substitute.c

@@ -21,114 +21,1098 @@
 /******************************************************************************
 /******************************************************************************
 *                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
 *                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
 *                                                                             *
 *                                                                             *
-*                         coded by Peter Unold 1992                           *
+*                      coded by Igor van den Hoven 2004                       *
 ******************************************************************************/
 ******************************************************************************/
 
 
-
 #include "tintin.h"
 #include "tintin.h"
 
 
-DO_COMMAND(do_substitute)
+int is_variable(struct session *ses, char *str)
 {
 {
-	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE], *str;
+	struct listroot *root;
+	char temp[BUFFER_SIZE], *ptt;
+	int i = 1;
+
+	while (str[i] == str[0])
+	{
+		i++;
+	}
 
 
-	str = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
-	arg = get_arg_in_braces(ses, str, arg2, GET_ALL);
-	arg = get_arg_in_braces(ses, arg, arg3, GET_ALL);
+	if (str[i] == DEFAULT_OPEN)
+	{
+		return TRUE;
+	}
 
 
-	if (*arg3 == 0)
+	if (str[i] != '_' && isalpha((int) str[i]) == 0)
 	{
 	{
-		strcpy(arg3, "5");
+		return FALSE;
 	}
 	}
 
 
-	if (*arg1 == 0)
+	ptt = temp;
+
+	while (isalnum((int) str[i]) || str[i] == '_')
 	{
 	{
-		show_list(ses->list[LIST_SUBSTITUTE], 0);
+		*ptt++ = str[i];
+
+		i++;
 	}
 	}
-	else if (*str == 0)
+	*ptt = 0;
+
+	root = local_list(ses);
+
+	if (search_node_list(root, temp) == NULL)
 	{
 	{
-		if (show_node_with_wild(ses, arg1, ses->list[LIST_SUBSTITUTE]) == FALSE)
+		root = ses->list[LIST_VARIABLE];
+
+		if (search_node_list(root, temp) == NULL)
 		{
 		{
-			show_message(ses, LIST_SUBSTITUTE, "#SUBSTITUTE: NO MATCH(ES) FOUND FOR {%s}.", arg1);
+			return FALSE;
 		}
 		}
 	}
 	}
-	else
+
+	return TRUE;
+}
+
+int is_function(struct session *ses, char *str)
+{
+	char temp[BUFFER_SIZE], *ptt;
+	int i = 1;
+
+	while (str[i] == str[0])
 	{
 	{
-		update_node_list(ses->list[LIST_SUBSTITUTE], arg1, arg2, arg3, "");
+		i++;
+	}
 
 
-		show_message(ses, LIST_SUBSTITUTE, "#OK. {%s} IS NOW SUBSTITUTED AS {%s} @ {%s}.", arg1, arg2, arg3);
+	if (str[i] != '_' && isalpha((int) str[i]) == 0)
+	{
+		return FALSE;
 	}
 	}
-	return ses;
-}
 
 
+	ptt = temp;
 
 
-DO_COMMAND(do_unsubstitute)
-{
-	delete_node_with_wild(ses, LIST_SUBSTITUTE, arg);
+	while (isalnum((int) str[i]) || str[i] == '_')
+	{
+		*ptt++ = str[i];
+
+		i++;
+	}
+	*ptt = 0;
+
+	if (str[i] != DEFAULT_OPEN)
+	{
+		return FALSE;
+	}
+
+	if (search_node_list(ses->list[LIST_FUNCTION], temp) == NULL)
+	{
+		if (find_session(temp) == NULL)
+		{
+			return FALSE;
+		}
+	}
 
 
-	return ses;
+	return TRUE;
 }
 }
 
 
-void check_all_substitutions(struct session *ses, char *original, char *line)
+int substitute(struct session *ses, char *string, char *result, int flags)
 {
 {
-	char match[BUFFER_SIZE], subst[BUFFER_SIZE], output[BUFFER_SIZE], temp[BUFFER_SIZE], *ptl, *ptm, *pto;
-	struct listroot *root = ses->list[LIST_SUBSTITUTE];
 	struct listnode *node;
 	struct listnode *node;
-	int len;
+	struct listroot *root;
+	struct session *sesptr;
+	char temp[BUFFER_SIZE], buf[BUFFER_SIZE], buffer[BUFFER_SIZE], *pti, *pto, *ptt, *str;
+	char *pte, old[10] = { 0 };
+	int i, cnt, escape = FALSE, flags_neol = flags;
+
+	push_call("substitute(%p,%p,%p,%d)",ses,string,result,flags);
+
+	pti = string;
+	pto = (string == result) ? buffer : result;
 
 
-	for (root->update = 0 ; root->update < root->used ; root->update++)
+	DEL_BIT(flags_neol, SUB_EOL|SUB_LNF);
+
+	while (TRUE)
 	{
 	{
-		if (check_one_regexp(ses, root->list[root->update], line, original, 0))
+		if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *pti & 128 && pti[1] != 0)
+		{
+			*pto++ = *pti++;
+			*pto++ = *pti++;
+			continue;
+		}
+
+		switch (*pti)
 		{
 		{
-			node = root->list[root->update];
+			case '\0':
+				if (HAS_BIT(flags, SUB_EOL))
+				{
+					if (HAS_BIT(ses->flags, SES_FLAG_RUN))
+					{
+						*pto++ = '\r';
+					}
+					else
+					{
+						*pto++ = '\r';
+						*pto++ = '\n';
+					}
+				}
+
+				if (HAS_BIT(flags, SUB_LNF))
+				{
+					*pto++ = '\n';
+				}
 
 
-			pto = original;
-			ptl = line;
+				*pto = 0;
 
 
-			*output = 0;
+				if (string == result)
+				{
+					strcpy(result, buffer);
 
 
-			do
-			{
-				if (*gtd->vars[0] == 0)
+					pop_call();
+					return pto - buffer;
+				}
+				else
 				{
 				{
-					break;
+					pop_call();
+					return pto - result;
 				}
 				}
+				break;
+
+			case '@':
+				if (HAS_BIT(flags, SUB_FUN) && !HAS_BIT(ses->list[LIST_FUNCTION]->flags, LIST_FLAG_IGNORE))
+				{
+					i = 1;
+					escape = FALSE;
+					sesptr = NULL;
+
+					while (pti[i] == '@')
+					{
+						escape = TRUE;
 
 
-				strcpy(match, gtd->vars[0]);
+						i++;
+					}
 
 
-				substitute(ses, node->arg2, temp, SUB_ARG);
-				substitute(ses, temp, subst, SUB_VAR|SUB_FUN|SUB_COL|SUB_ESC);
+					for (ptt = temp ; isalnum((int) pti[i]) || pti[i] == '_' ; i++)
+					{
+						*ptt++ = pti[i];
+					}
+					*ptt = 0;
 
 
-				if (*node->arg1 == '~')
+					if (pti[i] != DEFAULT_OPEN)
+					{
+						while (*pti == '@')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					node = search_node_list(ses->list[LIST_FUNCTION], temp);
+
+					if (node == NULL)
+					{
+						sesptr = find_session(temp);
+					}
+
+					if (sesptr == NULL && node == NULL)
+					{
+						while (*pti == '@')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					if (escape)
+					{
+						pti++;
+
+						while (*pti == '@')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					pti = get_arg_in_braces(ses, &pti[i], temp, GET_ONE);
+
+					if (sesptr)
+					{
+						substitute(sesptr, temp, pto, flags_neol);
+
+						pto += strlen(pto);
+						
+						continue;
+					}
+					else
+					{
+						substitute(ses, temp, buf, flags_neol);
+					}
+
+					show_debug(ses, LIST_FUNCTION, "#DEBUG FUNCTION {%s}", node->arg1);
+
+					RESTRING(gtd->vars[0], buf);
+
+					pte = buf;
+
+					for (i = 1 ; i < 100 ; i++)
+					{
+						pte = get_arg_in_braces(ses, pte, temp, GET_ALL);
+
+						RESTRING(gtd->vars[i], temp);
+
+						if (*pte == 0)
+						{
+							while (++i < 100)
+							{
+								if (*gtd->vars[i])
+								{
+									RESTRING(gtd->vars[i], "");
+								}
+							}
+							break;
+						}
+
+						if (*pte == COMMAND_SEPARATOR)
+						{
+							pte++;
+						}
+
+					}
+
+					substitute(ses, node->arg2, buf, SUB_ARG);
+
+					script_driver(ses, LIST_FUNCTION, buf);
+
+					substitute(ses, "$result", pto, flags_neol|SUB_VAR);
+
+					pto += strlen(pto);
+				}
+				else
 				{
 				{
-					ptm = strstr(pto, match);
+					if (HAS_BIT(flags, SUB_SEC) && !HAS_BIT(flags, SUB_ARG) && is_function(ses, pti))
+					{
+						*pto++ = '\\';
+					}
+					*pto++ = *pti++;
+				}
+				break;
 
 
-					len = strlen(match);
+			case '*':
+				if (HAS_BIT(flags, SUB_VAR) && !HAS_BIT(ses->list[LIST_VARIABLE]->flags, LIST_FLAG_IGNORE) && pti[1])
+				{
+					int brace = FALSE;
+					i = 1;
+					escape = FALSE;
+
+					while (pti[i] == '*')
+					{
+						escape = TRUE;
+
+						i++;
+					}
+
+					if (pti[i] == DEFAULT_OPEN)
+					{
+						brace = TRUE;
+
+						ptt = get_arg_in_braces(ses, &pti[i], buf, GET_ALL);
+
+						i += strlen(buf) + 2;
+
+						substitute(ses, buf, temp, flags_neol);
+					}
+					else
+					{
+						ptt = temp;
+
+						while (isalnum((int) pti[i]) || pti[i] == '_')
+						{
+							*ptt++ = pti[i];
+
+							i++;
+						}
+						*ptt = 0;
+					}
+
+					if (*temp)
+					{
+						root = local_list(ses);
+
+						if ((node = search_node_list(root, temp)) == NULL)
+						{
+							root = ses->list[LIST_VARIABLE];
+
+							node = search_node_list(root, temp);
+						}
+					}
+					else
+					{
+						root = ses->list[LIST_VARIABLE];
+						node = NULL;
+					}
+
+					if (brace == FALSE && node == NULL)
+					{
+						while (*pti == '*')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					if (escape)
+					{
+						pti++;
+
+						while (*pti == '*')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					pti = get_arg_at_brackets(ses, &pti[i], temp + strlen(temp));
+
+					substitute(ses, temp, buf, flags_neol);
+
+					str = str_dup("");
+
+					get_nest_node_key(root, buf, &str, brace);
+
+					substitute(ses, str, pto, flags_neol - SUB_VAR);
+
+					pto += strlen(pto);
+
+					str_free(str);
 				}
 				}
 				else
 				else
 				{
 				{
-					ptm = strip_vt102_strstr(pto, match, &len);
+					if (HAS_BIT(flags, SUB_SEC) && !HAS_BIT(flags, SUB_ARG) && is_variable(ses, pti))
+					{
+						*pto++ = '\\';
+					}
+					*pto++ = *pti++;
+				}
+				break;
 
 
-					ptl = strstr(ptl, match) + strlen(match);
+			case '$':
+				if (HAS_BIT(flags, SUB_VAR) && !HAS_BIT(ses->list[LIST_VARIABLE]->flags, LIST_FLAG_IGNORE) && pti[1])
+				{
+					int brace = FALSE;
+					i = 1;
+					escape = FALSE;
+
+					while (pti[i] == '$')
+					{
+						escape = TRUE;
+
+						i++;
+					}
+
+					if (pti[i] == DEFAULT_OPEN)
+					{
+						brace = TRUE;
+
+						ptt = get_arg_in_braces(ses, &pti[i], buf, GET_ALL);
+
+						i += strlen(buf) + 2;
+
+						substitute(ses, buf, temp, flags_neol);
+					}
+					else
+					{
+						ptt = temp;
+
+						while (isalnum((int) pti[i]) || pti[i] == '_')
+						{
+							*ptt++ = pti[i];
+
+							i++;
+						}
+						*ptt = 0;
+					}
+
+					if (*temp)
+					{
+						root = local_list(ses);
+
+						if ((node = search_node_list(root, temp)) == NULL)
+						{
+							root = ses->list[LIST_VARIABLE];
+
+							node = search_node_list(root, temp);
+						}
+					}
+					else
+					{
+						root = ses->list[LIST_VARIABLE];
+						node = NULL;
+					}
+
+					if (brace == FALSE && node == NULL)
+					{
+						while (*pti == '$')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					if (escape)
+					{
+						pti++;
+
+						while (*pti == '$')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					pti = get_arg_at_brackets(ses, &pti[i], temp + strlen(temp));
+
+					substitute(ses, temp, buf, flags_neol);
+
+					str = str_dup("");
+
+					get_nest_node_val(root, buf, &str, brace);
+
+					substitute(ses, str, pto, flags_neol - SUB_VAR);
+
+					pto += strlen(pto);
+
+					str_free(str);
+				}
+				else
+				{
+					if (HAS_BIT(flags, SUB_SEC) && !HAS_BIT(flags, SUB_ARG) && is_variable(ses, pti))
+					{
+						*pto++ = '\\';
+					}
+					*pto++ = *pti++;
+				}
+				break;
+
+			case '&':
+				if (HAS_BIT(flags, SUB_CMD) && (isdigit((int) pti[1]) || pti[1] == '&'))
+				{
+					if (pti[1] == '&')
+					{
+						while (pti[1] == '&')
+						{
+							*pto++ = *pti++;
+						}
+						if (isdigit((int) pti[1]))
+						{
+							pti++;
+						}
+						else
+						{
+							*pto++ = *pti++;
+						}
+					}
+					else
+					{
+						i = isdigit((int) pti[2]) ? (pti[1] - '0') * 10 + pti[2] - '0' : pti[1] - '0';
+
+						for (cnt = 0 ; gtd->cmds[i][cnt] ; cnt++)
+						{
+							*pto++ = gtd->cmds[i][cnt];
+						}
+						pti += isdigit((int) pti[2]) ? 3 : 2;
+					}
+				}
+				else if (HAS_BIT(flags, SUB_VAR) && !HAS_BIT(ses->list[LIST_VARIABLE]->flags, LIST_FLAG_IGNORE))
+				{
+					int brace = FALSE;
+					i = 1;
+					escape = FALSE;
+
+					while (pti[i] == '&')
+					{
+						escape = TRUE;
+
+						i++;
+					}
+
+					if (pti[i] == DEFAULT_OPEN)
+					{
+						brace = TRUE;
+
+						ptt = get_arg_in_braces(ses, &pti[i], buf, GET_ALL);
+
+						i += strlen(buf) + 2;
+
+						substitute(ses, buf, temp, flags_neol);
+					}
+					else
+					{
+						ptt = temp;
+
+						while (isalnum((int) pti[i]) || pti[i] == '_')
+						{
+							*ptt++ = pti[i];
+
+							i++;
+						}
+						*ptt = 0;
+					}
+
+					if (*temp)
+					{
+						root = local_list(ses);
+
+						if ((node = search_node_list(root, temp)) == NULL)
+						{
+							root = ses->list[LIST_VARIABLE];
+							node = search_node_list(root, temp);
+						}
+					}
+					else
+					{
+						root = ses->list[LIST_VARIABLE];
+						node = NULL;
+					}
+
+					if (brace == FALSE && node == NULL)
+					{
+						while (*pti == '&')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					if (escape)
+					{
+						pti++;
+
+						while (*pti == '&')
+						{
+							*pto++ = *pti++;
+						}
+						continue;
+					}
+
+					pti = get_arg_at_brackets(ses, &pti[i], temp + strlen(temp));
+
+					substitute(ses, temp, buf, flags_neol);
+
+					str = str_dup("");
+
+					get_nest_index(root, buf, &str, brace);
+
+					substitute(ses, str, pto, flags_neol - SUB_VAR);
+
+					pto += strlen(pto);
+
+					str_free(str);
+				}
+				else
+				{
+					if (HAS_BIT(flags, SUB_SEC) && !HAS_BIT(flags, SUB_ARG) && is_variable(ses, pti))
+					{
+						*pto++ = '\\';
+					}
+					*pto++ = *pti++;
 				}
 				}
+				break;
+
+			case '%':
+				if (HAS_BIT(flags, SUB_ARG) && (isdigit((int) pti[1]) || pti[1] == '%'))
+				{
+					if (pti[1] == '%')
+					{
+						while (pti[1] == '%')
+						{
+							*pto++ = *pti++;
+						}
+						pti++;
+					}
+					else
+					{
+						i = isdigit((int) pti[2]) ? (pti[1] - '0') * 10 + pti[2] - '0' : pti[1] - '0';
+
+						ptt = gtd->vars[i];
+
+						while (*ptt)
+						{
+							if (HAS_BIT(ses->flags, SES_FLAG_BIG5) && *ptt & 128 && ptt[1] != 0)
+							{
+								*pto++ = *ptt++;
+								*pto++ = *ptt++;
+								continue;
+							}
+
+							if (HAS_BIT(flags, SUB_SEC))
+							{
+								switch (*ptt)
+								{
+									case '\\':
+										*pto++ = '\\';
+										*pto++ = '\\';
+										break;
+
+									case '{':
+										*pto++ = '\\';
+										*pto++ = 'x';
+										*pto++ = '7';
+										*pto++ = 'B';
+										break;
 
 
-				*ptm = 0;
+									case '}':
+										*pto++ = '\\';
+										*pto++ = 'x';
+										*pto++ = '7';
+										*pto++ = 'D';
+										break;
 
 
-				cat_sprintf(output, "%s%s", pto, subst);
+									case '$':
+									case '&':
+									case '*':
+										if (is_variable(ses, ptt))
+										{
+											*pto++ = '\\';
+											*pto++ = *ptt;
+										}
+										else
+										{
+											*pto++ = *ptt;
+										}
+										break;
 
 
-				pto = ptm + len;
+									case '@':
+										if (is_function(ses, ptt))
+										{
+											*pto++ = '\\';
+											*pto++ = *ptt;
+										}
+										else
+										{
+											*pto++ = *ptt;
+										}
+										break;
 
 
-				show_debug(ses, LIST_SUBSTITUTE, "#DEBUG SUBSTITUTE {%s} {%s}", node->arg1, match);
-			}
-			while (check_one_regexp(ses, node, ptl, pto, 0));
+									case COMMAND_SEPARATOR:
+										*pto++ = '\\';
+										*pto++ = COMMAND_SEPARATOR;
+										break;
 
 
-			strcat(output, pto);
+									default:
+										*pto++ = *ptt;
+										break;
+								}
+								ptt++;
+							}
+							else
+							{
+								*pto++ = *ptt++;
+							}
+						}
+						pti += isdigit((int) pti[2]) ? 3 : 2;
+					}
+				}
+				else
+				{
+					*pto++ = *pti++;
+				}
+				break;
+
+			case '<':
+				if (HAS_BIT(flags, SUB_COL) && isalnum((int) pti[1]))
+				{
+					if (HAS_BIT(flags, SUB_CMP) && old[0] && !strncmp(old, pti, strlen(old)))
+					{
+						pti += strlen(old);
+					}
+					else if (isdigit((int) pti[1]) && isdigit((int) pti[2]) && isdigit((int) pti[3]) && pti[4] == '>')
+					{
+						if (pti[1] != '8' || pti[2] != '8' || pti[3] != '8')
+						{
+							*pto++ = ASCII_ESC;
+							*pto++ = '[';
+
+							switch (pti[1])
+							{
+								case '2':
+									*pto++ = '2';
+									*pto++ = '2';
+									*pto++ = ';';
+									break;
+								case '8':
+									break;
+								default:
+									*pto++ = pti[1];
+									*pto++ = ';';
+							}
+							switch (pti[2])
+							{
+								case '8':
+									break;
+								default:
+									*pto++ = '3';
+									*pto++ = pti[2];
+									*pto++ = ';';
+									break;
+							}
+							switch (pti[3])
+							{
+								case '8':
+									break;
+								default:
+									*pto++ = '4';
+									*pto++ = pti[3];
+									*pto++ = ';';
+									break;
+							}
+							pto--;
+							*pto++ = 'm';
+						}
+						pti += sprintf(old, "<%c%c%c>", pti[1], pti[2], pti[3]);
+					}
+					else if (pti[1] >= 'a' && pti[1] <= 'f' && pti[2] >= 'a' && pti[2] <= 'f' && pti[3] >= 'a' && pti[3] <= 'f' && pti[4] == '>')
+					{
+						*pto++ = ASCII_ESC;
+						*pto++ = '[';
+						*pto++ = '3';
+						*pto++ = '8';
+						*pto++ = ';';
+						*pto++ = '5';
+						*pto++ = ';';
+						cnt = 16 + (pti[1] - 'a') * 36 + (pti[2] - 'a') * 6 + (pti[3] - 'a');
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = 'm';
+						pti += sprintf(old, "<%c%c%c>", pti[1], pti[2], pti[3]);
+					}
+					else if (pti[1] >= 'A' && pti[1] <= 'F' && pti[2] >= 'A' && pti[2] <= 'F' && pti[3] >= 'A' && pti[3] <= 'F' && pti[4] == '>')
+					{
+						*pto++ = ASCII_ESC;
+						*pto++ = '[';
+						*pto++ = '4';
+						*pto++ = '8';
+						*pto++ = ';';
+						*pto++ = '5';
+						*pto++ = ';';
+						cnt = 16 + (pti[1] - 'A') * 36 + (pti[2] - 'A') * 6 + (pti[3] - 'A');
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = 'm';
+						pti += sprintf(old, "<%c%c%c>", pti[1], pti[2], pti[3]);
+					}
+					else if (pti[1] == 'g' && isdigit((int) pti[2]) && isdigit((int) pti[3]) && pti[4] == '>')
+					{
+						*pto++ = ASCII_ESC;
+						*pto++ = '[';
+						*pto++ = '3';
+						*pto++ = '8';
+						*pto++ = ';';
+						*pto++ = '5';
+						*pto++ = ';';
+						cnt = 232 + (pti[2] - '0') * 10 + (pti[3] - '0');
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = 'm';
+						pti += sprintf(old, "<g%c%c>", pti[2], pti[3]);
+					}
+					else if (pti[1] == 'G' && isdigit((int) pti[2]) && isdigit((int) pti[3]) && pti[4] == '>')
+					{
+						*pto++ = ASCII_ESC;
+						*pto++ = '[';
+						*pto++ = '4';
+						*pto++ = '8';
+						*pto++ = ';';
+						*pto++ = '5';
+						*pto++ = ';';
+						cnt = 232 + (pti[2] - '0') * 10 + (pti[3] - '0');
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = 'm';
+						pti += sprintf(old, "<G%c%c>", pti[2], pti[3]);
+					}
+					else if (toupper((int) pti[1]) == 'F' && isxdigit((int) pti[2]) && isxdigit((int) pti[3]) && isxdigit((int) pti[4]) && pti[5] == '>')
+					{
+						*pto++ = ASCII_ESC;
+						*pto++ = '[';
+						*pto++ = '3';
+						*pto++ = '8';
+						*pto++ = ';';
+						*pto++ = '2';
+						*pto++ = ';';
+						cnt  = isdigit(pti[2]) ? (pti[2] - '0') : (pti[2] - 'A' + 10);
+						cnt += cnt * 16;
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = ';';
+						cnt  = isdigit(pti[3]) ? (pti[3] - '0') : (pti[3] - 'A' + 10);
+						cnt += cnt * 16;
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = ';';
+						cnt  = isdigit(pti[4]) ? (pti[4] - '0') : (pti[4] - 'A' + 10);
+						cnt += cnt * 16;
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = 'm';
+						pti += sprintf(old, "<F%c%c%c>", pti[2], pti[3], pti[4]);
+					}
+					else if (toupper((int) pti[1]) == 'F' && isxdigit((int) pti[2]) && isxdigit((int) pti[3]) && isxdigit((int) pti[4]) && isxdigit((int) pti[5]) && isxdigit((int) pti[6]) && isxdigit((int) pti[7]) && pti[8] == '>')
+					{
+						*pto++ = ASCII_ESC;
+						*pto++ = '[';
+						*pto++ = '3';
+						*pto++ = '8';
+						*pto++ = ';';
+						*pto++ = '2';
+						*pto++ = ';';
+						cnt  = isdigit(pti[2]) ? 16 * (pti[2] - '0') : 16 * (pti[2] - 'A' + 10);
+						cnt += isdigit(pti[3]) ?  1 * (pti[3] - '0') :  1 * (pti[3] - 'A' + 10);
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = ';';
+						cnt  = isdigit(pti[4]) ? 16 * (pti[4] - '0') : 16 * (pti[4] - 'A' + 10);
+						cnt += isdigit(pti[5]) ?  1 * (pti[5] - '0') :  1 * (pti[5] - 'A' + 10);
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = ';';
+						cnt  = isdigit(pti[6]) ? 16 * (pti[6] - '0') : 16 * (pti[6] - 'A' + 10);
+						cnt += isdigit(pti[7]) ?  1 * (pti[7] - '0') :  1 * (pti[7] - 'A' + 10);
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = 'm';
+						pti += sprintf(old, "<F%c%c%c%c%c%c>", pti[2], pti[3], pti[4], pti[5], pti[6], pti[7]);
+					}
+					else if (toupper((int) pti[1]) == 'B' && isxdigit((int) pti[2]) && isxdigit((int) pti[3]) && isxdigit((int) pti[4]) && pti[5] == '>')
+					{
+						*pto++ = ASCII_ESC;
+						*pto++ = '[';
+						*pto++ = '4';
+						*pto++ = '8';
+						*pto++ = ';';
+						*pto++ = '2';
+						*pto++ = ';';
+						cnt  = isdigit(pti[2]) ? (pti[2] - '0') : (pti[2] - 'A' + 10);
+						cnt += cnt * 16;
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = ';';
+						cnt  = isdigit(pti[3]) ? (pti[3] - '0') : (pti[3] - 'A' + 10);
+						cnt += cnt * 16;
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = ';';
+						cnt  = isdigit(pti[4]) ? (pti[4] - '0') : (pti[4] - 'A' + 10);
+						cnt += cnt * 16;
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = 'm';
+						pti += sprintf(old, "<B%c%c%c>", pti[2], pti[3], pti[4]);
+					}
+					else if (toupper((int) pti[1]) == 'B' && isxdigit((int) pti[2]) && isxdigit((int) pti[3]) && isxdigit((int) pti[4]) && isxdigit((int) pti[5]) && isxdigit((int) pti[6]) && isxdigit((int) pti[7]) && pti[8] == '>')
+					{
+						*pto++ = ASCII_ESC;
+						*pto++ = '[';
+						*pto++ = '4';
+						*pto++ = '8';
+						*pto++ = ';';
+						*pto++ = '2';
+						*pto++ = ';';
+						cnt  = isdigit(pti[2]) ? 16 * (pti[2] - '0') : 16 * (pti[2] - 'A' + 10);
+						cnt += isdigit(pti[3]) ?  1 * (pti[3] - '0') :  1 * (pti[3] - 'A' + 10);
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = ';';
+						cnt  = isdigit(pti[4]) ? 16 * (pti[4] - '0') : 16 * (pti[4] - 'A' + 10);
+						cnt += isdigit(pti[5]) ?  1 * (pti[5] - '0') :  1 * (pti[5] - 'A' + 10);
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = ';';
+						cnt  = isdigit(pti[6]) ? 16 * (pti[6] - '0') : 16 * (pti[6] - 'A' + 10);
+						cnt += isdigit(pti[7]) ?  1 * (pti[7] - '0') :  1 * (pti[7] - 'A' + 10);
+						*pto++ = '0' + cnt / 100;
+						*pto++ = '0' + cnt % 100 / 10;
+						*pto++ = '0' + cnt % 10;
+						*pto++ = 'm';
+						pti += sprintf(old, "<B%c%c%c%c%c%c>", pti[2], pti[3], pti[4], pti[5], pti[6], pti[7]);
+					}
+					else
+					{
+						*pto++ = *pti++;
+					}
+				}
+				else
+				{
+					*pto++ = *pti++;
+				}
+				break;
 
 
-//			substitute(ses, output, original, SUB_VAR|SUB_FUN|SUB_COL|SUB_ESC);
 
 
-			strcpy(original, output);
+			case '\\':
+				if (HAS_BIT(flags, SUB_ESC))
+				{
+					pti++;
 
 
-			strip_vt102_codes(original, line);
+					switch (*pti)
+					{
+						case 'a':
+							*pto++ = '\a';
+							break;
+						case 'b':
+							*pto++ = '\b';
+							break;
+						case 'c':
+							if (pti[1])
+							{
+								pti++;
+								*pto++ = *pti % 32;
+							}
+							break;
+						case 'e':
+							*pto++ = '\e';
+							break;
+						case 'f':
+							*pto++ = '\f';
+							break;
+						case 'n':
+							*pto++ = '\n';
+							break;
+						case 'r':
+							*pto++ = '\r';
+							break;
+						case 't':
+							*pto++ = '\t';
+							break;
+						case 'x':
+							if (pti[1] && pti[2])
+							{
+								if (pti[1] == '0' && pti[2] == '0' && pti[3] == 0)
+								{
+									pti += 2;
+									DEL_BIT(flags, SUB_EOL);
+									DEL_BIT(flags, SUB_LNF);
+								}
+								else
+								{
+									pti++;
+									*pto++ = hex_number_8bit(pti);
+									pti++;
+								}
+							}
+							break;
+
+						case 'u':
+							if (pti[1] && pti[2] && pti[3] && pti[4])
+							{
+								pto += unicode_16_bit(&pti[1], pto);
+								pti += 4;
+							}
+							break;
+						case 'U':
+							if (pti[1] && pti[2] && pti[3] && pti[4] && pti[5] && pti[6])
+							{
+								pto += unicode_21_bit(&pti[1], pto);
+								pti += 6;
+							}
+							break;
+
+						case 'v':
+							*pto++ = '\v';
+							break;
+						case '0':
+							if (pti[1] == 0)
+							{
+								DEL_BIT(flags, SUB_EOL);
+								DEL_BIT(flags, SUB_LNF);
+							}
+							else if (pti[1] && pti[2])
+							{
+								pti++;
+								*pto++ = oct_number(pti);
+								pti++;
+							}
+							break;
+
+						case '\0':
+							DEL_BIT(flags, SUB_EOL);
+							DEL_BIT(flags, SUB_LNF);
+							continue;
+
+						default:
+							*pto++ = *pti;
+							break;
+					}
+					pti++;
+				}
+				else if (HAS_BIT(flags, SUB_SEC) && !HAS_BIT(flags, SUB_ARG))
+				{
+					*pto++ = '\\';
+					*pto++ = *pti++;
+				}
+				else if (HAS_BIT(flags, SUB_LIT))
+				{
+					*pto++ = *pti++;
+				}
+				else
+				{
+					*pto++ = *pti++;
+
+					if (*pti)
+					{
+						*pto++ = *pti++;
+					}
+				}
+				break;
+
+			default:
+				if (HAS_BIT(flags, SUB_SEC) && !HAS_BIT(flags, SUB_ARG))
+				{
+					switch (*pti)
+					{
+						case '{':
+							*pto++ = '\\';
+							*pto++ = 'x';
+							*pto++ = '7';
+							*pto++ = 'B';
+							break;
+
+						case '}':
+							*pto++ = '\\';
+							*pto++ = 'x';
+							*pto++ = '7';
+							*pto++ = 'D';
+							break;
+
+						case COMMAND_SEPARATOR:
+							*pto++ = '\\';
+							*pto++ = COMMAND_SEPARATOR;
+							break;
+
+						default:
+							*pto++ = *pti;
+							break;
+					}
+					pti++;
+				}
+				else
+				{
+					*pto++ = *pti++;
+				}
+				break;
 		}
 		}
 	}
 	}
+	pop_call();
+	return 0;
 }
 }
-

+ 0 - 56
src/tab.c

@@ -1,56 +0,0 @@
-/******************************************************************************
-*   This file is part of TinTin++                                             *
-*                                                                             *
-*   Copyright 2004-2019 Igor van den Hoven                                    *
-*                                                                             *
-*   TinTin++ is free software; you can redistribute it and/or modify          *
-*   it under the terms of the GNU General Public License as published by      *
-*   the Free Software Foundation; either version 3 of the License, or         *
-*   (at your option) any later version.                                       *
-*                                                                             *
-*   This program is distributed in the hope that it will be useful,           *
-*   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
-*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
-*   GNU General Public License for more details.                              *
-*                                                                             *
-*                                                                             *
-*   You should have received a copy of the GNU General Public License         *
-*   along with TinTin++.  If not, see https://www.gnu.org/licenses.           *
-******************************************************************************/
-
-/******************************************************************************
-*                (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t                 *
-*                                                                             *
-*                      coded by Igor van den Hoven 2006                       *
-******************************************************************************/
-
-
-#include "tintin.h"
-
-
-DO_COMMAND(do_tab)
-{
-	char arg1[BUFFER_SIZE];
-
-	sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
-
-	if (*arg1 == 0)
-	{
-		show_list(ses->list[LIST_TAB], 0);
-	}
-	else
-	{
-		update_node_list(ses->list[LIST_TAB], arg1, "", "0", "");
-
-		show_message(ses, LIST_TAB, "#OK. {%s} IS NOW A TAB.", arg1);
-	}
-	return ses;
-}
-
-
-DO_COMMAND(do_untab)
-{
-	delete_node_with_wild(ses, LIST_TAB, arg);
-
-	return ses;
-}

+ 135 - 12
src/tables.c

@@ -37,6 +37,7 @@ struct command_type command_table[] =
 	{    "bell",              do_bell,              TOKEN_TYPE_COMMAND },
 	{    "bell",              do_bell,              TOKEN_TYPE_COMMAND },
 	{    "break",             do_nop,               TOKEN_TYPE_BREAK   },
 	{    "break",             do_nop,               TOKEN_TYPE_BREAK   },
 	{    "buffer",            do_buffer,            TOKEN_TYPE_COMMAND },
 	{    "buffer",            do_buffer,            TOKEN_TYPE_COMMAND },
+	{    "button",            do_button,            TOKEN_TYPE_COMMAND },
 	{    "case",              do_nop,               TOKEN_TYPE_CASE    },
 	{    "case",              do_nop,               TOKEN_TYPE_CASE    },
 	{    "chat",              do_chat,              TOKEN_TYPE_COMMAND },
 	{    "chat",              do_chat,              TOKEN_TYPE_COMMAND },
 	{    "class",             do_class,             TOKEN_TYPE_COMMAND },
 	{    "class",             do_class,             TOKEN_TYPE_COMMAND },
@@ -48,6 +49,7 @@ struct command_type command_table[] =
 	{    "debug",             do_debug,             TOKEN_TYPE_COMMAND },
 	{    "debug",             do_debug,             TOKEN_TYPE_COMMAND },
 	{    "default",           do_nop,               TOKEN_TYPE_DEFAULT },
 	{    "default",           do_nop,               TOKEN_TYPE_DEFAULT },
 	{    "delay",             do_delay,             TOKEN_TYPE_COMMAND },
 	{    "delay",             do_delay,             TOKEN_TYPE_COMMAND },
+	{    "draw",              do_draw,              TOKEN_TYPE_COMMAND },
 	{    "echo",              do_echo,              TOKEN_TYPE_COMMAND },
 	{    "echo",              do_echo,              TOKEN_TYPE_COMMAND },
 	{    "else",              do_nop,               TOKEN_TYPE_ELSE    },
 	{    "else",              do_nop,               TOKEN_TYPE_ELSE    },
 	{    "elseif",            do_nop,               TOKEN_TYPE_ELSEIF  },
 	{    "elseif",            do_nop,               TOKEN_TYPE_ELSEIF  },
@@ -104,6 +106,7 @@ struct command_type command_table[] =
 	{    "ticker",            do_tick,              TOKEN_TYPE_COMMAND },
 	{    "ticker",            do_tick,              TOKEN_TYPE_COMMAND },
 	{    "unaction",          do_unaction,          TOKEN_TYPE_COMMAND },
 	{    "unaction",          do_unaction,          TOKEN_TYPE_COMMAND },
 	{    "unalias",           do_unalias,           TOKEN_TYPE_COMMAND },
 	{    "unalias",           do_unalias,           TOKEN_TYPE_COMMAND },
+	{    "unbutton",          do_unbutton,          TOKEN_TYPE_COMMAND },
 	{    "undelay",           do_undelay,           TOKEN_TYPE_COMMAND },
 	{    "undelay",           do_undelay,           TOKEN_TYPE_COMMAND },
 	{    "unevent",           do_unevent,           TOKEN_TYPE_COMMAND },
 	{    "unevent",           do_unevent,           TOKEN_TYPE_COMMAND },
 	{    "unfunction",        do_unfunction,        TOKEN_TYPE_COMMAND },
 	{    "unfunction",        do_unfunction,        TOKEN_TYPE_COMMAND },
@@ -127,8 +130,9 @@ struct command_type command_table[] =
 
 
 struct list_type list_table[LIST_MAX] =
 struct list_type list_table[LIST_MAX] =
 {
 {
-	{    "ACTION",            "ACTIONS",            SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX },
-	{    "ALIAS",             "ALIASES",            SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX },
+	{    "ACTION",            "ACTIONS",            SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX|LIST_FLAG_PRIORITY },
+	{    "ALIAS",             "ALIASES",            SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX|LIST_FLAG_PRIORITY },
+	{    "BUTTON",            "BUTTONS",            SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_PRIORITY },
 	{    "CLASS",             "CLASSES",            SORT_PRIORITY,    2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_INHERIT                                 },
 	{    "CLASS",             "CLASSES",            SORT_PRIORITY,    2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_INHERIT                                 },
 	{    "COMMAND",           "COMMANDS",           SORT_APPEND,      1,  LIST_FLAG_MESSAGE                                                                  },
 	{    "COMMAND",           "COMMANDS",           SORT_APPEND,      1,  LIST_FLAG_MESSAGE                                                                  },
 	{    "CONFIG",            "CONFIGURATIONS",     SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_INHERIT                 },
 	{    "CONFIG",            "CONFIGURATIONS",     SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_INHERIT                 },
@@ -136,13 +140,13 @@ struct list_type list_table[LIST_MAX] =
 	{    "EVENT",             "EVENTS",             SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "EVENT",             "EVENTS",             SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "FUNCTION",          "FUNCTIONS",          SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "FUNCTION",          "FUNCTIONS",          SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "GAG",               "GAGS",               SORT_ALPHA,       1,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "GAG",               "GAGS",               SORT_ALPHA,       1,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
-	{    "HIGHLIGHT",         "HIGHLIGHTS",         SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX },
+	{    "HIGHLIGHT",         "HIGHLIGHTS",         SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX|LIST_FLAG_PRIORITY },
 	{    "HISTORY",           "HISTORIES",          SORT_APPEND,      1,  LIST_FLAG_MESSAGE                                                                  },
 	{    "HISTORY",           "HISTORIES",          SORT_APPEND,      1,  LIST_FLAG_MESSAGE                                                                  },
 	{    "MACRO",             "MACROS",             SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "MACRO",             "MACROS",             SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "PATH",              "PATHS",              SORT_APPEND,      2,  LIST_FLAG_MESSAGE                                                                  },
 	{    "PATH",              "PATHS",              SORT_APPEND,      2,  LIST_FLAG_MESSAGE                                                                  },
 	{    "PATHDIR",           "PATHDIRS",           SORT_ALPHA,       3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "PATHDIR",           "PATHDIRS",           SORT_ALPHA,       3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
-	{    "PROMPT",            "PROMPTS",            SORT_PRIORITY,    4,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX },
-	{    "SUBSTITUTE",        "SUBSTITUTES",        SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX },
+	{    "PROMPT",            "PROMPTS",            SORT_PRIORITY,    4,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX|LIST_FLAG_PRIORITY },
+	{    "SUBSTITUTE",        "SUBSTITUTES",        SORT_PRIORITY,    3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX|LIST_FLAG_PRIORITY },
 	{    "TAB",               "TABS",               SORT_ALPHA,       1,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "TAB",               "TABS",               SORT_ALPHA,       1,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "TICKER",            "TICKERS",            SORT_ALPHA,       3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "TICKER",            "TICKERS",            SORT_ALPHA,       3,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "VARIABLE",          "VARIABLES",          SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_NEST }
 	{    "VARIABLE",          "VARIABLES",          SORT_ALPHA,       2,  LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_NEST }
@@ -258,10 +262,10 @@ struct config_type config_table[] =
 	},
 	},
 
 
 	{
 	{
-		"LOG",
+		"LOG MODE",
 		"",
 		"",
-		"The data format of the log files",
-		config_log
+		"The data type mode of log files",
+		config_logmode
 	},
 	},
 
 
 	{
 	{
@@ -334,6 +338,13 @@ struct config_type config_table[] =
 		config_speedwalk
 		config_speedwalk
 	},
 	},
 
 
+	{
+		"TELNET",
+		"TELNET support is enabled.",
+		"TELNET support is disabled.",
+		config_telnet
+	},
+
 	{
 	{
 		"TINTIN CHAR",
 		"TINTIN CHAR",
 		"",
 		"",
@@ -558,7 +569,7 @@ struct array_type array_table[] =
 
 
 struct map_type map_table[] =
 struct map_type map_table[] =
 {
 {
-	{     "AT",               map_at,              0,              1    },
+	{     "AT",               map_at,              0,              2    },
 	{     "COLOR",            map_color,           MAP_FLAG_VTMAP, 1    },
 	{     "COLOR",            map_color,           MAP_FLAG_VTMAP, 1    },
 	{     "CREATE",           map_create,          MAP_FLAG_VTMAP, 0    },
 	{     "CREATE",           map_create,          MAP_FLAG_VTMAP, 0    },
 	{     "DEBUG",            map_debug,           0,              2    },
 	{     "DEBUG",            map_debug,           0,              2    },
@@ -594,7 +605,7 @@ struct map_type map_table[] =
 	{     "UNDO",             map_undo,            MAP_FLAG_VTMAP, 2    },
 	{     "UNDO",             map_undo,            MAP_FLAG_VTMAP, 2    },
 	{     "UNINSERT",         map_uninsert,        MAP_FLAG_VTMAP, 2    },
 	{     "UNINSERT",         map_uninsert,        MAP_FLAG_VTMAP, 2    },
 	{     "UNLINK",           map_unlink,          MAP_FLAG_VTMAP, 2    },
 	{     "UNLINK",           map_unlink,          MAP_FLAG_VTMAP, 2    },
-	{     "UPDATE",           map_update,          MAP_FLAG_VTMAP, 2    },
+	{     "UPDATE",           map_update,          0,              0    },
 	{     "VNUM",             map_vnum,            MAP_FLAG_VTMAP, 2    },
 	{     "VNUM",             map_vnum,            MAP_FLAG_VTMAP, 2    },
 	{     "WRITE",            map_write,           0,              1    },
 	{     "WRITE",            map_write,           0,              1    },
 	{     "",                 NULL,                0    }
 	{     "",                 NULL,                0    }
@@ -954,6 +965,113 @@ struct cursor_type cursor_table[] =
 	}
 	}
 };
 };
 
 
+struct draw_type draw_table[] =
+{
+	{
+		"BLANK SQUARE",
+		"Draw a blank square.",
+		draw_blank
+	},
+
+	{
+		"BOTTOM SIDE",
+		"Draw the bottom side of a box.",
+		draw_bot_line
+	},
+
+	{
+		"BOX",
+		"Draw a box.",
+		draw_box
+	},
+
+	{
+		"BOX TEXT",
+		"Draw a box with given text.",
+		draw_box_text
+	},
+
+	{
+		"CENTER LEFT LINE",
+		"Draw the center left line of two boxes.",
+		draw_center_left_line
+	},
+
+	{
+		"CENTER RIGHT LINE",
+		"Draw the center right line of two boxes.",
+		draw_center_right_line
+	},
+
+	{
+		"HORIZONTAL LINE",
+		"Draw a horizontal line.",
+		draw_horizontal_line
+	},
+
+	{
+		"LEFT SIDE",
+		"Draw the left side of a box.",
+		draw_left_line
+	},
+
+
+	{
+		"MIDDLE TOP LINE",
+		"Draw the middle top line of two boxes.",
+		draw_middle_top_line
+	},
+
+	{
+		"MIDDLE BOTTOM LINE",
+		"Draw the middle bottom line of two boxes.",
+		draw_middle_bot_line
+	},
+
+	{
+		"RIGHT SIDE",
+		"Draw the right side of a box.",
+		draw_right_line
+	},
+	
+	{
+		"SIDE LINES",
+		"Draw the left and right sides of a box.",
+		draw_side_lines
+	},
+
+	{
+		"SIDE LINES TEXT",
+		"Draw the side lines of a box with given text.",
+		draw_side_lines_text
+	},
+
+
+	{
+		"TOP LINE",
+		"Draw the bottom lines of a box.",
+		draw_top_line
+	},
+
+	{
+		"TEXT",
+		"Draw given text without a frame.",
+		draw_text
+	},
+
+	{
+		"VERTICAL LINE",
+		"Draw a vertical line.",
+		draw_vertical_line
+	},
+
+	{
+		"",
+		"",
+		NULL
+	}
+};
+
 struct screen_type screen_table[] =
 struct screen_type screen_table[] =
 {
 {
 	{
 	{
@@ -968,7 +1086,7 @@ struct screen_type screen_table[] =
 		"CLEAR",
 		"CLEAR",
 		"Clear the screen.",
 		"Clear the screen.",
 		SCREEN_FLAG_GET_ONE,
 		SCREEN_FLAG_GET_ONE,
-		SCREEN_FLAG_GET_ONE,
+		SCREEN_FLAG_GET_NONE,
 		SCREEN_FLAG_CSIP,
 		SCREEN_FLAG_CSIP,
 		screen_clear
 		screen_clear
 	},
 	},
@@ -1086,7 +1204,7 @@ struct screen_type screen_table[] =
 		screen_save
 		screen_save
 	},
 	},
 	{
 	{
-		"Scrollbar",
+		"SCROLLBAR",
 		"Scrollbar settings.",
 		"Scrollbar settings.",
 		SCREEN_FLAG_GET_ONE,
 		SCREEN_FLAG_GET_ONE,
 		SCREEN_FLAG_GET_ONE,
 		SCREEN_FLAG_GET_ONE,
@@ -1128,7 +1246,9 @@ struct event_type event_table[] =
 	{    "CATCH ",                                 "Triggers on catch events."               },
 	{    "CATCH ",                                 "Triggers on catch events."               },
 	{    "CHAT MESSAGE",                           "Triggers on any chat related message."   },
 	{    "CHAT MESSAGE",                           "Triggers on any chat related message."   },
 	{    "CLASS ACTIVATED",                        "Triggers on class activations."          },
 	{    "CLASS ACTIVATED",                        "Triggers on class activations."          },
+	{    "CLASS CREATED",                          "Triggers on class creation."             },
 	{    "CLASS DEACTIVATED",                      "Triggers on class deactivations."        },
 	{    "CLASS DEACTIVATED",                      "Triggers on class deactivations."        },
+	{    "CLASS DESTROYED",                        "Triggers on class destruction."          },
 	{    "DATE",                                   "Triggers on the given date."             },
 	{    "DATE",                                   "Triggers on the given date."             },
 	{    "DAY",                                    "Triggers each day or given day."         },
 	{    "DAY",                                    "Triggers each day or given day."         },
 	{    "DOUBLE-CLICKED ",                        "Triggers when mouse is double-clicked"   },
 	{    "DOUBLE-CLICKED ",                        "Triggers when mouse is double-clicked"   },
@@ -1232,9 +1352,11 @@ struct path_type path_table[] =
 
 
 struct line_type line_table[] =
 struct line_type line_table[] =
 {
 {
+	{    "BACKGROUND",        line_background        },
 	{    "GAG",               line_gag               },
 	{    "GAG",               line_gag               },
 	{    "IGNORE",            line_ignore            },
 	{    "IGNORE",            line_ignore            },
 	{    "LOG",               line_log               },
 	{    "LOG",               line_log               },
+	{    "LOGMODE",           line_logmode           },
 	{    "LOGVERBATIM",       line_logverbatim       },
 	{    "LOGVERBATIM",       line_logverbatim       },
 	{    "QUIET",             line_quiet             },
 	{    "QUIET",             line_quiet             },
 	{    "STRIP",             line_strip             },
 	{    "STRIP",             line_strip             },
@@ -1770,6 +1892,7 @@ struct map_group_type map_group_table[] =
 	{ "NESW MISC",			"NESW MISC",		1, 1,	1, 1,	0, 0,	"{\\u2B51} {\\u2012} {\\u2507} {\\u254D}" },
 	{ "NESW MISC",			"NESW MISC",		1, 1,	1, 1,	0, 0,	"{\\u2B51} {\\u2012} {\\u2507} {\\u254D}" },
 	{ "NESW CURVED",		"NESW CURVED",		1, 1,	1, 1,	0, 0,	"{\\u2570} {\\u256D} {\\u256E} {\\u256F}" },
 	{ "NESW CURVED",		"NESW CURVED",		1, 1,	1, 1,	0, 0,	"{\\u2570} {\\u256D} {\\u256E} {\\u256F}" },
 	{ "NESW DIRS",			"NESW DIRS",		1, 1,	1, 1,	0, 0,	"{\\u2191} {\\u2B08} {\\u2B95} {\\u2b0A} {\\u2193} {\\u2B0B} {\\u2B05} {\\u2B09}" },
 	{ "NESW DIRS",			"NESW DIRS",		1, 1,	1, 1,	0, 0,	"{\\u2191} {\\u2B08} {\\u2B95} {\\u2b0A} {\\u2193} {\\u2B0B} {\\u2B05} {\\u2B09}" },
+//	{ "NESW DIRS",			"NESW DIRS",		1, 1,	1, 1,	0, 0,	"{\\U01F805}{\\u2B08}{\\U01F806}{\\u2b0A}{\\U01F807}{\\u2B0B}{\\U01F804}{\\u2B09}" }, poor cross-platform support.
 
 
 	{ "MUDFONT",			"MUDFONT",		1, 2,	1, 2,	0, 0,	"" },
 	{ "MUDFONT",			"MUDFONT",		1, 2,	1, 2,	0, 0,	"" },
 	{ "MUDFONT PRIVATE",		"MUDFONT",		1, 2,	1, 2,	0, 0,	"{\\uE000} {\\uE001} {\\uE002} {\\uE003} {\\uE004} {\\uE005} {\\uE006} {\\uE007} {\\uE008} {\\uE009} {\\uE00A} {\\uE00B} {\\uE00C} {\\uE00D} {\\uE00E} {\\uE00F} {\\uE010} {\\uE011} {\\uE012} {\\uE013} {\\uE014} {\\uE015} {\\uE016} {\\uE017} {\\uE018} {\\uE019} {\\uE01A} {\\uE01B} {\\uE01C} {\\uE01D} {\\uE01E} {\\uE01F} {\\uE020} {\\uE021} {\\uE022} {\\uE023} {\\uE024} {\\uE025} {\\uE026} {\\uE027} {\\uE028} {\\uE029} {\\uE02A} {\\uE02B} {\\uE02C} {\\uE02D} {\\uE02E} {\\uE02F} {\\uE030} {\\uE031} {\\uE032} {\\uE033} {\\uE034} {\\uE035} {\\uE036} {\\uE037} {\\uE038} {\\uE039} {\\uE03A} {\\uE03B} {\\uE03C} {\\uE03D} {\\uE03E} {\\uE03F} {\\uE040} {\\uE041} {\\uE042} {\\uE043} {\\uE044} {\\uE045} {\\uE046} {\\uE047} {\\uE048} {\\uE049} {\\uE04A} {\\uE04B} {\\uE04C} {\\uE04D} {\\uE04E} {\\uE04F} {\\uE050} {\\uE051} {\\uE052} {\\uE053} {\\uE054} {\\uE055} {\\uE056} {\\uE057} {\\uE058} {\\uE059} {\\uE05A} {\\uE05B} {\\uE05C} {\\uE05D} {\\uE05E} {\\uE05F} {\\uE060} {\\uE061} {\\uE062} {\\uE063} {\\uE064} {\\uE065} {\\uE066} {\\uE067} {\\uE068} {\\uE069} {\\uE06A} {\\uE06B} {\\uE06C} {\\uE06D} {\\uE06E} {\\uE06F} {\\uE070} {\\uE071} {\\uE072} {\\uE073} {\\uE074} {\\uE075} {\\uE076} {\\uE077} {\\uE078} {\\uE079} {\\uE07A} {\\uE07B} {\\uE07C} {\\uE07D} {\\uE07E} {\\uE07F} {\\uE080} {\\uE081} {\\uE082} {\\uE083} {\\uE084} {\\uE085} {\\uE086} {\\uE087}" },
 	{ "MUDFONT PRIVATE",		"MUDFONT",		1, 2,	1, 2,	0, 0,	"{\\uE000} {\\uE001} {\\uE002} {\\uE003} {\\uE004} {\\uE005} {\\uE006} {\\uE007} {\\uE008} {\\uE009} {\\uE00A} {\\uE00B} {\\uE00C} {\\uE00D} {\\uE00E} {\\uE00F} {\\uE010} {\\uE011} {\\uE012} {\\uE013} {\\uE014} {\\uE015} {\\uE016} {\\uE017} {\\uE018} {\\uE019} {\\uE01A} {\\uE01B} {\\uE01C} {\\uE01D} {\\uE01E} {\\uE01F} {\\uE020} {\\uE021} {\\uE022} {\\uE023} {\\uE024} {\\uE025} {\\uE026} {\\uE027} {\\uE028} {\\uE029} {\\uE02A} {\\uE02B} {\\uE02C} {\\uE02D} {\\uE02E} {\\uE02F} {\\uE030} {\\uE031} {\\uE032} {\\uE033} {\\uE034} {\\uE035} {\\uE036} {\\uE037} {\\uE038} {\\uE039} {\\uE03A} {\\uE03B} {\\uE03C} {\\uE03D} {\\uE03E} {\\uE03F} {\\uE040} {\\uE041} {\\uE042} {\\uE043} {\\uE044} {\\uE045} {\\uE046} {\\uE047} {\\uE048} {\\uE049} {\\uE04A} {\\uE04B} {\\uE04C} {\\uE04D} {\\uE04E} {\\uE04F} {\\uE050} {\\uE051} {\\uE052} {\\uE053} {\\uE054} {\\uE055} {\\uE056} {\\uE057} {\\uE058} {\\uE059} {\\uE05A} {\\uE05B} {\\uE05C} {\\uE05D} {\\uE05E} {\\uE05F} {\\uE060} {\\uE061} {\\uE062} {\\uE063} {\\uE064} {\\uE065} {\\uE066} {\\uE067} {\\uE068} {\\uE069} {\\uE06A} {\\uE06B} {\\uE06C} {\\uE06D} {\\uE06E} {\\uE06F} {\\uE070} {\\uE071} {\\uE072} {\\uE073} {\\uE074} {\\uE075} {\\uE076} {\\uE077} {\\uE078} {\\uE079} {\\uE07A} {\\uE07B} {\\uE07C} {\\uE07D} {\\uE07E} {\\uE07F} {\\uE080} {\\uE081} {\\uE082} {\\uE083} {\\uE084} {\\uE085} {\\uE086} {\\uE087}" },

+ 18 - 15
src/telopt_client.c

@@ -216,7 +216,7 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 		cpsrc = src;
 		cpsrc = src;
 	}
 	}
 
 
-	if (HAS_BIT(ses->flags, SES_FLAG_LOGLEVEL) && ses->logfile)
+	if (HAS_BIT(ses->logmode, LOG_FLAG_LOW) && ses->logfile)
 	{
 	{
 		fwrite(cpsrc, 1, cplen, ses->logfile);
 		fwrite(cpsrc, 1, cplen, ses->logfile);
 
 
@@ -244,7 +244,7 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 
 
 	while (cplen > 0)
 	while (cplen > 0)
 	{
 	{
-		if (!HAS_BIT(ses->flags, SES_FLAG_RUN) && *cpsrc == IAC)
+		if (*cpsrc == IAC && HAS_BIT(ses->flags, SES_FLAG_TELNET) && !HAS_BIT(ses->flags, SES_FLAG_RUN))
 		{
 		{
 			skip = 2;
 			skip = 2;
 
 
@@ -435,7 +435,7 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 
 
 			switch (*cpsrc)
 			switch (*cpsrc)
 			{
 			{
-				case '\0':
+				case ASCII_NUL:
 					cpsrc++;
 					cpsrc++;
 					cplen--;
 					cplen--;
 					continue;
 					continue;
@@ -446,8 +446,8 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 					cplen--;
 					cplen--;
 					continue;
 					continue;
 
 
-				case '\r':
-					if (cplen > 1 && cpsrc[1] == '\n')
+				case ASCII_CR:
+					if (cplen > 1 && cpsrc[1] == ASCII_LF)
 					{
 					{
 						cpsrc++;
 						cpsrc++;
 						cplen--;
 						cplen--;
@@ -455,7 +455,7 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 					}
 					}
 					break;
 					break;
 
 
-				case '\n':
+				case ASCII_LF:
 					if (HAS_BIT(ses->telopts, TELOPT_FLAG_PROMPT))
 					if (HAS_BIT(ses->telopts, TELOPT_FLAG_PROMPT))
 					{
 					{
 						DEL_BIT(ses->telopts, TELOPT_FLAG_PROMPT);
 						DEL_BIT(ses->telopts, TELOPT_FLAG_PROMPT);
@@ -465,7 +465,7 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 					gtd->mud_output_len++;
 					gtd->mud_output_len++;
 					cplen--;
 					cplen--;
 
 
-					while (*cpsrc == '\r')
+					while (*cpsrc == ASCII_CR)
 					{
 					{
 						cpsrc++;
 						cpsrc++;
 						cplen--;
 						cplen--;
@@ -474,7 +474,7 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 					continue;
 					continue;
 
 
 				default:
 				default:
-					if (cpsrc[0] == ESCAPE)
+					if (cpsrc[0] == ASCII_ESC)
 					{
 					{
 						if (cplen >= 2 && cpsrc[1] == 'Z')
 						if (cplen >= 2 && cpsrc[1] == 'Z')
 						{
 						{
@@ -753,29 +753,32 @@ int client_recv_do_naws(struct session *ses, int cplen, unsigned char *cpsrc)
 int client_send_sb_naws(struct session *ses, int cplen, unsigned char *cpsrc)
 int client_send_sb_naws(struct session *ses, int cplen, unsigned char *cpsrc)
 {
 {
 	int rows;
 	int rows;
+	int cols;
 
 
 	rows = HAS_BIT(ses->flags, SES_FLAG_SPLIT) ? ses->bot_row - ses->top_row + 1 : gtd->screen->rows;
 	rows = HAS_BIT(ses->flags, SES_FLAG_SPLIT) ? ses->bot_row - ses->top_row + 1 : gtd->screen->rows;
 
 
+	cols = ses->wrap > 0 ? ses->wrap : gtd->screen->cols;
+
 	// Properly handle row and colum size of 255
 	// Properly handle row and colum size of 255
 
 
-	if (gtd->screen->cols % 256 == IAC && gtd->screen->rows % 256 == IAC)
+	if (cols % 256 == IAC && gtd->screen->rows % 256 == IAC)
 	{
 	{
-		telnet_printf(ses, 11, "%c%c%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, gtd->screen->cols / 256, IAC, gtd->screen->cols % 256, rows / 256, IAC, rows % 256, IAC, SE);
+		telnet_printf(ses, 11, "%c%c%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, cols / 256, IAC, cols % 256, rows / 256, IAC, rows % 256, IAC, SE);
 	}
 	}
-	else if (gtd->screen->cols % 256 == IAC)
+	else if (cols % 256 == IAC)
 	{
 	{
-		telnet_printf(ses, 10, "%c%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, gtd->screen->cols / 256, IAC, gtd->screen->cols % 256, rows / 256, rows % 256, IAC, SE);
+		telnet_printf(ses, 10, "%c%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, cols / 256, IAC, cols % 256, rows / 256, rows % 256, IAC, SE);
 	}
 	}
 	else if (gtd->screen->rows % 256 == IAC)
 	else if (gtd->screen->rows % 256 == IAC)
 	{
 	{
-		telnet_printf(ses, 10, "%c%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, gtd->screen->cols / 256, gtd->screen->cols % 256, rows / 256, IAC, rows % 256, IAC, SE);
+		telnet_printf(ses, 10, "%c%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, cols / 256, cols % 256, rows / 256, IAC, rows % 256, IAC, SE);
 	}
 	}
 	else
 	else
 	{
 	{
-		telnet_printf(ses, 9, "%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, gtd->screen->cols / 256, gtd->screen->cols % 256, rows / 256, rows % 256, IAC, SE);
+		telnet_printf(ses, 9, "%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, cols / 256, cols % 256, rows / 256, rows % 256, IAC, SE);
 	}
 	}
 
 
-	client_telopt_debug(ses, "SENT IAC SB NAWS %d %d %d %d", gtd->screen->cols / 256, gtd->screen->cols % 256, gtd->screen->rows / 256, gtd->screen->rows % 256);
+	client_telopt_debug(ses, "SENT IAC SB NAWS %d %d %d %d", cols / 256, cols % 256, gtd->screen->rows / 256, gtd->screen->rows % 256);
 
 
 	return 3;
 	return 3;
 }
 }

+ 1 - 1
src/telopt_server.c

@@ -792,7 +792,7 @@ int process_do_msdp(struct session *ses, struct port_data *buddy, unsigned char
 
 
 	for (index = 0 ; index < gtd->msdp_table_size ; index++)
 	for (index = 0 ; index < gtd->msdp_table_size ; index++)
 	{
 	{
-		buddy->msdp_data[index] = (struct msdp_data *) calloc(1, sizeof(struct msdp_data *));
+		buddy->msdp_data[index] = (struct msdp_data *) calloc(1, sizeof(struct msdp_data));
 
 
 		buddy->msdp_data[index]->flags = msdp_table[index].flags;
 		buddy->msdp_data[index]->flags = msdp_table[index].flags;
 		buddy->msdp_data[index]->value = strdup("");
 		buddy->msdp_data[index]->value = strdup("");

+ 19 - 26
src/text.c

@@ -54,7 +54,7 @@ void print_line(struct session *ses, char **str, int prompt)
 		str_cpy(str, out);
 		str_cpy(str, out);
 	}
 	}
 
 
-	if (HAS_BIT(ses->flags, SES_FLAG_WORDWRAP))
+	if (ses->wrap)
 	{
 	{
 		word_wrap(ses, *str, out, TRUE);
 		word_wrap(ses, *str, out, TRUE);
 	}
 	}
@@ -129,12 +129,12 @@ int word_wrap(struct session *ses, char *textin, char *textout, int display)
 			lis = pti;
 			lis = pti;
 		}
 		}
 
 
-		if (ses->cur_col > gtd->screen->cols)
+		if (ses->cur_col > gtd->screen->cols || (ses->wrap > 0 && ses->cur_col > ses->wrap))
 		{
 		{
 			cnt++;
 			cnt++;
 			ses->cur_col = 1;
 			ses->cur_col = 1;
 
 
-			if (HAS_BIT(ses->flags, SES_FLAG_WORDWRAP))
+			if (ses->wrap)
 			{
 			{
 				if (pto - los > 15 || !SCROLL(ses))
 				if (pto - los > 15 || !SCROLL(ses))
 				{
 				{
@@ -190,14 +190,14 @@ int word_wrap(struct session *ses, char *textin, char *textout, int display)
 	return (cnt + 1);
 	return (cnt + 1);
 }
 }
 
 
-// store whatever falls inbetween skip and keep. Used by #buffer
+// store whatever falls inbetween skip and keep. Used by #buffer not checking SCROLL().
 
 
-int word_wrap_split(struct session *ses, char *textin, char *textout, int display, int start, int end)
+int word_wrap_split(struct session *ses, char *textin, char *textout, int wrap, int start, int end)
 {
 {
 	char *pti, *pto, *lis, *los, *chi, *cho, *ptb;
 	char *pti, *pto, *lis, *los, *chi, *cho, *ptb;
-	int width, size, i = 0, cnt = 0;
+	int width, size, i = 0, lines = 0;
 
 
-	push_call("word_wrap_split(%s,%p,%p,%d,%d)",ses->name, textin,textout, start, end);
+	push_call("word_wrap_split(%s,%p,%p,%d,%d,%d)",ses->name,textin,textout,wrap,start,end);
 
 
 	pti = chi = lis = textin;
 	pti = chi = lis = textin;
 	pto = cho = los = textout;
 	pto = cho = los = textout;
@@ -208,23 +208,16 @@ int word_wrap_split(struct session *ses, char *textin, char *textout, int displa
 	{
 	{
 		if (skip_vt102_codes(pti))
 		if (skip_vt102_codes(pti))
 		{
 		{
-//			if (cnt >= start && cnt < end)
+			for (i = skip_vt102_codes(pti) ; i > 0 ; i--)
 			{
 			{
-				for (i = skip_vt102_codes(pti) ; i > 0 ; i--)
-				{
-					*pto++ = *pti++;
-				}
+				*pto++ = *pti++;
 			}
 			}
-/*			else
-			{
-				pti += skip_vt102_codes(pti);
-			}*/
 			continue;
 			continue;
 		}
 		}
 
 
 		if (*pti == '\n')
 		if (*pti == '\n')
 		{
 		{
-			if (cnt++ >= start && cnt < end)
+			if (lines++ >= start && lines < end)
 			{
 			{
 				*pto++ = *pti++;
 				*pto++ = *pti++;
 			}
 			}
@@ -246,16 +239,16 @@ int word_wrap_split(struct session *ses, char *textin, char *textout, int displa
 			lis = pti;
 			lis = pti;
 		}
 		}
 
 
-		if (ses->cur_col > gtd->screen->cols)
+		if (ses->cur_col > gtd->screen->cols || (wrap > 0 && ses->cur_col > wrap))
 		{
 		{
-			cnt++;
+			lines++;
 			ses->cur_col = 1;
 			ses->cur_col = 1;
 
 
-			if (HAS_BIT(ses->flags, SES_FLAG_WORDWRAP))
+			if (wrap)
 			{
 			{
-				if (pto - los > 15 || !SCROLL(ses))
+				if (pto - los > 15 || ses->cur_col < 15)
 				{
 				{
-					if (cnt >= start && cnt < end)
+					if (lines >= start && lines < end)
 					{
 					{
 						*pto++ = '\n';
 						*pto++ = '\n';
 					}
 					}
@@ -264,7 +257,7 @@ int word_wrap_split(struct session *ses, char *textin, char *textout, int displa
 				}
 				}
 				else if (lis != chi) // infinite VT loop detection
 				else if (lis != chi) // infinite VT loop detection
 				{
 				{
-					if (cnt >= start && cnt < end)
+					if (lines >= start && lines < end)
 					{
 					{
 						pto = los;
 						pto = los;
 						*pto++ = '\n';
 						*pto++ = '\n';
@@ -274,7 +267,7 @@ int word_wrap_split(struct session *ses, char *textin, char *textout, int displa
 				}
 				}
 				else if (los != cho)
 				else if (los != cho)
 				{
 				{
-					if (cnt >= start && cnt < end)
+					if (lines >= start && lines < end)
 					{
 					{
 						pto = cho = los;
 						pto = cho = los;
 						pto++;
 						pto++;
@@ -314,7 +307,7 @@ int word_wrap_split(struct session *ses, char *textin, char *textout, int displa
 				ses->cur_col++;
 				ses->cur_col++;
 			}
 			}
 
 
-			if (cnt < start || cnt >= end)
+			if (lines < start || lines >= end)
 			{
 			{
 				pto = ptb;
 				pto = ptb;
 			}
 			}
@@ -323,6 +316,6 @@ int word_wrap_split(struct session *ses, char *textin, char *textout, int displa
 	*pto = 0;
 	*pto = 0;
 
 
 	pop_call();
 	pop_call();
-	return (cnt + 1);
+	return (lines + 1);
 }
 }
 
 

Разница между файлами не показана из-за своего большого размера
+ 361 - 282
src/tintin.h


+ 1 - 1
src/tokenize.c

@@ -924,7 +924,7 @@ struct scriptnode *parse_script(struct scriptroot *root, int lvl, struct scriptn
 			case TOKEN_TYPE_REGEX:
 			case TOKEN_TYPE_REGEX:
 				split = NULL;
 				split = NULL;
 
 
-				token->regex->val = find(root->ses, token->str, token->regex->str, SUB_CMD);
+				token->regex->val = find(root->ses, token->str, token->regex->str, SUB_VAR|SUB_FUN, SUB_CMD);
 
 
 				if (token->regex->val)
 				if (token->regex->val)
 				{
 				{

+ 2 - 2
src/utils.c

@@ -400,9 +400,9 @@ char *indent(int len)
 
 
 	cnt = (cnt + 1) % 10;
 	cnt = (cnt + 1) % 10;
 
 
-	memset(outbuf[cnt], '\t', len);
+	memset(outbuf[cnt], ' ', len * 5);
 
 
-	outbuf[cnt][len] = 0;
+	outbuf[cnt][len * 5] = 0;
 
 
 	return outbuf[cnt];
 	return outbuf[cnt];
 }
 }

+ 69 - 7
src/variable.c

@@ -39,7 +39,7 @@ DO_COMMAND(do_variable)
 	{
 	{
 		show_list(root, 0);
 		show_list(root, 0);
 	}
 	}
-	else if (*arg1 && *arg == 0)
+	else if (*arg == 0)
 	{
 	{
 		node = search_nest_node(root, arg1);
 		node = search_nest_node(root, arg1);
 
 
@@ -53,7 +53,7 @@ DO_COMMAND(do_variable)
 
 
 				view_nest_node(node, &str_result, 0, 1);
 				view_nest_node(node, &str_result, 0, 1);
 
 
-				tintin_printf2(ses, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s" COLOR_BRACE "}" COLOR_RESET "\n", gtd->tintin_char, list_table[LIST_VARIABLE].name, node->arg1, str_result);
+				print_lines(ses, SUB_NONE, COLOR_TINTIN "%c" COLOR_COMMAND "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\n{\n" COLOR_STRING "%s" COLOR_BRACE "}" COLOR_RESET "\n", gtd->tintin_char, list_table[LIST_VARIABLE].name, node->arg1, str_result);
 
 
 				str_free(str_result);
 				str_free(str_result);
 			}
 			}
@@ -288,13 +288,75 @@ void charactertonumber(struct session *ses, char *str)
 
 
 void colorstring(struct session *ses, char *str)
 void colorstring(struct session *ses, char *str)
 {
 {
-	char result[BUFFER_SIZE] = { 0 };
+	char result[BUFFER_SIZE];
 
 
-	get_highlight_codes(ses, str, result);
+	get_color_names(ses, str, result);
 
 
 	strcpy(str, result);
 	strcpy(str, result);
+}
 
 
-	strcpy(str, result);
+int get_color_names(struct session *ses, char *string, char *result)
+{
+	int cnt;
+
+	*result = 0;
+
+	if (*string == '<')
+	{
+		substitute(ses, string, result, SUB_COL);
+
+		return TRUE;
+	}
+
+	if (*string == '\\')
+	{
+		substitute(ses, string, result, SUB_ESC);
+
+		return TRUE;
+	}
+
+	while (*string)
+	{
+		if (isalpha(*string))
+		{
+			for (cnt = 0 ; *color_table[cnt].name ; cnt++)
+			{
+				if (is_abbrev(color_table[cnt].name, string))
+				{
+					substitute(ses, color_table[cnt].code, result, SUB_COL);
+
+					result += strlen(result);
+
+					break;
+				}
+			}
+
+			if (*color_table[cnt].name == 0)
+			{
+				return FALSE;
+			}
+
+			string += strlen(color_table[cnt].name);
+		}
+
+		switch (*string)
+		{
+			case ' ':
+			case ';':
+			case ',':
+			case '{':
+			case '}':
+				string++;
+				break;
+
+			case 0:
+				return TRUE;
+
+			default:
+				return FALSE;
+		}
+	}
+	return TRUE;
 }
 }
 
 
 void headerstring(char *str)
 void headerstring(char *str)
@@ -490,7 +552,7 @@ void wrapstring(struct session *ses, char *str)
 
 
 				get_color_codes(color, tmp, color);
 				get_color_codes(color, tmp, color);
 
 
-				sprintf(tmp, "%.*s", pti - sos, sos);
+				sprintf(tmp, "%.*s", (int) (pti - sos), sos);
 
 
 				substitute(ses, tmp, sec, SUB_SEC);
 				substitute(ses, tmp, sec, SUB_SEC);
 
 
@@ -505,7 +567,7 @@ void wrapstring(struct session *ses, char *str)
 
 
 				get_color_codes(color, tmp, color);
 				get_color_codes(color, tmp, color);
 
 
-				sprintf(tmp, "%.*s", lis - sos, sos);
+				sprintf(tmp, "%.*s", (int) (lis - sos), sos);
 
 
 				substitute(ses, tmp, sec, SUB_SEC);
 				substitute(ses, tmp, sec, SUB_SEC);
 
 

+ 34 - 8
src/vt102.c

@@ -28,12 +28,22 @@
 
 
 void save_pos(struct session *ses)
 void save_pos(struct session *ses)
 {
 {
-	printf("\e7"); 
+	if (ses->cur_row == gtd->screen->rows)
+	{
+		printf("\e7"); 
 
 
-	ses->sav_row = ses->cur_row;
-	ses->sav_col = ses->cur_col;
+		ses->sav_row = ses->cur_row;
+		ses->sav_col = ses->cur_col;
+	}
 }
 }
 
 
+void load_pos(struct session *ses)
+{
+	printf("\e8\e8"); 
+
+	ses->cur_row = ses->sav_row;
+	ses->cur_col = ses->sav_col;
+}
 
 
 void restore_pos(struct session *ses)
 void restore_pos(struct session *ses)
 {
 {
@@ -43,13 +53,26 @@ void restore_pos(struct session *ses)
 	ses->cur_col = ses->sav_col;
 	ses->cur_col = ses->sav_col;
 }
 }
 
 
+void goto_pos(struct session *ses, int row, int col)
+{
+	printf("\e[%d;%dH", row, col);
+
+	ses->cur_row = row;
+	ses->cur_col = col;
+}
+
 void goto_rowcol(struct session *ses, int row, int col)
 void goto_rowcol(struct session *ses, int row, int col)
 {
 {
 	printf("\e[%d;%dH", row, col);
 	printf("\e[%d;%dH", row, col);
 
 
 	ses->cur_row = row;
 	ses->cur_row = row;
+	ses->cur_col = col;
 }
 }
 
 
+void erase_lines(struct session *ses, int rows)
+{
+	printf("\e[%dM", rows);
+}
 
 
 void erase_toeol(void)
 void erase_toeol(void)
 {
 {
@@ -60,9 +83,12 @@ void erase_toeol(void)
 	doesn't do much
 	doesn't do much
 */
 */
 
 
-void reset(void)
+void reset(struct session *ses)
 {
 {
-	printf("%cc", ESCAPE);
+	ses->cur_row = 1;
+	ses->cur_col = 1;
+
+	printf("\ec");
 }
 }
 
 
 
 
@@ -70,12 +96,12 @@ void scroll_region(struct session *ses, int top, int bot)
 {
 {
 	push_call("scroll_region(%p,%d,%d)",ses,top,bot);
 	push_call("scroll_region(%p,%d,%d)",ses,top,bot);
 
 
-	printf("%c[%d;%dr", ESCAPE, top, bot);
+	printf("\e[%d;%dr", top, bot);
 
 
 	ses->top_row = top;
 	ses->top_row = top;
 	ses->bot_row = bot;
 	ses->bot_row = bot;
 
 
-	check_all_events(ses, SUB_ARG, 0, 2, "VT100 SCROLL REGION", ntos(top), ntos(bot));
+	check_all_events(ses, SUB_ARG, 0, 4, "VT100 SCROLL REGION", ntos(top), ntos(bot), ntos(gtd->screen->rows), ntos(gtd->screen->cols), ntos(ses->wrap > 0 ? ses->wrap : gtd->screen->cols));
 
 
 	pop_call();
 	pop_call();
 	return;
 	return;
@@ -86,7 +112,7 @@ void reset_scroll_region(struct session *ses)
 {
 {
 	if (ses == gtd->ses)
 	if (ses == gtd->ses)
 	{
 	{
-		printf("%c[r", ESCAPE);
+		printf("\e[r");
 	}
 	}
 	ses->top_row = 1;
 	ses->top_row = 1;
 	ses->bot_row = gtd->screen->rows;
 	ses->bot_row = gtd->screen->rows;

Некоторые файлы не были показаны из-за большого количества измененных файлов