Bläddra i källkod

Feat: cumulative update

dzp 6 månader sedan
förälder
incheckning
637c57efbc
60 ändrade filer med 1551 tillägg och 780 borttagningar
  1. 123 29
      SCRIPTS
  2. 9 77
      TODO
  3. 30 23
      docs/help.html
  4. 4 3
      docs/tutorial.html
  5. 41 1
      mods/igr.mods
  6. 11 11
      src/advertise.c
  7. 37 68
      src/banner.c
  8. 20 18
      src/base.c
  9. 2 2
      src/buffer.c
  10. 14 12
      src/chat.c
  11. 71 4
      src/class.c
  12. 1 1
      src/command.c
  13. 5 5
      src/config.c
  14. 187 18
      src/cursor.c
  15. 3 3
      src/daemon.c
  16. 29 26
      src/data.c
  17. 10 27
      src/draw.c
  18. 10 5
      src/edit.c
  19. 8 5
      src/event.c
  20. 5 5
      src/files.c
  21. 138 0
      src/gui.h
  22. 78 70
      src/help.c
  23. 3 3
      src/history.c
  24. 14 20
      src/input.c
  25. 24 25
      src/line.c
  26. 30 10
      src/main.c
  27. 33 24
      src/mapper.c
  28. 25 25
      src/math.c
  29. 1 1
      src/mccp.c
  30. 1 1
      src/memory.c
  31. 48 0
      src/misc.c
  32. 6 6
      src/msdp.c
  33. 3 3
      src/nest.c
  34. 3 3
      src/net.c
  35. 30 19
      src/parse.c
  36. 12 13
      src/path.c
  37. 11 7
      src/port.c
  38. 6 8
      src/regex.c
  39. 224 14
      src/scan.c
  40. 8 8
      src/screen.c
  41. 8 3
      src/session.c
  42. 11 8
      src/show.c
  43. 6 6
      src/sort.c
  44. 4 4
      src/split.c
  45. 16 12
      src/ssl.c
  46. 3 3
      src/string.c
  47. 7 7
      src/substitute.c
  48. 12 6
      src/system.c
  49. 33 30
      src/tables.c
  50. 7 7
      src/telopt_client.c
  51. 1 1
      src/telopt_server.c
  52. 1 1
      src/terminal.c
  53. 9 6
      src/tintin.h
  54. 29 17
      src/tokenize.c
  55. 19 18
      src/trigger.c
  56. 19 14
      src/update.c
  57. 1 1
      src/utf8.c
  58. 15 1
      src/utils.c
  59. 6 6
      src/variable.c
  60. 26 26
      src/vt102.c

+ 123 - 29
SCRIPTS

@@ -7,14 +7,17 @@
 #nop static (16) flag to <168>.
 #nop static (16) flag to <168>.
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
 
 
-#loop 1 1000 vnum
+#alias {color_static}
 {
 {
-	#map at $vnum
+	#loop 1 1000 vnum
 	{
 	{
-		#map get roomflags result;
-		#if {$result & 16}
+		#map at $vnum
 		{
 		{
-			#map set roomcolor <168>
+			#map get roomflags result;
+			#if {$result & 16}
+			{
+				#map set roomcolor <168>
+			}
 		}
 		}
 	}
 	}
 }
 }
@@ -152,7 +155,7 @@
 }
 }
 {60}
 {60}
 
 
-#alias {ticklist}
+#alias {tickers}
 {
 {
 	#info tickers save;
 	#info tickers save;
 
 
@@ -242,33 +245,35 @@
 #nop Show xterm 256 colors.
 #nop Show xterm 256 colors.
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
 
 
-#var temp {}
-
-#foreach {0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15} {var1}
+#alias {color_table}
 {
 {
-	#showme {$var1 \e[38;5;${var1}m}
-}
+	#var temp {};
 
 
-#foreach {a;b;c;d;e;f} {var1}
-{
-	#foreach {a;b;c;d;e;f} {var2}
+	#foreach {0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15} {var1}
 	{
 	{
-		#foreach {a;b;c;d;e;f} {var3}
+		#showme {$var1 \e[38;5;${var1}m}
+	};
+
+	#foreach {a;b;c;d;e;f} {var1}
+	{
+		#foreach {a;b;c;d;e;f} {var2}
 		{
 		{
-			#var temp {$temp <$var1$var2$var3><<888>$var1$var2$var3>}
-		};
-		#showme $temp;
-		#var temp {}
-	}
-}
+			#foreach {a;b;c;d;e;f} {var3}
+			{
+				#var temp {$temp <$var1$var2$var3><<888>$var1$var2$var3>}
+			};
+			#showme $temp;
+			#var temp {}
+		}
+	};
 
 
-#loop 0 23 cnt
-{
-	#format temp {$temp <g%+02s><<888>g%+02s} {$cnt} {$cnt};
+	#loop 0 23 cnt
+	{
+		#format temp {$temp <g%+02s><<888>g%+02s} {$cnt} {$cnt};
+	};
+	#showme $temp
 }
 }
 
 
-#showme $temp
-
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
 #nop Draw a health bar. Alternatively: #draw bar -2 1 -2 20 {%1;%2;<faa><afa>}
 #nop Draw a health bar. Alternatively: #draw bar -2 1 -2 20 {%1;%2;<faa><afa>}
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
@@ -437,7 +442,7 @@
 	#line gag
 	#line gag
 }
 }
 
 
-#alias {repeat_check}
+#alias {repeat_show}
 {
 {
 	#if {$repeat[cnt] <= 1}
 	#if {$repeat[cnt] <= 1}
 	{
 	{
@@ -445,7 +450,7 @@
 	};
 	};
 	#else
 	#else
 	{
 	{
-		#line ignore #showme {($repeat[cnt]) %0}
+		#line ignore #showme {<128>($repeat[cnt]) <088>$repeat[str]}
 	};
 	};
 	#var repeat[str] {};
 	#var repeat[str] {};
 	#var repeat[cnt] 1
 	#var repeat[cnt] 1
@@ -848,7 +853,7 @@
 
 
 			#draw red teed line $SCROLL[BOT_ROW]+1 $SCROLL[TOP_COL] $SCROLL[BOT_ROW]+1 $SCROLL[BOT_COL];
 			#draw red teed line $SCROLL[BOT_ROW]+1 $SCROLL[TOP_COL] $SCROLL[BOT_ROW]+1 $SCROLL[BOT_COL];
 
 
-			#screen clear square $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL];
+			#nop #screen clear square $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL];
 		};
 		};
 	};
 	};
 	#if {$SCROLL[MODE] == 1}
 	#if {$SCROLL[MODE] == 1}
@@ -1038,6 +1043,95 @@
 	#line ignore #showme <118>wton %0 = $wton
 	#line ignore #showme <118>wton %0 = $wton
 }
 }
 
 
+#nop -------------------------------------------------------------------------
+#nop Utility aliases to save variables as json, and load json as variables.
+#nop -------------------------------------------------------------------------
+
+#alias {json_save}
+{
+	#if {"%1" == "" || "%2" == ""}
+	{
+		#showme Syntax: json_save <variable> <filename>;
+		#return
+	};
+
+	#line quiet #log remove %2;
+	#line json {%1} {#line log {%2} {&0}}
+}
+
+#alias {json_load}
+{
+	#if {"%1" == "" || "%2" == ""}
+	{
+		#showme Syntax: json_load <variable> <filename>;
+		#return
+	};
+	#line quiet #unvar {%2};
+	#scan json {%2} {%1}
+}
+
+#nop -------------------------------------------------------------------------
+#nop Example of switching to an editing window, with mouse support. Use #edit
+#nop create to start editing. After editing is finished you can use #edit save
+#nop to store the data to a variable.
+#nop -------------------------------------------------------------------------
+
+#config mouse on
+
+#event {PROGRAM START}
+{
+	#screen raise {SCREEN RESIZE}
+}
+
+#event {SCREEN RESIZE}
+{
+	#screen clear all;
+
+	#screen scroll  2 2 -10 -2;
+	#screen input  -7 2 -2 -2;
+
+	#draw azure rounded left right bot top side 1 1 -9 -1;
+	#draw azure rounded left right bot top side -8 1 -1 -1
+}
+
+#event {PRESSED INPUT MOUSE BUTTON ONE}
+{
+	#cursor position %0 %1
+}
+
+#event {EDIT STARTED}
+{
+	#screen inputregion 2 2 -10 -2;
+	#screen scrollregion -7 2 -2 -2
+}
+
+#event {CATCH EDIT FINISHED}
+{
+	#screen input  -7 2 -2 -2;
+	#screen scroll  2 2 -10 -2;
+	#showme <138>EDIT FINISHED %0. LINES: %1  SIZE: %2
+}
+
+#nop -------------------------------------------------------------------------
+#nop Example script for drawing health bars
+#nop -------------------------------------------------------------------------
+
+#split 26 0
+#screen clear top
+
+#alias {draw_bar}
+{
+	#math value 0;
+	#loop 1 26 cnt
+	{
+		#draw ralign tile $cnt 1 $cnt 8 <178>$value/100;
+		#draw horizontal bar $cnt 10 $cnt 20 {$value;100;%0};
+		#math value $value + 4
+	}
+}
+
+draw_bar <faa><afa>
+
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
 #nop 
 #nop 
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------

+ 9 - 77
TODO

@@ -1,80 +1,32 @@
-- switch to pcre2
-
-- #alias test {#if {1} {%1}} gives an error on an empty input.
-
-- check if #scan file is escaping braces
-
-- If I set #config log_level low then it ignores #log timestamp {%Y-%m-%d-%H:%M:%S}
-
-- Update script's --time-style=full-iso doesn't work on Mac.
-
-- Investigate: EVENT_FLAG_UPDATE running as gtd->level->quiet++ in check_all_events
-
-- Add an example #edit script to SCRIPTS
-
-- #map offset 10 10 doesn't generate an error
-
-- strip [ ] from auto tab completion
+- Add full script highlighting of nested commands as well as variables,
+  indicate missing variables and functions. Add #info <list> show.
 
 
-- #draw tile 1 1 1 1 {\x7B}
+- #config {COMMAND ECHO} mode that echoes all commands as sent to the mud.
 
 
-- #screen scroll 10 1 -3 -1;#showme {bla} {-2}
+- make roomdata searchable in #map
 
 
-#draw RED ROUNDED BOX {1 1 2 2} gives a poor error message
+- #split 0 0 -100 -100 should do something sensible
 
 
-- #var foo {{}{aaa}} creates no assignment
+- Add blight to msdp/gmcp/mssp listing
 
 
-- With internet down, #session reconnect events might fail
-
-- Write an example script that makes tintin mimic Discord, with soft enters, emoticons, etc.
-
-- Add an example script to display time left on tickers using #info tickers save
+- switch to pcre2
 
 
 - comprehensive memory breakdown for variables/triggers/mapper/etc
 - comprehensive memory breakdown for variables/triggers/mapper/etc
 
 
-- #draw calign grid table {2} {2} {8} {42} {n;s;w;e} {n;s;w;e}; doesn't work properly.
-
 - a better trigger stack debug buffer
 - a better trigger stack debug buffer
 
 
-- Problem with restoring true color subs.
-#sub bla {<F00AA00>bla}
-#high blo <118>
-#showme <158>test bli bla blo test
-
-- named delays don't work in gts
-
-- #SPLIT when you give the top bar a negative value for its size, TinTin isn’t drawing the white box around it
-
-- Add an option to insert multiple items to a list
-
 - allow setting output encoding for #port
 - allow setting output encoding for #port
 
 
 - https://github.com/mintty/mintty/wiki/CtrlSeqs#audio-support
 - https://github.com/mintty/mintty/wiki/CtrlSeqs#audio-support
 - mintty --configdir DIRNAME
 - mintty --configdir DIRNAME
 
 
-- Fix: #ERROR: UNKNOWN TOKEN TYPE: 14 (#info tokenizer)
-
-- split screen scrollback setting in #screen
-
-- terrain based weight modifier
-- weightless mode for #map list and #map find
-
 - Make #draw scroll grid table work properly.
 - Make #draw scroll grid table work properly.
 
 
-
 - update https://tintin.mudhalla.net/info/ansicolor/
 - update https://tintin.mudhalla.net/info/ansicolor/
 
 
 - Make sure #config compact also applies to the log file.
 - Make sure #config compact also applies to the log file.
 
 
-- Add an #event that triggers when a function/variable is not found.
-
-- tab completion on input history
-
-- look into handling VARIABLE UPDATE event better
-
-- catch event to handle #map global exceptions
-
-
+- catch event for #map global to handle exceptions
 
 
 - Add routine to escape 0x00 in port.c RECEIVED DATA event.
 - Add routine to escape 0x00 in port.c RECEIVED DATA event.
 
 
@@ -112,20 +64,14 @@
 
 
 - #line escape {variables;functions}
 - #line escape {variables;functions}
 
 
-- look into a #debug flag for #class
-
 - Another nice thing would be if there was some flag to make a trigger match newlines as space.
 - Another nice thing would be if there was some flag to make a trigger match newlines as space.
 
 
-- fix up named delays and undelay
-
 - add a #regex like command for #cursor to update the input line.
 - add a #regex like command for #cursor to update the input line.
 
 
 - custom mapping for unicode table to set width
 - custom mapping for unicode table to set width
 
 
 - color code for dynamic color ranges
 - color code for dynamic color ranges
 
 
-- #MACRO {\cz} {#cursor get t;#var t} does not handle { } in input.
-
 - Look into delete_index_list leaving a table with ->used set to 0 causing #list crashes
 - Look into delete_index_list leaving a table with ->used set to 0 causing #list crashes
 
 
 - #daemon attach fails under high cpu load
 - #daemon attach fails under high cpu load
@@ -139,7 +85,7 @@
   - set_line_screen debug: col = -5 (64) from draw_text(%p,%d,%p,%p,%p)
   - set_line_screen debug: col = -5 (64) from draw_text(%p,%d,%p,%p,%p)
   - set_line_screen stack call triggered on android
   - set_line_screen stack call triggered on android
 
 
-  - regex101 like regex tester
+
 
 
   - check: #var bla { x};#draw scroll box 1 1 3 40 $bla
   - check: #var bla { x};#draw scroll box 1 1 3 40 $bla
 
 
@@ -157,10 +103,6 @@
 
 
   - vertical bar drawing
   - vertical bar drawing
 
 
-  - error: cursor_check_line_modified1: 
-  - https://tintin.sourceforge.io/forum/viewtopic.php?f=10&t=2811 (possible
-    issue with initiating input buffer for a new session)
-
   - finish BUFFER_SIZE replacement.
   - finish BUFFER_SIZE replacement.
 
 
   - WSL sound, double check soundpack scripts for lag/stutter
   - WSL sound, double check soundpack scripts for lag/stutter
@@ -175,10 +117,6 @@
 
 
 * STUFF THAT IS PROBABLY GONNA GET DONE
 * STUFF THAT IS PROBABLY GONNA GET DONE
 
 
-  - #line timeshot to auto destroy a trigger after given interval.
-
-  - make named delays proper delays
-
   - Finish port proxy support: resizing, input, security
   - Finish port proxy support: resizing, input, security
 
 
   - look into transparent drawing
   - look into transparent drawing
@@ -225,8 +163,6 @@
 
 
   - Remote script loading
   - Remote script loading
 
 
-  - add class specific debug
-  - better class event and class size handling ?
 
 
   - more potent long-click handling including held down ticks.
   - more potent long-click handling including held down ticks.
 
 
@@ -234,16 +170,12 @@
 
 
   - Add SESSIONS to the list table.
   - Add SESSIONS to the list table.
 
 
-  - Add debugger to syntax highlighter, substitution highlighing, 256 color support, and variable expansion.
-
   - add packets patched counter
   - add packets patched counter
 
 
   - reportable_sounds
   - reportable_sounds
 
 
   - TELNET documentation.
   - TELNET documentation.
 
 
-  - Add JSON support to #scan
-
   - see if #break 2 is possible, maybe #continue 2 as well.
   - see if #break 2 is possible, maybe #continue 2 as well.
 
 
   - IPv6 for chat
   - IPv6 for chat

+ 30 - 23
docs/help.html

@@ -94,10 +94,6 @@ a:active {color:#b06}
          arguments. The priority part is optional and determines the priority
          arguments. The priority part is optional and determines the priority
          of the alias, it defaults to 5.
          of the alias, it defaults to 5.
 
 
-         If no % variable is used in the commands section any argument will be
-         appended to the end as if %0 was used. This feature might be removed
-         in the future, and shouldn't be used.
-
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #alias {k} {kill %1;kick}
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #alias {k} {kill %1;kick}
 
 
          Typing 'k orc' would result in attacking the orc followed by a kick.
          Typing 'k orc' would result in attacking the orc followed by a kick.
@@ -417,7 +413,7 @@ a:active {color:#b06}
          clients, typically for the purpose of chatting and sending files.
          clients, typically for the purpose of chatting and sending files.
          This is a decentralized chat system, meaning you have to exchange ip
          This is a decentralized chat system, meaning you have to exchange ip
          addresses and port numbers with other users in order to connect to
          addresses and port numbers with other users in order to connect to
-         them.
+         them. Chat events are triggered in the startup session.
 
 
          </span><span style='color:#FFF'>#chat {init} {port}
          </span><span style='color:#FFF'>#chat {init} {port}
 </span><span style='color:#AAA'>           #chat initialize launches your chat server. The port number is
 </span><span style='color:#AAA'>           #chat initialize launches your chat server. The port number is
@@ -472,8 +468,8 @@ a:active {color:#b06}
            used instead of the connection's name when sending someone a message
            used instead of the connection's name when sending someone a message
            The second column shows the connection's name. The third column
            The second column shows the connection's name. The third column
            shows flags set for the connection, (P)rivate, (I)gnore, (S)erve,
            shows flags set for the connection, (P)rivate, (I)gnore, (S)erve,
-           (F)orward to user, and (f)orward from user. The next columns show
-           ip, port, and client name.
+           Forward(A)ll to user, (F)orward to user, and (f)orward from user.
+           The next columns show ip, port, and client name.
          </span><span style='color:#FFF'>#chat {zap}        {buddy}            Close a connection
          </span><span style='color:#FFF'>#chat {zap}        {buddy}            Close a connection
 
 
 Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
@@ -492,6 +488,8 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 </span><span style='color:#AAA'>           Will delete all triggers associated with the given class.
 </span><span style='color:#AAA'>           Will delete all triggers associated with the given class.
          </span><span style='color:#FFF'>#class {&lt;name&gt;} {close}
          </span><span style='color:#FFF'>#class {&lt;name&gt;} {close}
 </span><span style='color:#AAA'>           Close the given class, opening the last open class, if any.
 </span><span style='color:#AAA'>           Close the given class, opening the last open class, if any.
+         </span><span style='color:#FFF'>#class {&lt;name&gt;} {debug} {on|off}
+</span><span style='color:#AAA'>           Toggle debug mode for given class.
          </span><span style='color:#FFF'>#class {&lt;name&gt;} {kill}
          </span><span style='color:#FFF'>#class {&lt;name&gt;} {kill}
 </span><span style='color:#AAA'>           Will clear, close, and remove the class.
 </span><span style='color:#AAA'>           Will clear, close, and remove the class.
          </span><span style='color:#FFF'>#class {&lt;name&gt;} {list}
          </span><span style='color:#FFF'>#class {&lt;name&gt;} {list}
@@ -714,6 +712,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          COMPLETE    makes tab completion work while editing
          COMPLETE    makes tab completion work while editing
 
 
          DICTIONARY  performs tab completion on the dictionary
          DICTIONARY  performs tab completion on the dictionary
+         INPUT       performs tab completion on the input history
          LIST        performs tab completion on the tab completion list
          LIST        performs tab completion on the tab completion list
          SCROLLBACK  performs tab completion on the scrollback buffer
          SCROLLBACK  performs tab completion on the scrollback buffer
 
 
@@ -882,7 +881,7 @@ Command</span><span style='color:#AAA'>: #delay </span><span style='color:#FFF'>
          [BOXED] </span><span style='color:#FFF'>MAP
          [BOXED] </span><span style='color:#FFF'>MAP
 </span><span style='color:#AAA'>           will draw the map
 </span><span style='color:#AAA'>           will draw the map
          </span><span style='color:#FFF'>RAIN</span><span style='color:#AAA'> {&lt;VARIABLE&gt;} {[SPAWN]} {[FADE]} {[LEGEND]}
          </span><span style='color:#FFF'>RAIN</span><span style='color:#AAA'> {&lt;VARIABLE&gt;} {[SPAWN]} {[FADE]} {[LEGEND]}
-           will draw digital rain.
+           will draw digital rain SPAWN (0.01-100) FADE (1-100).
          [JOINTED|TOP|LEFT|BOTTOM|RIGHT] </span><span style='color:#FFF'>SIDE
          [JOINTED|TOP|LEFT|BOTTOM|RIGHT] </span><span style='color:#FFF'>SIDE
 </span><span style='color:#AAA'>           will draw one or more sides of a box.
 </span><span style='color:#AAA'>           will draw one or more sides of a box.
          [GRID] </span><span style='color:#FFF'>TABLE</span><span style='color:#AAA'> {[LIST1]} {[LIST2]}
          [GRID] </span><span style='color:#FFF'>TABLE</span><span style='color:#AAA'> {[LIST1]} {[LIST2]}
@@ -1177,6 +1176,9 @@ Command</span><span style='color:#AAA'>: #delay </span><span style='color:#FFF'>
 </span><span style='color:#AAA'>         </span><span style='color:#FFF'>EDIT STARTED, EDIT FINISHED
 </span><span style='color:#AAA'>         </span><span style='color:#FFF'>EDIT STARTED, EDIT FINISHED
 </span><span style='color:#AAA'>           %0 name  %1 lines %2 size %3 data
 </span><span style='color:#AAA'>           %0 name  %1 lines %2 size %3 data
 
 
+         </span><span style='color:#FFF'>EDIT RESUMED, EDIT SUSPENDED
+</span><span style='color:#AAA'>           %0 name
+
          </span><span style='color:#FFF'>HISTORY UPDATE
          </span><span style='color:#FFF'>HISTORY UPDATE
 </span><span style='color:#AAA'>           %0 command
 </span><span style='color:#AAA'>           %0 command
 
 
@@ -1251,12 +1253,13 @@ Command</span><span style='color:#AAA'>: #delay </span><span style='color:#FFF'>
 
 
          </span><span style='color:#5F5'>PORT EVENTS
          </span><span style='color:#5F5'>PORT EVENTS
 
 
-</span><span style='color:#AAA'>         </span><span style='color:#FFF'>CHAT MESSAGE</span><span style='color:#AAA'>, </span><span style='color:#FFF'>PORT MESSAGE
-</span><span style='color:#AAA'>           %0 raw text  %1 plain text
+</span><span style='color:#AAA'>         </span><span style='color:#FFF'>CHAT MESSAGE           </span><span style='color:#AAA'>%0 raw text  %1 plain text
+         </span><span style='color:#FFF'>CHAT SNOOP REQUEST     </span><span style='color:#AAA'>%0 name %1 ip %2 port
 
 
          </span><span style='color:#FFF'>PORT CONNECTION        </span><span style='color:#AAA'>%0 name %1 ip %2 port
          </span><span style='color:#FFF'>PORT CONNECTION        </span><span style='color:#AAA'>%0 name %1 ip %2 port
          </span><span style='color:#FFF'>PORT DISCONNECTION     </span><span style='color:#AAA'>%0 name %1 ip %2 port
          </span><span style='color:#FFF'>PORT DISCONNECTION     </span><span style='color:#AAA'>%0 name %1 ip %2 port
          </span><span style='color:#FFF'>PORT LOG MESSAGE       </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 plain data
          </span><span style='color:#FFF'>PORT LOG MESSAGE       </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 plain data
+         </span><span style='color:#FFF'>PORT MESSAGE           </span><span style='color:#AAA'>%0 raw text %1 plain text
          </span><span style='color:#FFF'>PORT RECEIVED MESSAGE  </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 plain data
          </span><span style='color:#FFF'>PORT RECEIVED MESSAGE  </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 plain data
          </span><span style='color:#FFF'>PORT RECEIVED DATA     </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 size
          </span><span style='color:#FFF'>PORT RECEIVED DATA     </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 size
 
 
@@ -1467,7 +1470,7 @@ Command</span><span style='color:#AAA'>: #delay </span><span style='color:#FFF'>
 
 
 </span><span style='color:#0AA'>      ####################################################################
 </span><span style='color:#0AA'>      ####################################################################
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
-      #</span><span style='color:#AAA'>                    T I N T I N + +   2.02.42                     </span><span style='color:#0AA'>#
+      #</span><span style='color:#AAA'>                    T I N T I N + +   2.02.51                     </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>      Code by Peter Unold, Bill Reis, and Igor van den Hoven      </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>      Code by Peter Unold, Bill Reis, and Igor van den Hoven      </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
@@ -3269,7 +3272,7 @@ Example</span><span style='color:#AAA'>: #high </span><span style='color:#FFF'>{
          key during selection.
          key during selection.
 
 
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#BUTTON'>button</a>, <a href='#DRAW'>draw</a>, <a href='#EVENT'>event</a> and <a href='#MSLP'>MSLP</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#BUTTON'>button</a>, <a href='#DRAW'>draw</a>, <a href='#EVENT'>event</a> and <a href='#MSLP'>mslp</a>.
 <a name='MSDP'></a>
 <a name='MSDP'></a>
 
 
 </span><span style='color:#FF5'>         MSDP
 </span><span style='color:#FF5'>         MSDP
@@ -3748,12 +3751,11 @@ Example</span><span style='color:#AAA'>: #high </span><span style='color:#FFF'>{
 
 
 </span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #read </span><span style='color:#FFF'>{</span><span style='color:#AAA'>filename</span><span style='color:#FFF'>}
 </span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #read </span><span style='color:#FFF'>{</span><span style='color:#AAA'>filename</span><span style='color:#FFF'>}
 
 
-</span><span style='color:#AAA'>         Reads a commands file into memory.  The coms file is merged in with
-         the currently loaded commands.  Duplicate commands are overwritten.
+</span><span style='color:#AAA'>         Reads a commands file into memory.  The commands are merged with the
+         currently loaded commands.  Duplicate commands are overwritten.
 
 
-         If you uses braces, { and } you can use several lines for 1 commands.
-         This however means you must always match every { with a } for the read
-         command to work.
+         If you uses braces you can use several lines for each command.  You
+         must match every { with a } for the read command to work.
 
 
          You can comment out triggers using /* text */
          You can comment out triggers using /* text */
 
 
@@ -3833,12 +3835,13 @@ Example</span><span style='color:#AAA'>: #high </span><span style='color:#FFF'>{
 
 
 </span><span style='color:#FF5'>         REPEAT
 </span><span style='color:#FF5'>         REPEAT
 
 
-</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #</span><span style='color:#FFF'>[</span><span style='color:#AAA'>number</span><span style='color:#FFF'>] {</span><span style='color:#AAA'>commands</span><span style='color:#FFF'>}
+</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #</span><span style='color:#FFF'>[</span><span style='color:#AAA'>number</span><span style='color:#FFF'>] {</span><span style='color:#AAA'>commands</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>..</span><span style='color:#FFF'>}
 
 
 </span><span style='color:#AAA'>        Sometimes you want to repeat the same command multiple times. This is
 </span><span style='color:#AAA'>        Sometimes you want to repeat the same command multiple times. This is
         the easiest way to accomplish that.
         the easiest way to accomplish that.
 
 
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #10 {buy bread}
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #10 {buy bread}
+</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #2 {buy bread} {buy apple}
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#MATHEMATICS'>mathematics</a> and <a href='#STATEMENTS'>statements</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#MATHEMATICS'>mathematics</a> and <a href='#STATEMENTS'>statements</a>.
 <a name='REPLACE'></a>
 <a name='REPLACE'></a>
@@ -3915,8 +3918,12 @@ Example</span><span style='color:#AAA'>: #high </span><span style='color:#FFF'>{
 
 
 </span><span style='color:#FFF'>         #scan {dir} &lt;filename&gt; &lt;variable&gt;
 </span><span style='color:#FFF'>         #scan {dir} &lt;filename&gt; &lt;variable&gt;
 
 
-</span><span style='color:#AAA'>          The scan dir command will read the given filename or directory and
-          store any gathered information into the provided variable.
+</span><span style='color:#AAA'>           The scan dir command will read the given filename or directory and
+           store any gathered information into the provided variable.
+
+</span><span style='color:#FFF'>         #scan {json} &lt;filename&gt; &lt;variable&gt;
+</span><span style='color:#AAA'>           The scan json command will read the given filename and store the data
+           in the provided tintin variable.
 
 
          </span><span style='color:#FFF'>#scan {tsv} &lt;filename&gt;
          </span><span style='color:#FFF'>#scan {tsv} &lt;filename&gt;
 
 
@@ -3928,9 +3935,9 @@ Example</span><span style='color:#AAA'>: #high </span><span style='color:#FFF'>{
          </span><span style='color:#FFF'>#scan {file} &lt;filename&gt; {commands}
          </span><span style='color:#FFF'>#scan {file} &lt;filename&gt; {commands}
 
 
 </span><span style='color:#AAA'>           The scan file command reads the given files and executes the
 </span><span style='color:#AAA'>           The scan file command reads the given files and executes the
-            commands argument. &amp;0 contains the raw content of the file and
-            &amp;1 contains the plain content. &amp;2 contains the raw byte size of the
-            file and &amp;3 the plain byte size. &amp;5 contains the line count.
+           commands argument. &amp;0 contains the raw content of the file and
+           &amp;1 contains the plain content. &amp;2 contains the raw byte size of the
+           file and &amp;3 the plain byte size. &amp;5 contains the line count.
 
 
          </span><span style='color:#FFF'>#scan {txt} &lt;filename&gt;
          </span><span style='color:#FFF'>#scan {txt} &lt;filename&gt;
 
 

+ 4 - 3
docs/tutorial.html

@@ -614,7 +614,7 @@ Example</span><span style='color:#AAA'>: #high </span><span style='color:#FFF'>{
 
 
 </span><span style='color:#0AA'>      ####################################################################
 </span><span style='color:#0AA'>      ####################################################################
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
-      #</span><span style='color:#AAA'>                    T I N T I N + +   2.02.42                     </span><span style='color:#0AA'>#
+      #</span><span style='color:#AAA'>                    T I N T I N + +   2.02.51                     </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>      Code by Peter Unold, Bill Reis, and Igor van den Hoven      </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>      Code by Peter Unold, Bill Reis, and Igor van den Hoven      </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
@@ -1217,7 +1217,7 @@ Example</span><span style='color:#AAA'>: #high </span><span style='color:#FFF'>{
          key during selection.
          key during selection.
 
 
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#BUTTON'>button</a>, <a href='help.html#DRAW'>draw</a>, <a href='help.html#EVENT'>event</a> and <a href='#MSLP'>MSLP</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#BUTTON'>button</a>, <a href='help.html#DRAW'>draw</a>, <a href='help.html#EVENT'>event</a> and <a href='#MSLP'>mslp</a>.
 <a name='MSDP'></a>
 <a name='MSDP'></a>
 
 
 </span><span style='color:#FF5'>         MSDP
 </span><span style='color:#FF5'>         MSDP
@@ -1506,12 +1506,13 @@ Example</span><span style='color:#AAA'>: #high </span><span style='color:#FFF'>{
 
 
 </span><span style='color:#FF5'>         REPEAT
 </span><span style='color:#FF5'>         REPEAT
 
 
-</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #</span><span style='color:#FFF'>[</span><span style='color:#AAA'>number</span><span style='color:#FFF'>] {</span><span style='color:#AAA'>commands</span><span style='color:#FFF'>}
+</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #</span><span style='color:#FFF'>[</span><span style='color:#AAA'>number</span><span style='color:#FFF'>] {</span><span style='color:#AAA'>commands</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>..</span><span style='color:#FFF'>}
 
 
 </span><span style='color:#AAA'>        Sometimes you want to repeat the same command multiple times. This is
 </span><span style='color:#AAA'>        Sometimes you want to repeat the same command multiple times. This is
         the easiest way to accomplish that.
         the easiest way to accomplish that.
 
 
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #10 {buy bread}
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #10 {buy bread}
+</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #2 {buy bread} {buy apple}
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#MATHEMATICS'>mathematics</a> and <a href='#STATEMENTS'>statements</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#MATHEMATICS'>mathematics</a> and <a href='#STATEMENTS'>statements</a>.
 <a name='SCREEN_READER'></a>
 <a name='SCREEN_READER'></a>

+ 41 - 1
mods/igr.mods

@@ -1,5 +1,45 @@
-Jan 2025        2.02.50
+Jun 2025        2.02.52
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
+base.c          Fixed a bug in the base64 conversion code. People using
+                tt++ -g will have to update their character passwords.
+
+Jan 2025        2.02.51
+------------------------------------------------------------------------------
+WinTin++        You can play .wav files in WinTin++ by creating the 'sounds'
+                directory in the 'bin' directory. Wav files stored in the
+                sounds directory can be played by executing:
+                #showme {\e]440;<filename>\a\}. To avoid playing multiple
+                sounds at once you can use:
+                #showme {\e]440;<filename>:async:nostop\a\}. You can cancel
+                an async sound using #showme {\e]440\a\}.
+
+data.c          #info system will report WINTIN++ as the OS for WinTin++.
+
+parse.c         Added support for multiple braced arguments to the repeat
+                option. #1 {#showme bli} {#showme bla}
+
+main.c          Added tt++ -l regex startup option to load a regex tester.
+
+input.c         Added the MODIFIED INPUT event. Triggers whenever the input
+                line is modified.
+
+vt102.c         Fixed true color handling for #highlight.
+
+cursor.c        Added automatic tab support on the input history.
+
+scan.c          Fixed a bug where #scan dir was storing invalid timestamps
+                on 32 bit systems.
+
+scan.c          The plain text argument of #scan file will have braces
+                substituted with \x7B \x7D.
+
+trigger.c       Using an alias that doesn't contain %0-%99 and providing an
+                an argument will generate a warning.
+
+class.c         Added #class <name> debug <on|off> option.
+
+scan.c          Added the #scan json <file> <variable> option. It will load
+                the given json file and store the data in the given variable.
 
 
 Jan 2024        2.02.42
 Jan 2024        2.02.42
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------

+ 11 - 11
src/advertise.c

@@ -153,7 +153,7 @@ struct advertisement_type advertisement_table[] =
                 "\n"
                 "\n"
                 "<178>To connect to 3Kingdoms enter:  #session 3K 3k.org 3000\n"
                 "<178>To connect to 3Kingdoms enter:  #session 3K 3k.org 3000\n"
                 "\n",
                 "\n",
- 
+
                 "\n"
                 "\n"
                 "<138>3Kingdoms\n"
                 "<138>3Kingdoms\n"
                 "<168>http://3k.org\n"
                 "<168>http://3k.org\n"
@@ -165,8 +165,8 @@ struct advertisement_type advertisement_table[] =
 	},
 	},
 
 
 	{
 	{
-		1400000000,  /* 2014 */ 
-		1800000000,  /* 2027 */ 
+		1400000000,  /* 2014 */
+		1800000000,  /* 2027 */
 		100,
 		100,
 
 
 		"\n"
 		"\n"
@@ -244,7 +244,7 @@ struct advertisement_type advertisement_table[] =
 		"\n"
 		"\n"
 		"<178>To connect to Primal Darkness enter: #session pd mud.primaldarkness.com 5000\n"
 		"<178>To connect to Primal Darkness enter: #session pd mud.primaldarkness.com 5000\n"
 		"\n",
 		"\n",
-		
+
 		"\n"
 		"\n"
 		"<138>Primal Darkness\n"
 		"<138>Primal Darkness\n"
 		"<168>http://www.primaldarkness.com\n"
 		"<168>http://www.primaldarkness.com\n"
@@ -318,8 +318,8 @@ struct advertisement_type advertisement_table[] =
 
 
 /*
 /*
 	{
 	{
-		1400000000, 
-		1700000000, 
+		1400000000,
+		1700000000,
 		100,
 		100,
 		"\n"
 		"\n"
 		"<138>               Carrion Fields  -  http://carrionfields.net\n"
 		"<138>               Carrion Fields  -  http://carrionfields.net\n"
@@ -333,12 +333,12 @@ struct advertisement_type advertisement_table[] =
 		"\n"
 		"\n"
                 "<178>To connect to Carrion Fields enter: #session cf carrionfields.net 4449\n"
                 "<178>To connect to Carrion Fields enter: #session cf carrionfields.net 4449\n"
                 "\n"
                 "\n"
-		                
+
 	},
 	},
 
 
 	{
 	{
-		1400000000, 
-		1700000000, 
+		1400000000,
+		1700000000,
 		100,
 		100,
 		"\n"
 		"\n"
 		"<138>                 Alter Aeon  -  http://www.alteraeon.com\n"
 		"<138>                 Alter Aeon  -  http://www.alteraeon.com\n"
@@ -356,7 +356,7 @@ struct advertisement_type advertisement_table[] =
 	},
 	},
 
 
 	{
 	{
-		1388166000, 
+		1388166000,
 		1600000000,
 		1600000000,
 		100,
 		100,
 		"\n"
 		"\n"
@@ -520,7 +520,7 @@ DO_COMMAND(do_advertise)
 		"\n"
 		"\n"
                 "<178>To connect to Lost Souls enter: #session ls lostsouls.org 23\n"
                 "<178>To connect to Lost Souls enter: #session ls lostsouls.org 23\n"
                 "\n"
                 "\n"
-		                
+
 	},
 	},
 
 
 	{
 	{

+ 37 - 68
src/banner.c

@@ -25,8 +25,6 @@
 
 
 #include "tintin.h"
 #include "tintin.h"
 
 
-#include "gui.h"
-
 #define BANNER_FLAG_DUPLICATE BV01
 #define BANNER_FLAG_DUPLICATE BV01
 
 
 void banner_create(struct session *ses, char *name, char *arg)
 void banner_create(struct session *ses, char *name, char *arg)
@@ -129,7 +127,7 @@ void banner_init(struct session *ses, char *arg1)
 
 
 	banner_website(ses, "New Worlds Ateraan", "http://www.ateraan.com", arg1);
 	banner_website(ses, "New Worlds Ateraan", "http://www.ateraan.com", arg1);
 	banner_address(ses, "New Worlds Ateraan", "nwa ateraan.com 4002", arg1);
 	banner_address(ses, "New Worlds Ateraan", "nwa ateraan.com 4002", arg1);
-	banner_expires(ses, "New Worlds Ateraan", "2029", arg1);
+	banner_expires(ses, "New Worlds Ateraan", "2030", arg1);
 
 
 
 
 	banner_create(ses, "Untold Dawn", arg1);
 	banner_create(ses, "Untold Dawn", arg1);
@@ -145,24 +143,23 @@ void banner_init(struct session *ses, char *arg1)
 	banner_address(ses, "Untold Dawn", "ud www.untold-dawn.com 4000", arg1);
 	banner_address(ses, "Untold Dawn", "ud www.untold-dawn.com 4000", arg1);
 	banner_expires(ses, "Untold Dawn", "2030", arg1);
 	banner_expires(ses, "Untold Dawn", "2030", arg1);
 
 
-/*
-	banner_create(ses, "Lost Souls", arg1);
 
 
-	banner_desc(ses, "Lost Souls",
-		"\"Lost Souls is not for the faint of heart.\" -- Net Games\n"
-		"\n"
-		"\"The depth of Lost Souls can be amazing.\" -- Playing MUDs On The Internet\n"
-		"\n"
-		"\"Have you ever come upon a place on the Net that's so incredible that you\n"
-		"can't believe such entertainment is free? This MUD will blow your mind with\n"
-		"its marvelous attention to detail and incredible role-playing atmosphere!\"\n"
-		"\n"
-		"  -- Yahoo! Wild Web Rides", arg1);
+	banner_create(ses, "Northern Crossroads", arg1);
 
 
-	banner_website(ses, "Lost Souls", "https://lostsouls.org", arg1);
-	banner_address(ses, "Lost Souls", "ls lostsouls.org 23", arg1);
-	banner_expires(ses, "Lost Souls", "2029", arg1);
+	banner_desc(ses, "Northern Crossroads",
+		"Northern Crossroads is a diverse world of blade wielders, assassins\n"
+		"and magic users who use their powers together to seek out the darkest\n"
+		"dungeons for hack'n'slash action. Decide between many classes, as\n"
+		"allowed by your choice of ten races, and prove your strength to ascend\n"
+		"to an Advanced class. Venture to dangerous zones with other mortals,\n"
+		"claim the rarest of items, join one of several clubs and build your character\n"
+		"to challenge other mortals. NC has enthralled players with hundreds of\n"
+		"detailed areas of various themes since 1993 and is one of the oldest\n"
+		"MUDs in the world.\n", arg1);
 
 
+	banner_website(ses, "Northern Crossroads", "https://www.ncmud.org", arg1);
+	banner_address(ses, "Northern Crossroads", "NC ncmud.org 9000", arg1);
+	banner_expires(ses, "Northern Crossroads", "2031", arg1);
 
 
 	banner_create(ses, "Kallisti MUD", arg1);
 	banner_create(ses, "Kallisti MUD", arg1);
 
 
@@ -179,7 +176,7 @@ void banner_init(struct session *ses, char *arg1)
 
 
 	banner_website(ses, "Kallisti MUD", "https://www.KallistiMUD.com", arg1);
 	banner_website(ses, "Kallisti MUD", "https://www.KallistiMUD.com", arg1);
 	banner_address(ses, "Kallisti MUD", "LoK kallistimud.com 4000", arg1);
 	banner_address(ses, "Kallisti MUD", "LoK kallistimud.com 4000", arg1);
-	banner_expires(ses, "Kallisti MUD", "2029", arg1);
+	banner_expires(ses, "Kallisti MUD", "2031", arg1);
 	banner_flag(ses, "Kallisti MUD", BANNER_FLAG_DUPLICATE);
 	banner_flag(ses, "Kallisti MUD", BANNER_FLAG_DUPLICATE);
 
 
 
 
@@ -198,7 +195,26 @@ void banner_init(struct session *ses, char *arg1)
 
 
 	banner_website(ses, "Legends of Kallisti", "https://legendsofkallisti.com", arg1);
 	banner_website(ses, "Legends of Kallisti", "https://legendsofkallisti.com", arg1);
 	banner_address(ses, "Legends of Kallisti", "LoK legendsofkallisti.com 4000", arg1);
 	banner_address(ses, "Legends of Kallisti", "LoK legendsofkallisti.com 4000", arg1);
-	banner_expires(ses, "Legends of Kallisti", "2029", arg1);
+	banner_expires(ses, "Legends of Kallisti", "2031", arg1);
+
+/*
+	banner_create(ses, "Lost Souls", arg1);
+
+	banner_desc(ses, "Lost Souls",
+		"\"Lost Souls is not for the faint of heart.\" -- Net Games\n"
+		"\n"
+		"\"The depth of Lost Souls can be amazing.\" -- Playing MUDs On The Internet\n"
+		"\n"
+		"\"Have you ever come upon a place on the Net that's so incredible that you\n"
+		"can't believe such entertainment is free? This MUD will blow your mind with\n"
+		"its marvelous attention to detail and incredible role-playing atmosphere!\"\n"
+		"\n"
+		"  -- Yahoo! Wild Web Rides", arg1);
+
+	banner_website(ses, "Lost Souls", "https://lostsouls.org", arg1);
+	banner_address(ses, "Lost Souls", "ls lostsouls.org 23", arg1);
+	banner_expires(ses, "Lost Souls", "2029", arg1);
+
 
 
 
 
 	banner_create(ses, "3Kingdoms", arg1);
 	banner_create(ses, "3Kingdoms", arg1);
@@ -490,49 +506,6 @@ void banner_test(struct session *ses, char *arg1)
 	tintin_header(ses, 80, "");
 	tintin_header(ses, 80, "");
 }
 }
 
 
-struct session *banner_gui(struct session *ses, char *arg1)
-{
-	char data[BUFFER_SIZE];
-	FILE *file;
-	size_t len;
-
-	strcpy(data, tt_gui);
-
-	len = strlen(data);
-
-	file = fmemopen(data, len, "r");
-
-	gtd->level->quiet++;
-
-	ses = read_file(ses, file, "tt_gui.h");
-
-	gtd->level->quiet--;
-
-	fclose(file);
-
-	return ses;
-
-/*
-	char filename[PATH_SIZE];
-	FILE *file;
-
-	sprintf(filename, "%s/gui.tin", gtd->system->tt_dir);
-
-	if ((file = fopen(filename, "w")) == NULL)
-	{
-		tintin_printf2(ses, "#BANNER GUI: FAILED TO CREATE {%s}.", filename);
-
-		return ses;
-	}
-
-	fputs(tt_gui, file);
-
-	fclose(file);
-
-	return command(ses, do_line, "quiet #read %s", filename);
-*/
-}
-
 DO_COMMAND(do_banner)
 DO_COMMAND(do_banner)
 {
 {
 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
 	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
@@ -545,10 +518,6 @@ DO_COMMAND(do_banner)
 	{
 	{
 		banner_init(ses, arg1);
 		banner_init(ses, arg1);
 	}
 	}
-	else if (is_abbrev(arg1, "GUI"))
-	{
-		return banner_gui(ses, arg1);
-	}
 	else if (is_abbrev(arg1, "LIST"))
 	else if (is_abbrev(arg1, "LIST"))
 	{
 	{
 		banner_list(ses, arg1);
 		banner_list(ses, arg1);
@@ -563,7 +532,7 @@ DO_COMMAND(do_banner)
 	}
 	}
 	else if (is_abbrev(arg1, "HELP"))
 	else if (is_abbrev(arg1, "HELP"))
 	{
 	{
-		tintin_printf2(ses, "#SYNTAX: #BANNER {GUI|INIT|LIST|RANDOM|SAVE|TEST}");
+		tintin_printf2(ses, "#SYNTAX: #BANNER {INIT|LIST|RANDOM|SAVE|TEST}");
 	}
 	}
 	else
 	else
 	{
 	{

+ 20 - 18
src/base.c

@@ -28,22 +28,22 @@
 char base64_table[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
 char base64_table[64] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
 
 
 char str64_table[256] =
 char str64_table[256] =
-{ 
+{
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,
 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0,  0,  0,  0,
 	52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0,  0,  0,  0,
 	 0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
 	 0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
 	15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
-	 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,	 
-	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0,	 
+	 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+	41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0,
 
 
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,	 
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,	 
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,	 
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0
 };
 };
@@ -142,6 +142,7 @@ int decompress_data(char *in, size_t size_in, char *out, size_t size_out)
 int str_to_base64(char *in, char *out, size_t size)
 int str_to_base64(char *in, char *out, size_t size)
 {
 {
 	char *pto;
 	char *pto;
+	unsigned char *uin = (unsigned char *) in;
 	int cnt;
 	int cnt;
 
 
 	push_call("str_to_base64(%p,%p,%zu)",in,out,size);
 	push_call("str_to_base64(%p,%p,%zu)",in,out,size);
@@ -150,24 +151,24 @@ int str_to_base64(char *in, char *out, size_t size)
 
 
 	for (cnt = 0 ; cnt + 3 <= size ; cnt += 3)
 	for (cnt = 0 ; cnt + 3 <= size ; cnt += 3)
 	{
 	{
-		*pto++ = base64_table[(unsigned char) in[cnt + 0] % 64];
-		*pto++ = base64_table[(unsigned char) in[cnt + 0] / 64 + (unsigned char) in[cnt + 1] % 16 * 4];
-		*pto++ = base64_table[(unsigned char) in[cnt + 1] / 16 + (unsigned char) in[cnt + 2] % 4 * 16];
-		*pto++ = base64_table[(unsigned char) in[cnt + 2] /  4];
+		*pto++ = base64_table[uin[cnt + 0] / 4];
+		*pto++ = base64_table[uin[cnt + 0] % 4 * 16 + uin[cnt + 1] / 16];
+		*pto++ = base64_table[uin[cnt + 1] % 16 * 4 + uin[cnt + 2] / 64];
+		*pto++ = base64_table[uin[cnt + 2] % 64];
 	}
 	}
 
 
 	switch (size - cnt)
 	switch (size - cnt)
 	{
 	{
 		case 1:
 		case 1:
-			*pto++ = base64_table[(unsigned char) in[cnt + 0] % 64];
-			*pto++ = base64_table[(unsigned char) in[cnt + 0] / 64];
+			*pto++ = base64_table[uin[cnt + 0] / 4];
+			*pto++ = base64_table[uin[cnt + 0] % 4 * 16];
 			*pto++ = '=';
 			*pto++ = '=';
 			*pto++ = '=';
 			*pto++ = '=';
 			break;
 			break;
 		case 2:
 		case 2:
-			*pto++ = base64_table[(unsigned char) in[cnt + 0] % 64];
-			*pto++ = base64_table[(unsigned char) in[cnt + 0] / 64 + (unsigned char) in[cnt + 1] % 16 * 4];
-			*pto++ = base64_table[(unsigned char) in[cnt + 1] / 16];
+			*pto++ = base64_table[uin[cnt + 0] / 4];
+			*pto++ = base64_table[uin[cnt + 0] % 4 * 16 + uin[cnt + 1] / 16];
+			*pto++ = base64_table[uin[cnt + 1] % 16 * 4];
 			*pto++ = '=';
 			*pto++ = '=';
 			break;
 			break;
 	}
 	}
@@ -182,27 +183,28 @@ int str_to_base64(char *in, char *out, size_t size)
 int base64_to_str(char *in, char *out, size_t size)
 int base64_to_str(char *in, char *out, size_t size)
 {
 {
 	char *pto;
 	char *pto;
+	unsigned char *uin = (unsigned char *) in;
 	int cnt;
 	int cnt;
 
 
 	pto = out;
 	pto = out;
 
 
 	for (cnt = 0 ; cnt + 4 <= size ; cnt += 4)
 	for (cnt = 0 ; cnt + 4 <= size ; cnt += 4)
 	{
 	{
-		*pto++ = str64_table[(unsigned char) in[cnt + 0]] + str64_table[(unsigned char) in[cnt + 1]] % 4 * 64;
+		*pto++ = str64_table[uin[cnt + 0]] * 4 + str64_table[uin[cnt + 1]] / 16;
 
 
 		if (in[cnt + 1] == '=')
 		if (in[cnt + 1] == '=')
 		{
 		{
 			break;
 			break;
 		}
 		}
 
 
-		*pto++ = str64_table[(unsigned char) in[cnt + 1]] / 4 + str64_table[(unsigned char) in[cnt + 2]] % 16 * 16;
+		*pto++ = str64_table[uin[cnt + 1]] % 16 * 16 + str64_table[uin[cnt + 2]] / 4;
 
 
 		if (in[cnt + 2] == '=')
 		if (in[cnt + 2] == '=')
 		{
 		{
 			break;
 			break;
 		}
 		}
 
 
-		*pto++ = str64_table[(unsigned char) in[cnt + 2]] / 16 + str64_table[(unsigned char) in[cnt + 3]] * 4;
+		*pto++ = str64_table[uin[cnt + 2]] % 4 * 64 + str64_table[uin[cnt + 3]];
 	}
 	}
 	*pto++ = 0;
 	*pto++ = 0;
 
 

+ 2 - 2
src/buffer.c

@@ -1172,7 +1172,7 @@ DO_BUFFER(buffer_info)
 
 
 	check_buffer(ses);
 	check_buffer(ses);
 
 
-	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);
 
 
 	if (*arg1 == 0)
 	if (*arg1 == 0)
@@ -1331,7 +1331,7 @@ DO_COMMAND(do_grep)
 				if (grep_cnt + grep_add >= grep_min)
 				if (grep_cnt + grep_add >= grep_min)
 				{
 				{
 					grep_cnt += grep_add;
 					grep_cnt += grep_add;
-					
+
 					tintin_puts2(ses, ses->scroll->buffer[scroll_cnt]->str);
 					tintin_puts2(ses, ses->scroll->buffer[scroll_cnt]->str);
 
 
 					if (grep_cnt + grep_add > grep_max)
 					if (grep_cnt + grep_add > grep_max)

+ 14 - 12
src/chat.c

@@ -151,7 +151,7 @@ DO_CHAT(chat_initialize)
 		syserr_printf(gtd->ses, "chat_initialize: setsockopt");
 		syserr_printf(gtd->ses, "chat_initialize: setsockopt");
 	}
 	}
 
 
-	ld.l_onoff  = 0; 
+	ld.l_onoff  = 0;
 	ld.l_linger = 100;
 	ld.l_linger = 100;
 
 
 	setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &ld, sizeof(ld));
 	setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &ld, sizeof(ld));
@@ -639,9 +639,9 @@ void chat_printf(char *format, ...)
 	}
 	}
 	str_cpy_printf(&tmp, "%s%s%s", gtd->chat->color, buf, "\e[0m");
 	str_cpy_printf(&tmp, "%s%s%s", gtd->chat->color, buf, "\e[0m");
 
 
-	check_all_events(gtd->ses, SUB_SEC|EVENT_FLAG_PORT, 0, 2, "CHAT MESSAGE", tmp, buf);
+	check_all_events(gts, SUB_SEC|EVENT_FLAG_PORT, 0, 2, "CHAT MESSAGE", tmp, buf);
 
 
-	if (!check_all_events(gtd->ses, SUB_SEC|EVENT_FLAG_CATCH, 0, 2, "CATCH CHAT MESSAGE", tmp, buf))
+	if (!check_all_events(gts, SUB_SEC|EVENT_FLAG_CATCH, 0, 2, "CATCH CHAT MESSAGE", tmp, buf))
 	{
 	{
 		tintin_printf(gtd->ses, "%s", tmp);
 		tintin_printf(gtd->ses, "%s", tmp);
 	}
 	}
@@ -740,9 +740,9 @@ int process_chat_input(struct chat_data *buddy)
 		else
 		else
 		{
 		{
 			chat_socket_printf(buddy, "%c\n%s has refused your connection due to an invalid handshake. (%s)\n%c", CHAT_MESSAGE, gtd->chat->name, buf, CHAT_END_OF_COMMAND);
 			chat_socket_printf(buddy, "%c\n%s has refused your connection due to an invalid handshake. (%s)\n%c", CHAT_MESSAGE, gtd->chat->name, buf, CHAT_END_OF_COMMAND);
-			
+
 			chat_printf("Refusing connection from %.21s:%d, invalid handshake.", buddy->ip, buddy->port);
 			chat_printf("Refusing connection from %.21s:%d, invalid handshake.", buddy->ip, buddy->port);
-			
+
 			pop_call();
 			pop_call();
 			return -1;
 			return -1;
 		}
 		}
@@ -965,6 +965,7 @@ void get_chat_commands(struct chat_data *buddy, char *buf, int len)
 				break;
 				break;
 
 
 			case CHAT_SNOOP_START:
 			case CHAT_SNOOP_START:
+				check_all_events(gts, EVENT_FLAG_PORT, 0, 3, "CHAT SNOOP REQUEST", buddy->name, buddy->ip, ntos(buddy->port));
 				break;
 				break;
 
 
 			case CHAT_SNOOP_DATA:
 			case CHAT_SNOOP_DATA:
@@ -1478,7 +1479,7 @@ DO_CHAT(chat_paste)
 			if ((buddy = find_buddy(name)) != NULL)
 			if ((buddy = find_buddy(name)) != NULL)
 			{
 			{
 				chat_printf("You paste to %s:\n%s", buddy->name, gtd->chat->paste_buf);
 				chat_printf("You paste to %s:\n%s", buddy->name, gtd->chat->paste_buf);
-	
+
 				chat_socket_printf(buddy, "%c\n%s pastes to you:\n%s\n%c", CHAT_TEXT_EVERYBODY, gtd->chat->name, gtd->chat->paste_buf, CHAT_END_OF_COMMAND);
 				chat_socket_printf(buddy, "%c\n%s pastes to you:\n%s\n%c", CHAT_TEXT_EVERYBODY, gtd->chat->name, gtd->chat->paste_buf, CHAT_END_OF_COMMAND);
 			}
 			}
 			else if (find_group(name) != NULL)
 			else if (find_group(name) != NULL)
@@ -1654,12 +1655,12 @@ DO_CHAT(chat_serve)
 	if (HAS_BIT(buddy->flags, CHAT_FLAG_SERVE))
 	if (HAS_BIT(buddy->flags, CHAT_FLAG_SERVE))
 	{
 	{
 		chat_printf("You are now chat serving %s.", buddy->name);
 		chat_printf("You are now chat serving %s.", buddy->name);
-		chat_socket_printf(buddy, "%c\n%s is now chat serving you.\n%c", CHAT_MESSAGE, gtd->chat->name, CHAT_END_OF_COMMAND); 
+		chat_socket_printf(buddy, "%c\n%s is now chat serving you.\n%c", CHAT_MESSAGE, gtd->chat->name, CHAT_END_OF_COMMAND);
 	}
 	}
 	else
 	else
 	{
 	{
 		chat_printf("You are no longer chat serving %s.", buddy->name);
 		chat_printf("You are no longer chat serving %s.", buddy->name);
-		chat_socket_printf(buddy, "%c\n%s is no longer chat serving you.\n%c", CHAT_MESSAGE, gtd->chat->name, CHAT_END_OF_COMMAND); 
+		chat_socket_printf(buddy, "%c\n%s is no longer chat serving you.\n%c", CHAT_MESSAGE, gtd->chat->name, CHAT_END_OF_COMMAND);
 	}
 	}
 }
 }
 
 
@@ -1680,6 +1681,7 @@ DO_CHAT(chat_who)
 			HAS_BIT(buddy->flags, CHAT_FLAG_PRIVATE)   ? "P" : " ",
 			HAS_BIT(buddy->flags, CHAT_FLAG_PRIVATE)   ? "P" : " ",
 			HAS_BIT(buddy->flags, CHAT_FLAG_IGNORE)    ? "I" : " ",
 			HAS_BIT(buddy->flags, CHAT_FLAG_IGNORE)    ? "I" : " ",
 			HAS_BIT(buddy->flags, CHAT_FLAG_SERVE)     ? "S" : " ",
 			HAS_BIT(buddy->flags, CHAT_FLAG_SERVE)     ? "S" : " ",
+			HAS_BIT(buddy->flags, CHAT_FLAG_FORWARDALL) ? "A" :
 			HAS_BIT(buddy->flags, CHAT_FLAG_FORWARD)   ? "F" :
 			HAS_BIT(buddy->flags, CHAT_FLAG_FORWARD)   ? "F" :
 			HAS_BIT(buddy->flags, CHAT_FLAG_FORWARDBY) ? "f" : " ",
 			HAS_BIT(buddy->flags, CHAT_FLAG_FORWARDBY) ? "f" : " ",
 			" ",
 			" ",
@@ -1918,7 +1920,7 @@ void chat_receive_file(char *arg, struct chat_data *buddy)
 		deny_file(buddy, "\nFile protocol error. (no file size was transmitted)\n");
 		deny_file(buddy, "\nFile protocol error. (no file size was transmitted)\n");
 
 
 		pop_call();
 		pop_call();
-		return;	
+		return;
 	}
 	}
 	*comma = 0;
 	*comma = 0;
 
 
@@ -2112,7 +2114,7 @@ void file_cleanup(struct chat_data *buddy)
 	if (buddy->file_name)
 	if (buddy->file_name)
 	{
 	{
 		free(buddy->file_name);
 		free(buddy->file_name);
-		
+
 		buddy->file_name = NULL;
 		buddy->file_name = NULL;
 	}
 	}
 }
 }
@@ -2358,7 +2360,7 @@ DO_CHAT(chat_private)
 			{
 			{
 				chat_socket_printf(buddy, "%c\n%s marked your connection private.\n%c", CHAT_MESSAGE, gtd->chat->name, CHAT_END_OF_COMMAND);
 				chat_socket_printf(buddy, "%c\n%s marked your connection private.\n%c", CHAT_MESSAGE, gtd->chat->name, CHAT_END_OF_COMMAND);
 
 
-				chat_printf("Your connection with %s is now private.", buddy->name);				
+				chat_printf("Your connection with %s is now private.", buddy->name);
 
 
 				SET_BIT(buddy->flags, CHAT_FLAG_PRIVATE);
 				SET_BIT(buddy->flags, CHAT_FLAG_PRIVATE);
 			}
 			}
@@ -2396,7 +2398,7 @@ DO_CHAT(chat_public)
 			{
 			{
 				chat_socket_printf(buddy, "%c\n%s marked your connection public.\n%c", CHAT_MESSAGE, gtd->chat->name, CHAT_END_OF_COMMAND);
 				chat_socket_printf(buddy, "%c\n%s marked your connection public.\n%c", CHAT_MESSAGE, gtd->chat->name, CHAT_END_OF_COMMAND);
 
 
-				chat_printf("Your connection with %s is now public.", buddy->name);				
+				chat_printf("Your connection with %s is now public.", buddy->name);
 
 
 				DEL_BIT(buddy->flags, CHAT_FLAG_PRIVATE);
 				DEL_BIT(buddy->flags, CHAT_FLAG_PRIVATE);
 			}
 			}

+ 71 - 4
src/class.c

@@ -31,6 +31,7 @@
 extern DO_CLASS(class_assign);
 extern DO_CLASS(class_assign);
 extern DO_CLASS(class_clear);
 extern DO_CLASS(class_clear);
 extern DO_CLASS(class_close);
 extern DO_CLASS(class_close);
+extern DO_CLASS(class_debug);
 extern DO_CLASS(class_kill);
 extern DO_CLASS(class_kill);
 extern DO_CLASS(class_list);
 extern DO_CLASS(class_list);
 extern DO_CLASS(class_load);
 extern DO_CLASS(class_load);
@@ -54,6 +55,7 @@ struct class_type class_table[] =
 	{    "ASSIGN",            class_assign,   "Execute command with given class opened."        },
 	{    "ASSIGN",            class_assign,   "Execute command with given class opened."        },
 	{    "CLEAR",             class_clear,    "Delete triggers associated with given class."    },
 	{    "CLEAR",             class_clear,    "Delete triggers associated with given class."    },
 	{    "CLOSE",             class_close,    "Close given class."                              },
 	{    "CLOSE",             class_close,    "Close given class."                              },
+	{    "DEBUG",             class_debug,    "Show debug messages for given class."            },
 	{    "KILL",              class_kill,     "Clear, close, and remove given class."           },
 	{    "KILL",              class_kill,     "Clear, close, and remove given class."           },
 	{    "LIST",              class_list,     "List triggers associated with given class."      },
 	{    "LIST",              class_list,     "List triggers associated with given class."      },
 	{    "LOAD",              class_load,     "Load saved data of given class."                 },
 	{    "LOAD",              class_load,     "Load saved data of given class."                 },
@@ -195,7 +197,7 @@ DO_CLASS(class_assign)
 
 
 	ses->group = strdup(arg1);
 	ses->group = strdup(arg1);
 
 
-	script_driver(ses, LIST_COMMAND, arg2);
+	script_driver(ses, LIST_COMMAND, node, arg2);
 
 
 	free(ses->group);
 	free(ses->group);
 
 
@@ -273,6 +275,71 @@ DO_CLASS(class_close)
 	return ses;
 	return ses;
 }
 }
 
 
+DO_CLASS(class_debug)
+{
+	if (node == NULL)
+	{
+		node = search_node_list(ses->list[LIST_CLASS], arg1);
+
+		if (node == NULL)
+		{
+			show_message(ses, LIST_CLASS, "#CLASS {%s} DOES NOT EXIST.", arg1);
+			return ses;
+		}
+	}
+
+	if (*arg2 == 0)
+	{
+		TOG_BIT(node->flags, NODE_FLAG_DEBUG);
+	}
+	else if (!strcasecmp(arg2, "ON"))
+	{
+		SET_BIT(node->flags, NODE_FLAG_DEBUG);
+	}
+	else if (!strcasecmp(arg2, "OFF"))
+	{
+		DEL_BIT(node->flags, NODE_FLAG_DEBUG);
+	}
+	else
+	{
+		show_error(ses, LIST_CLASS, "#SYNTAX: #CLASS {%s} DEBUG {ON|OFF}", arg1);
+		return ses;
+	}
+
+	if (HAS_BIT(node->flags, NODE_FLAG_DEBUG))
+	{
+		show_message(ses, LIST_CLASS, "#CLASS {%s} IS NOW BEING DEBUGGED.", arg1);
+	}
+	else
+	{
+		show_message(ses, LIST_CLASS, "#CLASS {%s} IS NO LONGER BEING DEBUGGED.", arg1);
+	}
+
+	for (int i = 0 ; i < LIST_MAX ; i++)
+	{
+		if (!HAS_BIT(ses->list[i]->flags, LIST_FLAG_CLASS))
+		{
+			continue;
+		}
+
+		for (int j = 0 ; j < ses->list[i]->used ; j++)
+		{
+			if (!strcmp(ses->list[i]->list[j]->group, node->arg1))
+			{
+				if (HAS_BIT(node->flags, NODE_FLAG_DEBUG))
+				{
+					SET_BIT(ses->list[i]->list[j]->flags, NODE_FLAG_DEBUG);
+				}
+				else
+				{
+					DEL_BIT(ses->list[i]->list[j]->flags, NODE_FLAG_DEBUG);
+				}
+			}
+		}
+	}
+	return ses;
+}
+
 
 
 DO_CLASS(class_list)
 DO_CLASS(class_list)
 {
 {
@@ -459,14 +526,14 @@ DO_CLASS(class_save)
 	show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN SAVED TO MEMORY.", arg1);
 	show_message(ses, LIST_CLASS, "#CLASS {%s} HAS BEEN SAVED TO MEMORY.", arg1);
 
 
 	return ses;
 	return ses;
-}	
+}
 
 
 DO_CLASS(class_size)
 DO_CLASS(class_size)
 {
 {
 	if (*arg1 == 0 || *arg2 == 0)
 	if (*arg1 == 0 || *arg2 == 0)
 	{
 	{
 		show_error(ses, LIST_CLASS, "#SYNTAX: #CLASS <NAME> SIZE <VARIABLE>");
 		show_error(ses, LIST_CLASS, "#SYNTAX: #CLASS <NAME> SIZE <VARIABLE>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -491,7 +558,7 @@ DO_CLASS(class_write)
 	if (*arg2 == 0 || (file = fopen(arg2, "w")) == NULL)
 	if (*arg2 == 0 || (file = fopen(arg2, "w")) == NULL)
 	{
 	{
 		show_error(ses, LIST_CLASS, "#ERROR: #CLASS WRITE {%s}: COULDN'T OPEN FILE.", arg2);
 		show_error(ses, LIST_CLASS, "#ERROR: #CLASS WRITE {%s}: COULDN'T OPEN FILE.", arg2);
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 

+ 1 - 1
src/command.c

@@ -170,7 +170,7 @@ struct session *execute(struct session *ses, char *format, ...)
 		get_arg_all(ses, buffer, buffer, FALSE);
 		get_arg_all(ses, buffer, buffer, FALSE);
 	}
 	}
 
 
-	ses = script_driver(ses, LIST_COMMAND, buffer);
+	ses = script_driver(ses, LIST_COMMAND, NULL, buffer);
 
 
 	free(buffer);
 	free(buffer);
 
 

+ 5 - 5
src/config.c

@@ -533,7 +533,7 @@ DO_CONFIG(config_childlock)
 DO_CONFIG(config_colormode)
 DO_CONFIG(config_colormode)
 {
 {
 	if (*arg2)
 	if (*arg2)
-	{	
+	{
 		if (is_abbrev(arg2, "NONE") || is_abbrev(arg2, "OFF"))
 		if (is_abbrev(arg2, "NONE") || is_abbrev(arg2, "OFF"))
 		{
 		{
 			ses->color = 0;
 			ses->color = 0;
@@ -888,7 +888,7 @@ DO_CONFIG(config_mousetracking)
 	{
 	{
 		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
 		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
 		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
 		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
-		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);	
+		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);
 		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);
 		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);
 		DEL_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
 		DEL_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
 
 
@@ -1124,7 +1124,7 @@ DO_CONFIG(config_screenreader)
 DO_CONFIG(config_scrolllock)
 DO_CONFIG(config_scrolllock)
 {
 {
 	if (*arg2)
 	if (*arg2)
-	{	
+	{
 		if (is_abbrev(arg2, "ON"))
 		if (is_abbrev(arg2, "ON"))
 		{
 		{
 			SET_BIT(ses->config_flags, CONFIG_FLAG_SCROLLLOCK);
 			SET_BIT(ses->config_flags, CONFIG_FLAG_SCROLLLOCK);
@@ -1140,7 +1140,7 @@ DO_CONFIG(config_scrolllock)
 			return NULL;
 			return NULL;
 		}
 		}
 	}
 	}
-	strcpy(arg2, HAS_BIT(ses->config_flags, CONFIG_FLAG_SCROLLLOCK) ? "ON" : "OFF");	
+	strcpy(arg2, HAS_BIT(ses->config_flags, CONFIG_FLAG_SCROLLLOCK) ? "ON" : "OFF");
 
 
 	return ses;
 	return ses;
 }
 }
@@ -1198,7 +1198,7 @@ DO_CONFIG(config_tabwidth)
 
 
 	return ses;
 	return ses;
 }
 }
-	
+
 DO_CONFIG(config_telnet)
 DO_CONFIG(config_telnet)
 {
 {
 	if (*arg2)
 	if (*arg2)

+ 187 - 18
src/cursor.c

@@ -709,7 +709,7 @@ DO_CURSOR(cursor_check_line_modified)
 
 
 	if (gtd->ses->input->str_len != width)
 	if (gtd->ses->input->str_len != width)
 	{
 	{
-		tintin_printf2(ses, "\e[1;31merror: cursor_check_line_modified2: str: %d vs %d", gtd->ses->input->str_len, width);
+		tintin_printf2(ses, "\e[1;31merror: cursor_check_line_modified2: str: %d vs %d raw: %d", gtd->ses->input->str_len, width, gtd->ses->input->raw_len);
 	}
 	}
 
 
 	if (gtd->ses->input->str_pos > gtd->ses->input->str_len)
 	if (gtd->ses->input->str_pos > gtd->ses->input->str_len)
@@ -854,9 +854,9 @@ DO_CURSOR(cursor_delete)
 				remove_line(gtd->ses->input->edit, gtd->ses->input->edit->update);
 				remove_line(gtd->ses->input->edit, gtd->ses->input->edit->update);
 
 
 				inputline_set(gtd->ses->input->edit->line[gtd->ses->input->edit->update]->str, 0);
 				inputline_set(gtd->ses->input->edit->line[gtd->ses->input->edit->update]->str, 0);
-				
+
 				cursor_redraw_edit(ses, arg);
 				cursor_redraw_edit(ses, arg);
-				
+
 				modified_input();
 				modified_input();
 			}
 			}
 		}
 		}
@@ -1166,6 +1166,11 @@ DO_CURSOR(cursor_escape_enter)
 						}
 						}
 						pti += 2;
 						pti += 2;
 					}
 					}
+					else if (pti[1] == 't')
+					{
+						*pto++ = '\t';
+						pti += 2;
+					}
 					else if (pti[1])
 					else if (pti[1])
 					{
 					{
 						*pto++ = *pti++;
 						*pto++ = *pti++;
@@ -1185,7 +1190,7 @@ DO_CURSOR(cursor_escape_enter)
 	}
 	}
 	cursor_enter(ses, "");
 	cursor_enter(ses, "");
 }
 }
-	
+
 DO_CURSOR(cursor_soft_enter)
 DO_CURSOR(cursor_soft_enter)
 {
 {
 	if (!inputline_editor())
 	if (!inputline_editor())
@@ -1217,7 +1222,7 @@ DO_CURSOR(cursor_enter_finish)
 	if (inputline_editor())
 	if (inputline_editor())
 	{
 	{
 		cursor_redraw_line(gtd->ses, "");
 		cursor_redraw_line(gtd->ses, "");
-		
+
 		return;
 		return;
 	}
 	}
 
 
@@ -1387,7 +1392,7 @@ DO_CURSOR(cursor_history_next)
 				inputline_max_str_len() - inputline_cur_off() - inputline_cur_str_len(),
 				inputline_max_str_len() - inputline_cur_off() - inputline_cur_str_len(),
 				UMAX(0, inputline_max_str_len() - inputline_cur_off() - inputline_cur_str_len() - 4),
 				UMAX(0, inputline_max_str_len() - inputline_cur_off() - inputline_cur_str_len() - 4),
 				root->list[root->update]->arg1);
 				root->list[root->update]->arg1);
-			
+
 			goto_pos(gtd->ses, inputline_cur_row(), inputline_cur_col());
 			goto_pos(gtd->ses, inputline_cur_row(), inputline_cur_col());
 		}
 		}
 		return;
 		return;
@@ -1459,7 +1464,7 @@ DO_CURSOR(cursor_history_prev)
 				inputline_max_str_len() - inputline_cur_off() - inputline_cur_str_len(),
 				inputline_max_str_len() - inputline_cur_off() - inputline_cur_str_len(),
 				UMAX(0, inputline_max_str_len() - inputline_cur_off() - inputline_cur_str_len() - 4),
 				UMAX(0, inputline_max_str_len() - inputline_cur_off() - inputline_cur_str_len() - 4),
 				root->list[root->update]->arg1);
 				root->list[root->update]->arg1);
-			
+
 			goto_pos(gtd->ses, inputline_cur_row(), inputline_cur_col());
 			goto_pos(gtd->ses, inputline_cur_row(), inputline_cur_col());
 		}
 		}
 		return;
 		return;
@@ -1546,6 +1551,17 @@ DO_CURSOR(cursor_history_find)
 
 
 	push_call("cursor_history_find(%s)", gtd->ses->input->buf);
 	push_call("cursor_history_find(%s)", gtd->ses->input->buf);
 
 
+	if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
+	{
+		check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 0, "MODIFIED INPUT");
+	}
+
+	if (!HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH))
+	{
+		pop_call();
+		return;
+	}
+
 	if (inputline_str_chk(0, gtd->ses->input->raw_len) == FALSE)
 	if (inputline_str_chk(0, gtd->ses->input->raw_len) == FALSE)
 	{
 	{
 		pop_call();
 		pop_call();
@@ -1608,7 +1624,7 @@ DO_CURSOR(cursor_home)
 		if (gtd->ses->input->str_pos)
 		if (gtd->ses->input->str_pos)
 		{
 		{
 			gtd->ses->input->str_pos = 0;
 			gtd->ses->input->str_pos = 0;
-			
+
 			return cursor_redraw_line(ses, arg);
 			return cursor_redraw_line(ses, arg);
 		}
 		}
 		return;
 		return;
@@ -1651,7 +1667,7 @@ DO_CURSOR(cursor_move_page_up)
 	int rows = UMAX(1, inputline_rows(gtd->ses) / 2);
 	int rows = UMAX(1, inputline_rows(gtd->ses) / 2);
 
 
 	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH);
 	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH);
-	
+
 	cursor_move_up(ses, ntos(rows));
 	cursor_move_up(ses, ntos(rows));
 }
 }
 
 
@@ -1712,7 +1728,7 @@ DO_CURSOR(cursor_move_page_down)
 	int rows = UMAX(1, inputline_rows(gtd->ses) / 2);
 	int rows = UMAX(1, inputline_rows(gtd->ses) / 2);
 
 
 	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH);
 	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH);
-	
+
 	cursor_move_down(ses, ntos(rows));
 	cursor_move_down(ses, ntos(rows));
 }
 }
 
 
@@ -2372,7 +2388,7 @@ DO_CURSOR(cursor_set)
 {
 {
 	char arg1[BUFFER_SIZE];
 	char arg1[BUFFER_SIZE];
 
 
-	arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN|SUB_ESC);
 
 
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
@@ -2522,10 +2538,146 @@ int cursor_scrollback_tab_add(int flag)
 
 
 		while (*ptb)
 		while (*ptb)
 		{
 		{
-			while (*ptb && is_space(*ptb))
+			while (*ptb)
+			{
+				switch (*ptb)
+				{
+					case ' ':
+					case '[':
+					case ']':
+					case '"':
+					case ':':
+					case '\t':
+					case '\n':
+					case '\r':
+					case '\v':
+					case '\f':
+						ptb++;
+						continue;
+				}
+				break;
+			}
+
+			if (HAS_BIT(flag, TAB_FLAG_CASELESS))
+			{
+				if (strncasecmp(ptb, tail, tail_len) != 0)
+				{
+					goto end;
+				}
+			}
+			else
+			{
+				if (*ptb != *tail || strncmp(ptb, tail, tail_len) != 0)
+				{
+					goto end;
+				}
+			}
+			ptt = tab;
+
+			for (tab_len = 0 ; tab_len < tail_len ; tab_len++)
+			{
+				*ptt++ = *ptb++;
+			}
+
+			while (*ptb && *ptb != ' ')
+			{
+				switch (*ptb)
+				{
+					case ';':
+					case '.':
+					case ',':
+					case '!':
+					case '?':
+					case ':':
+					case '"':
+					case '[':
+					case ']':
+						*ptt++ = 0;
+						ptb++;
+						break;
+
+					default:
+						*ptt++ = *ptb++;
+						break;
+				}
+			}
+			*ptt = 0;
+
+			if (search_node_list(gtd->ses->list[LIST_COMMAND], tab))
+			{
+				goto end;
+			}
+
+			node = create_node_list(gtd->ses->list[LIST_COMMAND], tab, "", "", "");
+
+			node->val32[0] = scroll_cnt;
+
+			if (HAS_BIT(flag, TAB_FLAG_FORWARD))
+			{
+				return TRUE;
+			}
+
+			if (root->used > 100)
+			{
+				return FALSE;
+			}
+
+			end:
+
+			while (*ptb && !is_space(*ptb))
 			{
 			{
 				ptb++;
 				ptb++;
 			}
 			}
+		}
+	}
+	return FALSE;
+}
+
+int cursor_input_tab_add(int flag)
+{
+	char tab[BUFFER_SIZE];
+	struct listroot *root = gtd->ses->list[LIST_COMMAND];
+	struct listnode *node;
+	int scroll_cnt, tab_len, tail_len;
+	char *ptb, *ptt, *tail;
+
+	tail     = root->list[0]->arg1;
+	tail_len = str_len(tail);
+
+	if (root->list[root->used - 1]->val32[0])
+	{
+		scroll_cnt = UMIN(root->list[root->used - 1]->val32[0], gtd->ses->list[LIST_HISTORY]->used - 1);
+	}
+	else
+	{
+		scroll_cnt = gtd->ses->list[LIST_HISTORY]->used - 1;
+	}
+
+	for ( ; scroll_cnt > 0 ; scroll_cnt--)
+	{
+		ptb = gtd->ses->list[LIST_HISTORY]->list[scroll_cnt]->arg1;
+
+		while (*ptb)
+		{
+			while (*ptb)
+			{
+				switch (*ptb)
+				{
+					case ' ':
+					case '[':
+					case ']':
+					case '"':
+					case ':':
+					case '\t':
+					case '\n':
+					case '\r':
+					case '\v':
+					case '\f':
+						ptb++;
+						continue;
+				}
+				break;
+			}
 
 
 			if (HAS_BIT(flag, TAB_FLAG_CASELESS))
 			if (HAS_BIT(flag, TAB_FLAG_CASELESS))
 			{
 			{
@@ -2559,6 +2711,8 @@ int cursor_scrollback_tab_add(int flag)
 					case '?':
 					case '?':
 					case ':':
 					case ':':
 					case '"':
 					case '"':
+					case '[':
+					case ']':
 						*ptt++ = 0;
 						*ptt++ = 0;
 						ptb++;
 						ptb++;
 						break;
 						break;
@@ -2631,6 +2785,11 @@ void cursor_tab_forward(struct session *ses, int flag)
 		tab_found = cursor_scrollback_tab_add(flag);
 		tab_found = cursor_scrollback_tab_add(flag);
 	}
 	}
 
 
+	if (tab_found == 0 && HAS_BIT(flag, TAB_FLAG_INPUT))
+	{
+		tab_found = cursor_input_tab_add(flag);
+	}
+
 	if (tab_found == 0 && HAS_BIT(flag, TAB_FLAG_DICTIONARY))
 	if (tab_found == 0 && HAS_BIT(flag, TAB_FLAG_DICTIONARY))
 	{
 	{
 		tab_found = cursor_dictionary_tab_add(flag);
 		tab_found = cursor_dictionary_tab_add(flag);
@@ -2681,6 +2840,11 @@ void cursor_tab_backward(struct session *ses, int flag)
 			cursor_scrollback_tab_add(flag);
 			cursor_scrollback_tab_add(flag);
 		}
 		}
 
 
+		if (HAS_BIT(flag, TAB_FLAG_INPUT))
+		{
+			cursor_input_tab_add(flag);
+		}
+
 		if (HAS_BIT(flag, TAB_FLAG_DICTIONARY))
 		if (HAS_BIT(flag, TAB_FLAG_DICTIONARY))
 		{
 		{
 			cursor_dictionary_tab_add(flag);
 			cursor_dictionary_tab_add(flag);
@@ -2708,6 +2872,7 @@ DO_CURSOR(cursor_tab)
 		tintin_printf2(ses, "  [%-18s] %s", "CASELESS", "Make the tab completion caseless");
 		tintin_printf2(ses, "  [%-18s] %s", "CASELESS", "Make the tab completion caseless");
 		tintin_printf2(ses, "  [%-18s] %s", "COMPLETE", "Make the tab completion work while editing");
 		tintin_printf2(ses, "  [%-18s] %s", "COMPLETE", "Make the tab completion work while editing");
 		tintin_printf2(ses, "  [%-18s] %s", "DICTIONARY", "Make the tab completion include the dictionary");
 		tintin_printf2(ses, "  [%-18s] %s", "DICTIONARY", "Make the tab completion include the dictionary");
+		tintin_printf2(ses, "  [%-18s] %s", "INPUT", "Make the tab completion include the input history");
 		tintin_printf2(ses, "  [%-18s] %s", "LIST", "Make the tab completion include the tab completion list");
 		tintin_printf2(ses, "  [%-18s] %s", "LIST", "Make the tab completion include the tab completion list");
 		tintin_printf2(ses, "  [%-18s] %s", "SCROLLBACK", "Make the tab completion include the scrollback buffer");
 		tintin_printf2(ses, "  [%-18s] %s", "SCROLLBACK", "Make the tab completion include the scrollback buffer");
 		tintin_printf2(ses, "  [%-18s] %s", "BACKWARD", "Make the tab completion go backward");
 		tintin_printf2(ses, "  [%-18s] %s", "BACKWARD", "Make the tab completion go backward");
@@ -2738,6 +2903,10 @@ DO_CURSOR(cursor_tab)
 		{
 		{
 			SET_BIT(flag, TAB_FLAG_LIST);
 			SET_BIT(flag, TAB_FLAG_LIST);
 		}
 		}
+		else if (is_abbrev(arg1, "INPUT"))
+		{
+			SET_BIT(flag, TAB_FLAG_INPUT);
+		}
 		else if (is_abbrev(arg1, "SCROLLBACK"))
 		else if (is_abbrev(arg1, "SCROLLBACK"))
 		{
 		{
 			SET_BIT(flag, TAB_FLAG_SCROLLBACK);
 			SET_BIT(flag, TAB_FLAG_SCROLLBACK);
@@ -2764,9 +2933,9 @@ DO_CURSOR(cursor_tab)
 			return cursor_redraw_line(ses, arg);
 			return cursor_redraw_line(ses, arg);
 		}
 		}
 
 
-		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
+		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_INPUT|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
 		{
 		{
-			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|LIST|SCROLLBACK> FORWARD}");
+			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|INPUT|LIST|SCROLLBACK> FORWARD}");
 		}
 		}
 		else
 		else
 		{
 		{
@@ -2780,15 +2949,15 @@ DO_CURSOR(cursor_tab)
 		if (!HAS_BIT(flag, TAB_FLAG_COMPLETE) && inputline_editor())
 		if (!HAS_BIT(flag, TAB_FLAG_COMPLETE) && inputline_editor())
 		{
 		{
 			snprintf(arg1, BUFFER_SIZE, "%*s", gtd->ses->tab_width, "");
 			snprintf(arg1, BUFFER_SIZE, "%*s", gtd->ses->tab_width, "");
-			
+
 			inputline_insert(arg1, 0);
 			inputline_insert(arg1, 0);
 
 
 			return cursor_redraw_line(ses, arg);
 			return cursor_redraw_line(ses, arg);
 		}
 		}
 
 
-		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
+		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_INPUT|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
 		{
 		{
-			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|LIST|SCROLLBACK> BACKWARD}");
+			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|INPUT|LIST|SCROLLBACK> BACKWARD}");
 		}
 		}
 		else
 		else
 		{
 		{
@@ -2797,6 +2966,6 @@ DO_CURSOR(cursor_tab)
 	}
 	}
 	else
 	else
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|LIST|SCROLLBACK> <BACKWARD|FORWARD>}");
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|INPUT|LIST|SCROLLBACK> <BACKWARD|FORWARD>}");
 	}
 	}
 }
 }

+ 3 - 3
src/daemon.c

@@ -32,7 +32,7 @@
 #include <util.h>
 #include <util.h>
 #endif
 #endif
 #endif
 #endif
-#include <fcntl.h>  
+#include <fcntl.h>
 #include <dirent.h>
 #include <dirent.h>
 #include <termios.h>
 #include <termios.h>
 #include <sys/un.h>
 #include <sys/un.h>
@@ -223,7 +223,7 @@ DO_DAEMON(daemon_attach)
 	if (pid == getpid())
 	if (pid == getpid())
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#ERROR: #DAEMON ATTACH: {%s} CANNOT ATTACH TO ITSELF.", filename);
 		show_error(ses, LIST_COMMAND, "#ERROR: #DAEMON ATTACH: {%s} CANNOT ATTACH TO ITSELF.", filename);
-		
+
 		return;
 		return;
 	}
 	}
 
 
@@ -313,7 +313,7 @@ DO_DAEMON(daemon_attach)
 
 
 		gtd->attach_sock = 0;
 		gtd->attach_sock = 0;
 //		gtd->attach_sock = close(gtd->attach_sock);
 //		gtd->attach_sock = close(gtd->attach_sock);
-		
+
 		return;
 		return;
 	}
 	}
 
 

+ 29 - 26
src/data.c

@@ -420,12 +420,15 @@ void delete_node(struct session *ses, int type, struct listnode *node)
 
 
 	insert_index_list(gtd->dispose_list, node, gtd->dispose_list->used);
 	insert_index_list(gtd->dispose_list, node, gtd->dispose_list->used);
 
 
-	switch (type)
+	if (!HAS_BIT(ses->flags, SES_FLAG_CLOSED))
 	{
 	{
-		case LIST_CLASS:
-			check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS DESTROYED", node->arg1);
-			check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS DESTROYED %s", node->arg1, node->arg1);
-			break;
+		switch (type)
+		{
+			case LIST_CLASS:
+				check_all_events(ses, EVENT_FLAG_CLASS, 0, 1, "CLASS DESTROYED", node->arg1);
+				check_all_events(ses, EVENT_FLAG_CLASS, 1, 1, "CLASS DESTROYED %s", node->arg1, node->arg1);
+				break;
+		}
 	}
 	}
 }
 }
 
 
@@ -494,7 +497,7 @@ int search_index_list(struct listroot *root, char *text, char *priority)
 		case SORT_ALPHA:
 		case SORT_ALPHA:
 		case SORT_STABLE:
 		case SORT_STABLE:
 			return bsearch_alpha_list(root, text, 0);
 			return bsearch_alpha_list(root, text, 0);
-		
+
 		case SORT_ALNUM:
 		case SORT_ALNUM:
 			return bsearch_alnum_list(root, text, 0);
 			return bsearch_alnum_list(root, text, 0);
 
 
@@ -508,7 +511,7 @@ int search_index_list(struct listroot *root, char *text, char *priority)
 
 
 	return nsearch_list(root, text);
 	return nsearch_list(root, text);
 }
 }
- 
+
 /*
 /*
 	Return insertion index.
 	Return insertion index.
 */
 */
@@ -1148,7 +1151,7 @@ DO_COMMAND(do_message)
 			else
 			else
 			{
 			{
 				show_error(ses, LIST_COMMAND, "#SYNTAX: #MESSAGE {%s} [ON|OFF]",  arg1);
 				show_error(ses, LIST_COMMAND, "#SYNTAX: #MESSAGE {%s} [ON|OFF]",  arg1);
-				
+
 				return ses;
 				return ses;
 			}
 			}
 			show_message(ses, LIST_COMMAND, "#OK: #MESSAGE STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ? "ON" : "OFF");
 			show_message(ses, LIST_COMMAND, "#OK: #MESSAGE STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ? "ON" : "OFF");
@@ -1221,7 +1224,7 @@ DO_COMMAND(do_ignore)
 				else
 				else
 				{
 				{
 					show_error(ses, LIST_COMMAND, "#SYNTAX: #IGNORE {%s} [ON|OFF]", arg1);
 					show_error(ses, LIST_COMMAND, "#SYNTAX: #IGNORE {%s} [ON|OFF]", arg1);
-				
+
 					return ses;
 					return ses;
 				}
 				}
 				show_message(ses, LIST_COMMAND, "#OK: #IGNORE STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE) ? "ON" : "OFF");
 				show_message(ses, LIST_COMMAND, "#OK: #IGNORE STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE) ? "ON" : "OFF");
@@ -1299,7 +1302,7 @@ DO_COMMAND(do_debug)
 			else
 			else
 			{
 			{
 				show_error(ses, LIST_COMMAND, "#SYNTAX: #DEBUG {%s} [ON|OFF|LOG]", arg1);
 				show_error(ses, LIST_COMMAND, "#SYNTAX: #DEBUG {%s} [ON|OFF|LOG]", arg1);
-				
+
 				return ses;
 				return ses;
 			}
 			}
 			show_message(ses, LIST_COMMAND, "#OK: #DEBUG STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, is_abbrev(arg2, "LOG") ? "LOG" : HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG) ? "ON" : "OFF");
 			show_message(ses, LIST_COMMAND, "#OK: #DEBUG STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, is_abbrev(arg2, "LOG") ? "LOG" : HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG) ? "ON" : "OFF");
@@ -1708,14 +1711,14 @@ DO_COMMAND(do_info)
 					}
 					}
 					else
 					else
 					{
 					{
-						tintin_printf2(ses, "{NAME}{%s}", ses->name);
-						tintin_printf2(ses, "{ACTIVE}{%d}", gtd->ses == ses);
-						tintin_printf2(ses, "{CLASS}{%s}", ses->group);
-						tintin_printf2(ses, "{CREATED}{%d}", ses->created);
-						tintin_printf2(ses, "{HOST} {%s}", ses->session_host);
-						tintin_printf2(ses, "{IP} {%s}", ses->session_ip);
-						tintin_printf2(ses, "{MTTS} {%d}", get_mtts_val(ses));
-						tintin_printf2(ses, "{PORT} {%s}", ses->session_port);
+						tintin_printf2(ses, "#INFO SESSION: {NAME}{%s}", ses->name);
+						tintin_printf2(ses, "#INFO SESSION: {ACTIVE}{%d}", gtd->ses == ses);
+						tintin_printf2(ses, "#INFO SESSION: {CLASS}{%s}", ses->group);
+						tintin_printf2(ses, "#INFO SESSION: {CREATED}{%d}", ses->created);
+						tintin_printf2(ses, "#INFO SESSION: {HOST} {%s}", ses->session_host);
+						tintin_printf2(ses, "#INFO SESSION: {IP} {%s}", ses->session_ip);
+						tintin_printf2(ses, "#INFO SESSION: {MTTS} {%d}", get_mtts_val(ses));
+						tintin_printf2(ses, "#INFO SESSION: {PORT} {%s}", ses->session_port);
 					}
 					}
 				}
 				}
 				else if (is_abbrev(arg1, "SESSIONS"))
 				else if (is_abbrev(arg1, "SESSIONS"))
@@ -1745,14 +1748,14 @@ DO_COMMAND(do_info)
 					{
 					{
 						for (sesptr = gts ; sesptr ; sesptr = sesptr->next)
 						for (sesptr = gts ; sesptr ; sesptr = sesptr->next)
 						{
 						{
-							tintin_printf2(ses, "{%s}{NAME}{%s}", sesptr->name, sesptr->name);
-							tintin_printf2(ses, "{%s}{ACTIVE}{%d}", sesptr->name, gtd->ses == sesptr);
-							tintin_printf2(ses, "{%s}{CLASS}{%s}", sesptr->name, sesptr->group);
-							tintin_printf2(ses, "{%s}{CREATED}{%d}", sesptr->name, sesptr->created);
-							tintin_printf2(ses, "{%s}{HOST} {%s}", sesptr->name, sesptr->session_host);
-							tintin_printf2(ses, "{%s}{IP} {%s}", sesptr->name, sesptr->session_ip);
-							tintin_printf2(ses, "{%s}{MTTS} {%d}", sesptr->name, get_mtts_val(ses));
-							tintin_printf2(ses, "{%s}{PORT} {%s}", sesptr->name, sesptr->session_port);
+							tintin_printf2(ses, "#INFO SESSIONS: {%s}{NAME}{%s}", sesptr->name, sesptr->name);
+							tintin_printf2(ses, "#INFO SESSIONS: {%s}{ACTIVE}{%d}", sesptr->name, gtd->ses == sesptr);
+							tintin_printf2(ses, "#INFO SESSIONS: {%s}{CLASS}{%s}", sesptr->name, sesptr->group);
+							tintin_printf2(ses, "#INFO SESSIONS: {%s}{CREATED}{%d}", sesptr->name, sesptr->created);
+							tintin_printf2(ses, "#INFO SESSIONS: {%s}{HOST} {%s}", sesptr->name, sesptr->session_host);
+							tintin_printf2(ses, "#INFO SESSIONS: {%s}{IP} {%s}", sesptr->name, sesptr->session_ip);
+							tintin_printf2(ses, "#INFO SESSIONS: {%s}{MTTS} {%d}", sesptr->name, get_mtts_val(ses));
+							tintin_printf2(ses, "#INFO SESSIONS: {%s}{PORT} {%s}", sesptr->name, sesptr->session_port);
 						}
 						}
 					}
 					}
 				}
 				}

+ 10 - 27
src/draw.c

@@ -458,15 +458,10 @@ DO_COMMAND(do_draw)
 			if (!is_math(ses, arg1) || !is_math(ses, arg2) || !is_math(ses, arg3) || !is_math(ses, arg4))
 			if (!is_math(ses, arg1) || !is_math(ses, arg2) || !is_math(ses, arg3) || !is_math(ses, arg4))
 			{
 			{
 				show_error(ses, LIST_COMMAND, "#ERROR: #DRAW: INVALID SQUARE: %s {%s} {%s} {%s} {%s}", draw_table[index].name, arg1, arg2, arg3, arg4);
 				show_error(ses, LIST_COMMAND, "#ERROR: #DRAW: INVALID SQUARE: %s {%s} {%s} {%s} {%s}", draw_table[index].name, arg1, arg2, arg3, arg4);
-//					is_math(ses, arg1) ? ntos(top_row) : arg1,
-//					is_math(ses, arg2) ? ntos(top_col) : arg2,
-//					is_math(ses, arg3) ? ntos(bot_row) : arg3,
-//					is_math(ses, arg4) ? ntos(bot_col) : arg4);
 
 
 				return ses;
 				return ses;
 			}
 			}
 
 
-
 			if (top_row == 0 && top_col == 0)
 			if (top_row == 0 && top_col == 0)
 			{
 			{
 				show_error(ses, LIST_COMMAND, "#SYNTAX: #DRAW [COLOR] [OPTIONS] {%s} <TOP_ROW> <TOP_COL> <BOT_ROW> <BOT_COL> [TEXT]", draw_table[index].name);
 				show_error(ses, LIST_COMMAND, "#SYNTAX: #DRAW [COLOR] [OPTIONS] {%s} <TOP_ROW> <TOP_COL> <BOT_ROW> <BOT_COL> [TEXT]", draw_table[index].name);
@@ -476,8 +471,6 @@ DO_COMMAND(do_draw)
 
 
 			if (top_row == 0)
 			if (top_row == 0)
 			{
 			{
-				top_row = 1;
-
 				SET_BIT(flags, DRAW_FLAG_SCROLL);
 				SET_BIT(flags, DRAW_FLAG_SCROLL);
 			}
 			}
 			else
 			else
@@ -490,20 +483,10 @@ DO_COMMAND(do_draw)
 				}
 				}
 			}
 			}
 
 
-			if (top_col == 0)
-			{
-				top_col = 1;
-			}
-
-			if (bot_row == 0)
-			{
-				bot_row = 1;
-			}
-
-			if (bot_col == 0)
-			{
-				bot_col = 1;
-			}
+			if (top_row == 0) top_row = 1;
+			if (top_col == 0) top_col = 1;
+			if (bot_row == 0) bot_row = 1;
+			if (bot_col == 0) bot_col = 1;
 
 
 			if (top_row > bot_row || top_col > bot_col)
 			if (top_row > bot_row || top_col > bot_col)
 			{
 			{
@@ -772,7 +755,7 @@ void string_to_font(struct session *ses, long long flags, char *in, char *out)
 			pto += sprintf(pto, "%.*s", skip, pti);
 			pto += sprintf(pto, "%.*s", skip, pti);
 
 
 			pti += skip;
 			pti += skip;
-			
+
 			continue;
 			continue;
 		}
 		}
 
 
@@ -963,7 +946,7 @@ void string_to_stamp(struct session *ses, long long flags, char *in, char *out)
 			get_color_codes(color, pti, color, GET_ONE);
 			get_color_codes(color, pti, color, GET_ONE);
 
 
 			pti += skip;
 			pti += skip;
-			
+
 			continue;
 			continue;
 		}
 		}
 		pti = get_char(ses, pti, chr1);
 		pti = get_char(ses, pti, chr1);
@@ -1543,7 +1526,7 @@ DO_DRAW(draw_corner)
 	else
 	else
 	{
 	{
 		goto_pos(ses, top_row, top_col);
 		goto_pos(ses, top_row, top_col);
-		
+
 		print_stdout(top_row, top_col, "%s%s", box_color, arg1);
 		print_stdout(top_row, top_col, "%s%s", box_color, arg1);
 	}
 	}
 }
 }
@@ -1731,7 +1714,7 @@ DO_DRAW(draw_line)
 	if (top_col == bot_col)
 	if (top_col == bot_col)
 	{
 	{
 		draw_line_vertical(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 		draw_line_vertical(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
-		
+
 		return;
 		return;
 	}
 	}
 
 
@@ -1791,7 +1774,7 @@ DO_DRAW(draw_map)
 // 3 use calign for centered bar
 // 3 use calign for centered bar
 // 4 use box drawing modifiers if no box is specified.
 // 4 use box drawing modifiers if no box is specified.
 // 4.1 rounded = (###)
 // 4.1 rounded = (###)
-// 4.2 teed    = [---] 
+// 4.2 teed    = [---]
 // 4.3 jeweled = <###>
 // 4.3 jeweled = <###>
 // 4.4 crossed = +++++
 // 4.4 crossed = +++++
 // 4.5 circled = OOOOO
 // 4.5 circled = OOOOO
@@ -2365,7 +2348,7 @@ DO_DRAW(draw_table_grid)
 						{
 						{
 							strcat(buf3, arg2);
 							strcat(buf3, arg2);
 						}
 						}
-	
+
 						if (*str == COMMAND_SEPARATOR)
 						if (*str == COMMAND_SEPARATOR)
 						{
 						{
 							str++;
 							str++;

+ 10 - 5
src/edit.c

@@ -114,7 +114,7 @@ DO_EDIT(edit_load)
 	if ((node = search_nest_node_ses(ses, arg1)) == NULL)
 	if ((node = search_nest_node_ses(ses, arg1)) == NULL)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#EDIT LOAD: VARIABLE {%s} NOT FOUND.", arg1);
 		show_error(ses, LIST_COMMAND, "#EDIT LOAD: VARIABLE {%s} NOT FOUND.", arg1);
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -260,6 +260,8 @@ DO_EDIT(edit_resume)
 
 
 	inputline_set(edit->line[edit->update]->str, 0);
 	inputline_set(edit->line[edit->update]->str, 0);
 
 
+	check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 1, "EDIT RESUMED", gtd->ses->input->edit_name);
+
 	cursor_redraw_edit(ses, "");
 	cursor_redraw_edit(ses, "");
 
 
 	return ses;
 	return ses;
@@ -284,6 +286,8 @@ DO_EDIT(edit_suspend)
 
 
 	cursor_redraw_edit(ses, "");
 	cursor_redraw_edit(ses, "");
 
 
+	check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 1, "EDIT SUSPENDED", gtd->ses->input->edit_name);
+
 	return ses;
 	return ses;
 }
 }
 
 
@@ -347,14 +351,15 @@ void enable_editor(struct edit_data *edit)
 
 
 	filesize = str_save_editor(gtd->ses->input->edit, &str1);
 	filesize = str_save_editor(gtd->ses->input->edit, &str1);
 
 
-	cursor_redraw_edit(gtd->ses, "");
-
-	check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 4, "STARTED EDITING", gtd->ses->input->edit_name, ntos(edit->used), ntos(filesize), str1);
+	check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 4, "EDIT STARTED", gtd->ses->input->edit_name, ntos(edit->used), ntos(filesize), str1);
 
 
 	if (*gtd->ses->input->edit_name)
 	if (*gtd->ses->input->edit_name)
 	{
 	{
-		check_all_events(gtd->ses, EVENT_FLAG_INPUT, 1, 4, "STARTED EDITING %s", gtd->ses->input->edit_name, gtd->ses->input->edit_name, ntos(edit->used), ntos(filesize), str1);
+		check_all_events(gtd->ses, EVENT_FLAG_INPUT, 1, 4, "EDIT STARTED %s", gtd->ses->input->edit_name, gtd->ses->input->edit_name, ntos(edit->used), ntos(filesize), str1);
 	}
 	}
+
+	cursor_redraw_edit(gtd->ses, "");
+
 }
 }
 
 
 int str_save_editor(struct edit_data *edit, char **str)
 int str_save_editor(struct edit_data *edit, char **str)

+ 8 - 5
src/event.c

@@ -215,7 +215,7 @@ int check_all_events(struct session *ses, int flags, int args, int vars, char *f
 			syserr_printf(ses, "check_all_events: vasprintf:");
 			syserr_printf(ses, "check_all_events: vasprintf:");
 		}
 		}
 
 
-		va_end(list); 
+		va_end(list);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -268,9 +268,12 @@ int check_all_events(struct session *ses, int flags, int args, int vars, char *f
 
 
 				substitute(ses_ptr, node->arg2, buf, sub);
 				substitute(ses_ptr, node->arg2, buf, sub);
 
 
-				if (!HAS_BIT(flags, EVENT_FLAG_UPDATE) && HAS_BIT(ses_ptr->list[LIST_EVENT]->flags, LIST_FLAG_DEBUG))
+				if (!HAS_BIT(flags, EVENT_FLAG_UPDATE))
 				{
 				{
-					show_debug(ses_ptr, LIST_EVENT, COLOR_DEBUG "#DEBUG EVENT " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+					if (HAS_BIT(ses_ptr->list[LIST_EVENT]->flags, LIST_FLAG_DEBUG) || HAS_BIT(node->flags, NODE_FLAG_DEBUG))
+					{
+						show_debug(ses_ptr, LIST_EVENT, node, COLOR_DEBUG "#DEBUG EVENT " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+					}
 				}
 				}
 
 
 				if (node->shots && --node->shots == 0)
 				if (node->shots && --node->shots == 0)
@@ -280,7 +283,7 @@ int check_all_events(struct session *ses, int flags, int args, int vars, char *f
 
 
 				gtd->level->quiet += HAS_BIT(flags, EVENT_FLAG_UPDATE) ? 1 : 0;
 				gtd->level->quiet += HAS_BIT(flags, EVENT_FLAG_UPDATE) ? 1 : 0;
 
 
-				script_driver(ses_ptr, LIST_EVENT, buf);
+				script_driver(ses_ptr, LIST_EVENT, node, buf);
 
 
 				gtd->level->quiet -= HAS_BIT(flags, EVENT_FLAG_UPDATE) ? 1 : 0;
 				gtd->level->quiet -= HAS_BIT(flags, EVENT_FLAG_UPDATE) ? 1 : 0;
 
 
@@ -576,7 +579,7 @@ void mouse_handler(struct session *ses, int flags, int row, int col)
 			{
 			{
 				strcpy(dir, swipe[9] > 0 ? "NE" : "NW");
 				strcpy(dir, swipe[9] > 0 ? "NE" : "NW");
 			}
 			}
-			check_all_events(ses, EVENT_FLAG_MOUSE, 0, 12, "SWIPED", dir, arg2, ntos(swipe[0]), ntos(swipe[1]), ntos(swipe[2]), ntos(swipe[3]), ntos(swipe[4]), ntos(swipe[5]), ntos(swipe[6]), ntos(swipe[7]), ntos(swipe[8]), ntos(swipe[9]));			
+			check_all_events(ses, EVENT_FLAG_MOUSE, 0, 12, "SWIPED", dir, arg2, ntos(swipe[0]), ntos(swipe[1]), ntos(swipe[2]), ntos(swipe[3]), ntos(swipe[4]), ntos(swipe[5]), ntos(swipe[6]), ntos(swipe[7]), ntos(swipe[8]), ntos(swipe[9]));
 			check_all_events(ses, EVENT_FLAG_MOUSE, 1, 12, "SWIPED %s", dir, dir, arg2, ntos(swipe[0]), ntos(swipe[1]), ntos(swipe[2]), ntos(swipe[3]), ntos(swipe[4]), ntos(swipe[5]), ntos(swipe[6]), ntos(swipe[7]), ntos(swipe[8]), ntos(swipe[9]));
 			check_all_events(ses, EVENT_FLAG_MOUSE, 1, 12, "SWIPED %s", dir, dir, arg2, ntos(swipe[0]), ntos(swipe[1]), ntos(swipe[2]), ntos(swipe[3]), ntos(swipe[4]), ntos(swipe[5]), ntos(swipe[6]), ntos(swipe[7]), ntos(swipe[8]), ntos(swipe[9]));
 			check_all_events(ses, EVENT_FLAG_MOUSE, 2, 12, "SWIPED %s %s", arg2, dir, dir, arg2, ntos(swipe[0]), ntos(swipe[1]), ntos(swipe[2]), ntos(swipe[3]), ntos(swipe[4]), ntos(swipe[5]), ntos(swipe[6]), ntos(swipe[7]), ntos(swipe[8]), ntos(swipe[9]));
 			check_all_events(ses, EVENT_FLAG_MOUSE, 2, 12, "SWIPED %s %s", arg2, dir, dir, arg2, ntos(swipe[0]), ntos(swipe[1]), ntos(swipe[2]), ntos(swipe[3]), ntos(swipe[4]), ntos(swipe[5]), ntos(swipe[6]), ntos(swipe[7]), ntos(swipe[8]), ntos(swipe[9]));
 		}
 		}

+ 5 - 5
src/files.c

@@ -98,7 +98,7 @@ struct session *read_file(struct session *ses, FILE *file, char *filename)
 	if (fread(bufi, 1, size, file) <= 0)
 	if (fread(bufi, 1, size, file) <= 0)
 	{
 	{
 		check_all_events(ses, EVENT_FLAG_SYSTEM, 0, 2, "READ ERROR", filename, "FREAD FAILURE");
 		check_all_events(ses, EVENT_FLAG_SYSTEM, 0, 2, "READ ERROR", filename, "FREAD FAILURE");
-		
+
 		tintin_printf(ses, "#ERROR: #READ {%s}: FREAD FAILURE.", filename);
 		tintin_printf(ses, "#ERROR: #READ {%s}: FREAD FAILURE.", filename);
 
 
 		return ses;
 		return ses;
@@ -332,7 +332,7 @@ struct session *read_file(struct session *ses, FILE *file, char *filename)
 
 
 		gtd->level->quiet++;
 		gtd->level->quiet++;
 
 
-		script_driver(ses, LIST_COMMAND, temp);
+		script_driver(ses, LIST_COMMAND, NULL, temp);
 
 
 		gtd->level->quiet--;
 		gtd->level->quiet--;
 	}
 	}
@@ -360,12 +360,12 @@ struct session *read_file(struct session *ses, FILE *file, char *filename)
 
 
 		if (pto - bufi >= BUFFER_SIZE)
 		if (pto - bufi >= BUFFER_SIZE)
 		{
 		{
-			show_debug(ses, LIST_COMMAND, "#WARNING: #READ {%s}: POSSIBLE BUFFER OVERFLOW AT COMMAND: %.30s", filename, bufi);
+			show_debug(ses, LIST_COMMAND, NULL, "#WARNING: #READ {%s}: POSSIBLE BUFFER OVERFLOW AT COMMAND: %.30s", filename, bufi);
 		}
 		}
 
 
 		if (bufi[0])
 		if (bufi[0])
 		{
 		{
-			ses = script_driver(ses, LIST_COMMAND, bufi);
+			ses = script_driver(ses, LIST_COMMAND, NULL, bufi);
 		}
 		}
 		pto = bufi;
 		pto = bufi;
 		pti++;
 		pti++;
@@ -426,7 +426,7 @@ DO_COMMAND(do_write)
 
 
 		return ses;
 		return ses;
 	}
 	}
-	
+
 	if (is_suffix(arg1, ".map") && !is_abbrev(arg2, "FORCE"))
 	if (is_suffix(arg1, ".map") && !is_abbrev(arg2, "FORCE"))
 	{
 	{
 		check_all_events(ses, EVENT_FLAG_SYSTEM, 0, 2, "WRITE ERROR", arg1, "INVALID FILE EXTENSION");
 		check_all_events(ses, EVENT_FLAG_SYSTEM, 0, 2, "WRITE ERROR", arg1, "INVALID FILE EXTENSION");

+ 138 - 0
src/gui.h

@@ -731,3 +731,141 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "}\n"
 "}\n"
 
 
 "#delay 0 gui_init\n";
 "#delay 0 gui_init\n";
+
+
+char *tt_regex = "#event {PROGRAM START}\n"
+"{\n"
+"	#var tab {{i}{0}{0}{}{1}{}};\n"
+"	#info matches save;\n"
+"	draw_gui;\n"
+"	#config mouse on\n"
+"}\n"
+"\n"
+"#event {SCREEN RESIZE}\n"
+"{\n"
+"	draw_gui;\n"
+"	#buffer end\n"
+"}\n"
+"\n"
+"#alias {draw_gui}\n"
+"{\n"
+"	#screen clear scroll;\n"
+"	#screen scroll 7 1 -4 -1;\n"
+"	#draw jade Silver rounded talign box 1 1 3 -1;\n"
+"	#draw jade Azure scaled tile 1 3 1 6 {REGULAR EXPRESSION};\n"
+"	#draw jade Silver rounded talign box 4 1 6 -1;\n"
+"	#draw jade Azure scaled tile 4 3 4 6 {TEST STRING};\n"
+"	#draw jade Green rounded calign box -3 -6 -1 -1 {exit};\n"
+"	#draw jade Green rounded calign box -3 -12 -1 -7 {help};\n"
+"\n"
+"	#screen inputregion 5 2 5 -2 TAB_2;\n"
+"	next_tab;\n"
+"	next_tab\n"
+"}\n"
+"\n"
+"#alias {next_tab}\n"
+"{\n"
+"	#if {$tab[i] == 0}\n"
+"	{\n"
+"		#screen inputregion 5 2 5 -2 TAB_2;\n"
+"		#cursor clear;\n"
+"		#cursor set $tab[1];\n"
+"	};\n"
+"	#if {$tab[i] == 1}\n"
+"	{\n"
+"		#screen inputregion 2 2 2 -2 TAB_1;\n"
+"		#cursor clear;\n"
+"		#cursor set $tab[0];\n"
+"	};\n"
+"	#math tab[i] ($tab[i] + 1) % 2;\n"
+"}\n"
+"\n"
+"#alias {mouse_tab}\n"
+"{\n"
+"	#var tab[i] %1;\n"
+"	#if {%1 == 0}\n"
+"	{\n"
+"		#screen inputregion 2 2 2 -2;\n"
+"		#cursor clear;\n"
+"		#cursor set $tab[0]\n"
+"	};\n"
+"	#if {%1 == 1}\n"
+"	{\n"
+"		#screen inputregion 5 2 5 -2;\n"
+"		#cursor clear;\n"
+"		#cursor set $tab[1]\n"
+"	};\n"
+"	#cursor position %2\n"
+"}\n"
+"\n"
+"#button {2;2;2;-2;PRESSED MOUSE BUTTON ONE} {mouse_tab 0 %3-1}\n"
+"#button {5;2;5;-2;PRESSED MOUSE BUTTON ONE} {mouse_tab 1 %3-1}\n"
+"#button {-3;-6;-1;-1} {#end}\n"
+"#button {-3;-12;-1;-7} {#buffer clear;#help regex}\n"
+"\n"
+"#event {SCROLLED MOUSE WHEEL DOWN} {#buffer down 3}\n"
+"#event {SCROLLED MOUSE WHEEL UP} {#buffer up 3}\n"
+"\n"
+"#macro {\t}\n"
+"{\n"
+"	next_tab\n"
+"}\n"
+"\n"
+"#alias {matches}\n"
+"{\n"
+"	#var result {};\n"
+"\n"
+"	#foreach {*info[MATCHES][]} {index}\n"
+"	{\n"
+"		#format temp {\\n%+3s %s} {<138>%$index} {<178>$info[MATCHES][$index]};\n"
+"		#cat result {$temp}\n"
+"	};\n"
+"	#if {{$last} === {$result}}\n"
+"	{\n"
+"		#return\n"
+"	};\n"
+"	#buffer clear;\n"
+"	#screen clear scroll;\n"
+"	#line ignore #showme {$result};\n"
+"\n"
+"	#var last {$result}\n"
+"}\n"
+"\n"
+"#event {GAG NO SESSION ACTIVE} {#nop}\n"
+"\n"
+"#event {PROCESSED KEYPRESS}\n"
+"{\n"
+"	#cursor get temp;\n"
+"	#replace temp {\\\\x7B%*\\\\x7D} {{&1}};\n"
+"	#replace temp {\\\\x7B%*\\\\x7D} {{&1}};\n"
+"\n"
+"	#if {{$temp} !== {$tab[$tab[i]]}}\n"
+"	{\n"
+"		#cursor get tab[$tab[i]];\n"
+"		#delay {input} {input_update} {0.1}\n"
+"	}\n"
+"}\n"
+"\n"
+"#alias {input_update}\n"
+"{\n"
+"	#replace tab[0] {\\\\x7B%*\\\\x7D} {{&1}};\n"
+"	#replace tab[0] {\\\\x7B%*\\\\x7D} {{&1}};\n"
+"	#replace tab[1] {\\\\x7B%*\\\\x7D} {{&1}};\n"
+"	#replace tab[1] {\\\\x7B%*\\\\x7D} {{&1}};\n"
+"\n"
+"	#regex {$tab[1]} {$tab[0]}\n"
+"	{\n"
+"		#info matches save\n"
+"	}\n"
+"	{\n"
+"		#if {{$last} !== {}}\n"
+"		{\n"
+"			#buffer clear;\n"
+"			#screen clear scroll;\n"
+"			#line ignore #showme {<118>The regular expression does not match the test string.\n};\n"
+"			#var last {}\n"
+"		};\n"
+"		#return\n"
+"	};\n"
+"	matches\n"
+"}\n";

+ 78 - 70
src/help.c

@@ -71,8 +71,8 @@ char *help_related(struct session *ses, int index, int html)
 
 
 	push_call("help_related(%p,%d,%d)",ses,index,html);
 	push_call("help_related(%p,%d,%d)",ses,index,html);
 
 
-	tmp  = str_alloc_stack(0);
-	link = str_alloc_stack(0);
+	tmp   = str_alloc_stack(0);
+	link  = str_alloc_stack(0);
 
 
 	arg  = help_table[index].also;
 	arg  = help_table[index].also;
 
 
@@ -84,7 +84,7 @@ char *help_related(struct session *ses, int index, int html)
 
 
 		if (html == 1)
 		if (html == 1)
 		{
 		{
-			sprintf(link, "\\c<a href='%s.php'\\c>%s\\c</a\\c>", tmp, tmp);
+			sprintf(link, "\\c<a href='%s.php'\\c>%s\\c</a\\c>", decapitalize(tmp), tmp);
 		}
 		}
 		else if (html == 2)
 		else if (html == 2)
 		{
 		{
@@ -216,7 +216,7 @@ DO_COMMAND(do_help)
 
 
 		FILE *logfile = fopen("../docs/help.html", "w");
 		FILE *logfile = fopen("../docs/help.html", "w");
 
 
-		script_driver(ses, LIST_COMMAND, "#config {log} {html}");
+		script_driver(ses, LIST_COMMAND, NULL, "#config {log} {html}");
 
 
 		if (HAS_BIT(ses->log->mode, LOG_FLAG_HTML))
 		if (HAS_BIT(ses->log->mode, LOG_FLAG_HTML))
 		{
 		{
@@ -415,7 +415,7 @@ DO_COMMAND(do_help)
 	{
 	{
 		FILE *logfile;
 		FILE *logfile;
 
 
-		script_driver(ses, LIST_COMMAND, "#config {log} {html}");
+		script_driver(ses, LIST_COMMAND, NULL, "#config {log} {html}");
 
 
 		*buf = 0;
 		*buf = 0;
 
 
@@ -544,10 +544,6 @@ struct help_type help_table[] =
 		"<278>         arguments. The priority part is optional and determines the priority\n"
 		"<278>         arguments. The priority part is optional and determines the priority\n"
 		"<278>         of the alias, it defaults to 5.\n"
 		"<278>         of the alias, it defaults to 5.\n"
 		"\n"
 		"\n"
-		"<278>         If no % variable is used in the commands section any argument will be\n"
-		"<278>         appended to the end as if %0 was used. This feature might be removed\n"
-		"<278>         in the future, and shouldn't be used.\n"
-		"\n"
 		"<178>Example<278>: #alias {k} {kill %1;kick}\n"
 		"<178>Example<278>: #alias {k} {kill %1;kick}\n"
 		"\n"
 		"\n"
 		"<278>         Typing 'k orc' would result in attacking the orc followed by a kick.\n"
 		"<278>         Typing 'k orc' would result in attacking the orc followed by a kick.\n"
@@ -639,7 +635,7 @@ struct help_type help_table[] =
 		"<278>         to the next.\n"
 		"<278>         to the next.\n"
 		"\n"
 		"\n"
 		"<178>Example<278>: #while {1} {#math cnt $cnt + 1;#if {$cnt == 20} {#break}}\n",
 		"<178>Example<278>: #while {1} {#math cnt $cnt + 1;#if {$cnt == 20} {#break}}\n",
-		
+
 		"statements"
 		"statements"
 	},
 	},
 	{
 	{
@@ -869,7 +865,7 @@ struct help_type help_table[] =
 		"<278>         clients, typically for the purpose of chatting and sending files.\n"
 		"<278>         clients, typically for the purpose of chatting and sending files.\n"
 		"<278>         This is a decentralized chat system, meaning you have to exchange ip\n"
 		"<278>         This is a decentralized chat system, meaning you have to exchange ip\n"
 		"<278>         addresses and port numbers with other users in order to connect to\n"
 		"<278>         addresses and port numbers with other users in order to connect to\n"
-		"<278>         them.\n"
+		"<278>         them. Chat events are triggered in the startup session.\n"
 		"\n"
 		"\n"
 		"<278>         <178>#chat {init} {port}\n"
 		"<278>         <178>#chat {init} {port}\n"
 		"<278>           #chat initialize launches your chat server. The port number is\n"
 		"<278>           #chat initialize launches your chat server. The port number is\n"
@@ -924,10 +920,10 @@ struct help_type help_table[] =
 		"<278>           used instead of the connection's name when sending someone a message\n"
 		"<278>           used instead of the connection's name when sending someone a message\n"
 		"<278>           The second column shows the connection's name. The third column\n"
 		"<278>           The second column shows the connection's name. The third column\n"
 		"<278>           shows flags set for the connection, (P)rivate, (I)gnore, (S)erve,\n"
 		"<278>           shows flags set for the connection, (P)rivate, (I)gnore, (S)erve,\n"
-		"<278>           (F)orward to user, and (f)orward from user. The next columns show\n"
-		"<278>           ip, port, and client name.\n"
+		"<278>           Forward(A)ll to user, (F)orward to user, and (f)orward from user.\n"
+		"<278>           The next columns show ip, port, and client name.\n"
 		"<278>         <178>#chat {zap}        {buddy}            Close a connection\n",
 		"<278>         <178>#chat {zap}        {buddy}            Close a connection\n",
-		
+
 		"port"
 		"port"
 	},
 	},
 	{
 	{
@@ -944,6 +940,8 @@ struct help_type help_table[] =
 		"<278>           Will delete all triggers associated with the given class.\n"
 		"<278>           Will delete all triggers associated with the given class.\n"
 		"<278>         <178>#class {<name>} {close}\n"
 		"<278>         <178>#class {<name>} {close}\n"
 		"<278>           Close the given class, opening the last open class, if any.\n"
 		"<278>           Close the given class, opening the last open class, if any.\n"
+		"<278>         <178>#class {<name>} {debug} {on|off}\n"
+		"<278>           Toggle debug mode for given class.\n"
 		"<278>         <178>#class {<name>} {kill}\n"
 		"<278>         <178>#class {<name>} {kill}\n"
 		"<278>           Will clear, close, and remove the class.\n"
 		"<278>           Will clear, close, and remove the class.\n"
 		"<278>         <178>#class {<name>} {list}\n"
 		"<278>         <178>#class {<name>} {list}\n"
@@ -968,7 +966,7 @@ struct help_type help_table[] =
 		"<178>Example<278>: #class rich kill;#class rich read poor.tin\n"
 		"<178>Example<278>: #class rich kill;#class rich read poor.tin\n"
 		"<278>         Deletes all triggers of 'rich' class if any. Read 'poor.tin' file,\n"
 		"<278>         Deletes all triggers of 'rich' class if any. Read 'poor.tin' file,\n"
 		"<278>         all triggers loaded will be assigned to the 'rich' class.\n",
 		"<278>         all triggers loaded will be assigned to the 'rich' class.\n",
-		
+
 		"config debug ignore info kill line message"
 		"config debug ignore info kill line message"
 	},
 	},
 	{
 	{
@@ -1078,7 +1076,7 @@ struct help_type help_table[] =
 		"<278>         reiterate the command.\n"
 		"<278>         reiterate the command.\n"
 		"\n"
 		"\n"
 		"<178>Example<278>: #loop 1 10 cnt {#if {$cnt % 2 == 0} {#continue} {say $cnt}}\n",
 		"<178>Example<278>: #loop 1 10 cnt {#if {$cnt % 2 == 0} {#continue} {say $cnt}}\n",
-		
+
 		"break foreach list loop parse repeat return while"
 		"break foreach list loop parse repeat return while"
 	},
 	},
 	{
 	{
@@ -1166,6 +1164,7 @@ struct help_type help_table[] =
 		"<278>         COMPLETE    makes tab completion work while editing\n"
 		"<278>         COMPLETE    makes tab completion work while editing\n"
 		"\n"
 		"\n"
 		"<278>         DICTIONARY  performs tab completion on the dictionary\n"
 		"<278>         DICTIONARY  performs tab completion on the dictionary\n"
+		"<278>         INPUT       performs tab completion on the input history\n"
 		"<278>         LIST        performs tab completion on the tab completion list\n"
 		"<278>         LIST        performs tab completion on the tab completion list\n"
 		"<278>         SCROLLBACK  performs tab completion on the scrollback buffer\n"
 		"<278>         SCROLLBACK  performs tab completion on the scrollback buffer\n"
 		"\n"
 		"\n"
@@ -1201,7 +1200,7 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<278>         You can launch tintin and attach the first daemonized instance using\n"
 		"<278>         You can launch tintin and attach the first daemonized instance using\n"
 		"<278>         tt++ -R. To attach a named instance use tt++ -R<name>.\n",
 		"<278>         tt++ -R. To attach a named instance use tt++ -R<name>.\n",
-		
+
 		"script system run"
 		"script system run"
 	},
 	},
 	{
 	{
@@ -1219,7 +1218,7 @@ struct help_type help_table[] =
 		"<278>         the log file, you must be logging in order for this to work.\n"
 		"<278>         the log file, you must be logging in order for this to work.\n"
 		"\n"
 		"\n"
 		"<278>         Not every list has debug support yet.\n",
 		"<278>         Not every list has debug support yet.\n",
-		
+
 		"class ignore info kill message"
 		"class ignore info kill message"
 	},
 	},
 	{
 	{
@@ -1230,7 +1229,7 @@ struct help_type help_table[] =
 		"<278>         The default command can only be used within the switch command. When\n"
 		"<278>         The default command can only be used within the switch command. When\n"
 		"<278>         the conditional argument of non of the case commands matches the switch\n"
 		"<278>         the conditional argument of non of the case commands matches the switch\n"
 		"<278>         command's conditional statement the default command is executed.\n",
 		"<278>         command's conditional statement the default command is executed.\n",
-		
+
 		"case default else elseif if switch regexp"
 		"case default else elseif if switch regexp"
 	},
 	},
 	{
 	{
@@ -1254,7 +1253,7 @@ struct help_type help_table[] =
 		"<278>         a name as the first argument, be aware this changes the syntax. If\n"
 		"<278>         a name as the first argument, be aware this changes the syntax. If\n"
 		"<278>         the name is a number keep in mind that delays with the same numeric\n"
 		"<278>         the name is a number keep in mind that delays with the same numeric\n"
 		"<278>         name will not be overwritten\n",
 		"<278>         name will not be overwritten\n",
-		
+
 		"event ticker"
 		"event ticker"
 	},
 	},
 
 
@@ -1335,7 +1334,7 @@ struct help_type help_table[] =
 		"<278>         [BOXED] <178>MAP\n"
 		"<278>         [BOXED] <178>MAP\n"
 		"<278>           will draw the map\n"
 		"<278>           will draw the map\n"
 		"<278>         <178>RAIN<278> {<VARIABLE>} {[SPAWN]} {[FADE]} {[LEGEND]}\n"
 		"<278>         <178>RAIN<278> {<VARIABLE>} {[SPAWN]} {[FADE]} {[LEGEND]}\n"
-		"<278>           will draw digital rain.\n"
+		"<278>           will draw digital rain SPAWN (0.01-100) FADE (1-100).\n"
 		"<278>         [JOINTED|TOP|LEFT|BOTTOM|RIGHT] <178>SIDE\n"
 		"<278>         [JOINTED|TOP|LEFT|BOTTOM|RIGHT] <178>SIDE\n"
 		"<278>           will draw one or more sides of a box.\n"
 		"<278>           will draw one or more sides of a box.\n"
 		"<278>         [GRID] <178>TABLE<278> {[LIST1]} {[LIST2]}\n"
 		"<278>         [GRID] <178>TABLE<278> {[LIST1]} {[LIST2]}\n"
@@ -1369,7 +1368,7 @@ struct help_type help_table[] =
 		"<178>Example<278>: #echo {The current date is %t.} {%Y-%m-%d %H:%M:%S}\n"
 		"<178>Example<278>: #echo {The current date is %t.} {%Y-%m-%d %H:%M:%S}\n"
 		"<278>         #echo {[%38s][%-38s]} {Hello World} {Hello World}\n"
 		"<278>         #echo {[%38s][%-38s]} {Hello World} {Hello World}\n"
 		"<278>         #echo {{this is %s on the top row} {1}} {printed}\n",
 		"<278>         #echo {{this is %s on the top row} {1}} {printed}\n",
-		
+
 		"buffer format grep showme"
 		"buffer format grep showme"
 	},
 	},
 	{
 	{
@@ -1403,7 +1402,7 @@ struct help_type help_table[] =
 		"<278>           Write the editor content to file.\n"
 		"<278>           Write the editor content to file.\n"
 		"\n"
 		"\n"
 		"<178>Example<278>: #edit create {bla.txt} {line 1} {line 2}\n",
 		"<178>Example<278>: #edit create {bla.txt} {line 1} {line 2}\n",
-		
+
 		"cursor macro"
 		"cursor macro"
 	},
 	},
 	{
 	{
@@ -1479,13 +1478,13 @@ struct help_type help_table[] =
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>arrow down               <268>││<178>next input line                             <268>│\n"
 		"<268>│<178>arrow down               <268>││<178>next input line                             <268>│\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
-		
+
 		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>│<178>ctrl arrow left          <268>││<178>cursor left word                            <268>│\n"
 		"<268>│<178>ctrl arrow left          <268>││<178>cursor left word                            <268>│\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>ctrl arrow right         <268>││<178>cursor right word                           <268>│\n"
 		"<268>│<178>ctrl arrow right         <268>││<178>cursor right word                           <268>│\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
-		
+
 		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>│<178>backspace                <268>││<178>backspace                                   <268>│\n"
 		"<268>│<178>backspace                <268>││<178>backspace                                   <268>│\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
@@ -1493,38 +1492,38 @@ struct help_type help_table[] =
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>ctrl backspace           <268>││<178>clear line                                  <268>│\n"
 		"<268>│<178>ctrl backspace           <268>││<178>clear line                                  <268>│\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
-		
+
 		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>│<178>delete                   <268>││<178>delete                                      <268>│\n"
 		"<268>│<178>delete                   <268>││<178>delete                                      <268>│\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>ctrl delete              <268>││<178>delete word right                           <268>│\n"
 		"<268>│<178>ctrl delete              <268>││<178>delete word right                           <268>│\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
-		
-		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"	
+
+		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>│<178>end                      <268>││<178>cursor end                                  <268>│\n"
 		"<268>│<178>end                      <268>││<178>cursor end                                  <268>│\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>ctrl end                 <268>││<178>scroll buffer end                           <268>│\n"
 		"<268>│<178>ctrl end                 <268>││<178>scroll buffer end                           <268>│\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 
 
-		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"	
+		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>│<178>enter                    <268>││<178>enter                                       <268>│\n"
 		"<268>│<178>enter                    <268>││<178>enter                                       <268>│\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>shift-enter              <268>││<178>soft enter                                  <268>│\n"
 		"<268>│<178>shift-enter              <268>││<178>soft enter                                  <268>│\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
-		
+
 		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>│<178>home                     <268>││<178>cursor home                                 <268>│\n"
 		"<268>│<178>home                     <268>││<178>cursor home                                 <268>│\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>ctrl home                <268>││<178>scroll buffer home                          <268>│\n"
 		"<268>│<178>ctrl home                <268>││<178>scroll buffer home                          <268>│\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
-		
-		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"	
+
+		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>│<178>page up                  <268>││<178>scroll buffer up                            <268>│\n"
 		"<268>│<178>page up                  <268>││<178>scroll buffer up                            <268>│\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>page down                <268>││<178>scroll buffer down                          <268>│\n"
 		"<268>│<178>page down                <268>││<178>scroll buffer down                          <268>│\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 		"<268>└─────────────────────────┘└────────────────────────────────────────────┘\n"
 
 
-		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"	
+		"<268>┌─────────────────────────┐┌────────────────────────────────────────────┐\n"
 		"<268>│<178>tab                      <268>││<178>complete word forward                       <268>│\n"
 		"<268>│<178>tab                      <268>││<178>complete word forward                       <268>│\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>├─────────────────────────┤├────────────────────────────────────────────┤\n"
 		"<268>│<178>shift-tab                <268>││<178>complete word backward                      <268>│\n"
 		"<268>│<178>shift-tab                <268>││<178>complete word backward                      <268>│\n"
@@ -1542,7 +1541,7 @@ struct help_type help_table[] =
 		"<278>         only called if the proceeding #IF or #ELSEIF is false.\n"
 		"<278>         only called if the proceeding #IF or #ELSEIF is false.\n"
 		"\n"
 		"\n"
 		"<178>Example<278>: #if {1d2 == 1} {smile};#else {grin}\n",
 		"<178>Example<278>: #if {1d2 == 1} {smile};#else {grin}\n",
-		
+
 		"case default elseif if switch regexp"
 		"case default elseif if switch regexp"
 	},
 	},
 	{
 	{
@@ -1555,7 +1554,7 @@ struct help_type help_table[] =
 		"<278>         #ELSEIF statements are false.\n"
 		"<278>         #ELSEIF statements are false.\n"
 		"\n"
 		"\n"
 		"<178>Example<278>: #if {1d3 == 1} {smirk};#elseif {1d2 == 1} {snicker}\n",
 		"<178>Example<278>: #if {1d3 == 1} {smirk};#elseif {1d2 == 1} {snicker}\n",
-		
+
 		"case default else if switch regexp"
 		"case default else if switch regexp"
 	},
 	},
 	{
 	{
@@ -1568,7 +1567,7 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<278>         The message is optional and is printed before tintin exits. When\n"
 		"<278>         The message is optional and is printed before tintin exits. When\n"
 		"<278>         using #end {\\} tintin will terminate silently.\n",
 		"<278>         using #end {\\} tintin will terminate silently.\n",
-		
+
 		"zap"
 		"zap"
 	},
 	},
 	{
 	{
@@ -1593,7 +1592,7 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<278>         Ending a line with \\ will stop tintin from appending a line feed.\n"
 		"<278>         Ending a line with \\ will stop tintin from appending a line feed.\n"
 		"<278>         To escape arguments in an alias or action use %%0 %%1 %%2 etc.\n",
 		"<278>         To escape arguments in an alias or action use %%0 %%1 %%2 etc.\n",
-		
+
 		"characters colors coordinates mathematics pcre"
 		"characters colors coordinates mathematics pcre"
 	},
 	},
 	{
 	{
@@ -1642,6 +1641,9 @@ struct help_type help_table[] =
 		"<278>         <178>EDIT STARTED, EDIT FINISHED\n"
 		"<278>         <178>EDIT STARTED, EDIT FINISHED\n"
 		"<278>           %0 name  %1 lines %2 size %3 data\n"
 		"<278>           %0 name  %1 lines %2 size %3 data\n"
 		"\n"
 		"\n"
+		"<278>         <178>EDIT RESUMED, EDIT SUSPENDED\n"
+		"<278>           %0 name\n"
+		"\n"
 		"<278>         <178>HISTORY UPDATE\n"
 		"<278>         <178>HISTORY UPDATE\n"
 		"<278>           %0 command\n"
 		"<278>           %0 command\n"
 		"\n"
 		"\n"
@@ -1716,12 +1718,13 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<278>         <128>PORT EVENTS\n"
 		"<278>         <128>PORT EVENTS\n"
 		"\n"
 		"\n"
-		"<278>         <178>CHAT MESSAGE<278>, <178>PORT MESSAGE\n"
-		"<278>           %0 raw text  %1 plain text\n"
+		"<278>         <178>CHAT MESSAGE           <278>%0 raw text  %1 plain text\n"
+		"<278>         <178>CHAT SNOOP REQUEST     <278>%0 name %1 ip %2 port\n"
 		"\n"
 		"\n"
 		"<278>         <178>PORT CONNECTION        <278>%0 name %1 ip %2 port\n"
 		"<278>         <178>PORT CONNECTION        <278>%0 name %1 ip %2 port\n"
 		"<278>         <178>PORT DISCONNECTION     <278>%0 name %1 ip %2 port\n"
 		"<278>         <178>PORT DISCONNECTION     <278>%0 name %1 ip %2 port\n"
 		"<278>         <178>PORT LOG MESSAGE       <278>%0 name %1 ip %2 port %3 data %4 plain data\n"
 		"<278>         <178>PORT LOG MESSAGE       <278>%0 name %1 ip %2 port %3 data %4 plain data\n"
+		"<278>         <178>PORT MESSAGE           <278>%0 raw text %1 plain text\n"
 		"<278>         <178>PORT RECEIVED MESSAGE  <278>%0 name %1 ip %2 port %3 data %4 plain data\n"
 		"<278>         <178>PORT RECEIVED MESSAGE  <278>%0 name %1 ip %2 port %3 data %4 plain data\n"
 		"<278>         <178>PORT RECEIVED DATA     <278>%0 name %1 ip %2 port %3 data %4 size\n"
 		"<278>         <178>PORT RECEIVED DATA     <278>%0 name %1 ip %2 port %3 data %4 size\n"
 		"\n"
 		"\n"
@@ -1771,6 +1774,7 @@ struct help_type help_table[] =
 		"<278>         <178>WRITE ERROR            <278>%0 filename %1 error message\n"
 		"<278>         <178>WRITE ERROR            <278>%0 filename %1 error message\n"
 		"<278>         <178>WRITE FILE             <278>%0 filename\n"
 		"<278>         <178>WRITE FILE             <278>%0 filename\n"
 		"\n"
 		"\n"
+		"<278>         <178>RECEIVED ERROR         <278>%0 message\n"
 		"<278>         <178>SYSTEM CRASH           <278>%0 message\n"
 		"<278>         <178>SYSTEM CRASH           <278>%0 message\n"
 		"<278>         <178>SYSTEM ERROR           <278>%0 name %1 system msg %2 error %3 error msg\n"
 		"<278>         <178>SYSTEM ERROR           <278>%0 name %1 system msg %2 error %3 error msg\n"
 		"<278>         <178>UNKNOWN COMMAND        <278>%0 raw text\n"
 		"<278>         <178>UNKNOWN COMMAND        <278>%0 raw text\n"
@@ -1814,7 +1818,7 @@ struct help_type help_table[] =
 		"<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",
-		
+
 		"button delay ticker"
 		"button delay ticker"
 	},
 	},
 	{
 	{
@@ -1828,7 +1832,7 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<178>Example<278>: #foreach {bob;tim;kim} {name} {tell $name Hello}\n"
 		"<178>Example<278>: #foreach {bob;tim;kim} {name} {tell $name Hello}\n"
 		"<178>Example<278>: #foreach {{bob}{tim}{kim}} {name} {tell $name Hello}\n",
 		"<178>Example<278>: #foreach {{bob}{tim}{kim}} {name} {tell $name Hello}\n",
-		
+
 		"break continue list loop parse repeat return while"
 		"break continue list loop parse repeat return while"
 	},
 	},
 	{
 	{
@@ -1876,7 +1880,7 @@ struct help_type help_table[] =
 		"<278>         #format {test} {%%}             a literal % character\n"
 		"<278>         #format {test} {%%}             a literal % character\n"
 		"\n"
 		"\n"
 		"<178>Comment<278>: See #help TIME for help on the %t argument.\n",
 		"<178>Comment<278>: See #help TIME for help on the %t argument.\n",
-		
+
 		"cat echo function local math replace script time variable"
 		"cat echo function local math replace script time variable"
 	},
 	},
 
 
@@ -1910,7 +1914,7 @@ struct help_type help_table[] =
 		"<278>         #show The current time is @gettime{}\n"
 		"<278>         #show The current time is @gettime{}\n"
 		"\n"
 		"\n"
 		"<178>Comment<278>: You can remove a function with the #unfunction command.\n",
 		"<178>Comment<278>: You can remove a function with the #unfunction command.\n",
-		
+
 		"format local math replace script variable"
 		"format local math replace script variable"
 	},
 	},
 	{
 	{
@@ -1925,7 +1929,7 @@ struct help_type help_table[] =
 		"<278>         There are a system messages that can be gagged using gag events.\n"
 		"<278>         There are a system messages that can be gagged using gag events.\n"
 		"\n"
 		"\n"
 		"<178>Comment<278>: You can remove a gag with the #ungag command.\n",
 		"<178>Comment<278>: You can remove a gag with the #ungag command.\n",
-		
+
 		"action highlight prompt substitute"
 		"action highlight prompt substitute"
 	},
 	},
 	{
 	{
@@ -1940,7 +1944,7 @@ struct help_type help_table[] =
 		"<268>      #<278>      Code by Peter Unold, Bill Reis, and Igor van den Hoven      <268>#\n"
 		"<268>      #<278>      Code by Peter Unold, Bill Reis, and Igor van den Hoven      <268>#\n"
 		"<268>      #<278>                                                                  <268>#\n"
 		"<268>      #<278>                                                                  <268>#\n"
 		"<268>      #<268>##################################################################<268>#<288>\n",
 		"<268>      #<268>##################################################################<268>#<288>\n",
-		
+
 		""
 		""
 	},
 	},
 	{
 	{
@@ -1959,7 +1963,7 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<178>Example<278>: #grep Bubba tells you\n"
 		"<178>Example<278>: #grep Bubba tells you\n"
 		"<278>         This will show all occasions where bubba tells you something.\n",
 		"<278>         This will show all occasions where bubba tells you something.\n",
-		
+
 		"buffer echo showme"
 		"buffer echo showme"
 	},
 	},
 	{
 	{
@@ -1970,7 +1974,7 @@ struct help_type help_table[] =
 		"<278>         Without an argument #help will list all available help subjects.\n"
 		"<278>         Without an argument #help will list all available help subjects.\n"
 		"\n"
 		"\n"
 		"<278>         Using #help %* will display all help entries.\n",
 		"<278>         Using #help %* will display all help entries.\n",
-		
+
 		"commands debug ignore info message statements"
 		"commands debug ignore info message statements"
 	},
 	},
 	{
 	{
@@ -2039,7 +2043,7 @@ struct help_type help_table[] =
 		"<178>Comment<278>: This command only works with ANSI/VT100 terminals or emulators.\n"
 		"<178>Comment<278>: This command only works with ANSI/VT100 terminals or emulators.\n"
 		"\n"
 		"\n"
 		"<178>Comment<278>: You can remove a highlight with the #unhighlight command.\n",
 		"<178>Comment<278>: You can remove a highlight with the #unhighlight command.\n",
-		
+
 		"action gag prompt substitute"
 		"action gag prompt substitute"
 	},
 	},
 	{
 	{
@@ -2074,7 +2078,7 @@ struct help_type help_table[] =
 		"<278>         the history list by default. You can bind these with a macro yourself\n"
 		"<278>         the history list by default. You can bind these with a macro yourself\n"
 		"<278>         using #cursor {history next} and #cursor {history prev}. Many #cursor\n"
 		"<278>         using #cursor {history next} and #cursor {history prev}. Many #cursor\n"
 		"<278>         commands only work properly when bound with a macro.\n",
 		"<278>         commands only work properly when bound with a macro.\n",
-		
+
 		"alias cursor keypad macro speedwalk tab"
 		"alias cursor keypad macro speedwalk tab"
 	},
 	},
 	{
 	{
@@ -2101,7 +2105,7 @@ struct help_type help_table[] =
 		"<178>Example<278>: #alias {k} {#if {\"%0\" == \"\"} {kill $target};#else {kill %0}}\n"
 		"<178>Example<278>: #alias {k} {#if {\"%0\" == \"\"} {kill $target};#else {kill %0}}\n"
 		"\n"
 		"\n"
 		"<178>Example<278>: #if {\"%0\" == \"{bli|bla}\"} {#showme %0 is either bli or bla.}\n",
 		"<178>Example<278>: #if {\"%0\" == \"{bli|bla}\"} {#showme %0 is either bli or bla.}\n",
-		
+
 		"case default else elseif math switch regexp"
 		"case default else elseif math switch regexp"
 	},
 	},
 	{
 	{
@@ -2984,10 +2988,10 @@ struct help_type help_table[] =
 		"<278>                 }\n"
 		"<278>                 }\n"
 		"<278>             }\n"
 		"<278>             }\n"
 		"        }\n",
 		"        }\n",
-		
+
 		"break continue foreach loop parse repeat return while"
 		"break continue foreach loop parse repeat return while"
 	},
 	},
-	
+
 	{
 	{
 		"LOCAL",
 		"LOCAL",
 		TOKEN_TYPE_COMMAND,
 		TOKEN_TYPE_COMMAND,
@@ -3760,8 +3764,8 @@ struct help_type help_table[] =
 		"<278>         In order to copy/paste, most terminals require that you press the shift\n"
 		"<278>         In order to copy/paste, most terminals require that you press the shift\n"
 		"<278>         key during selection.\n"
 		"<278>         key during selection.\n"
 		"\n",
 		"\n",
-		
-		"button draw event MSLP"
+
+		"button draw event mslp"
 	},
 	},
 
 
 	{
 	{
@@ -3929,7 +3933,7 @@ struct help_type help_table[] =
 		"<278>         #pathdir {dw} {ue} {40}\n"
 		"<278>         #pathdir {dw} {ue} {40}\n"
 		"\n"
 		"\n"
 		"<178>Comment<278>: You can remove a pathdir with the #unpathdir command.\n",
 		"<178>Comment<278>: You can remove a pathdir with the #unpathdir command.\n",
-		
+
 		"map path"
 		"map path"
 	},
 	},
 	{
 	{
@@ -3972,7 +3976,7 @@ struct help_type help_table[] =
 		"<278>         is used.\n"
 		"<278>         is used.\n"
 		"\n"
 		"\n"
 		"<178>TinTin++ <178>Description                                      POSIX\n"
 		"<178>TinTin++ <178>Description                                      POSIX\n"
-		"<178>      %a <278>Match zero or more characters including newlines ([^\\0]*?)\n"       
+		"<178>      %a <278>Match zero or more characters including newlines ([^\\0]*?)\n"
 		"<178>      %A <278>Match zero or more newlines                      ([\\n]*?)\n"
 		"<178>      %A <278>Match zero or more newlines                      ([\\n]*?)\n"
 		"<178>      %c <278>Match zero or more ansi color codes              ((?:\\e\\[[0-9;]*m)*?)\n"
 		"<178>      %c <278>Match zero or more ansi color codes              ((?:\\e\\[[0-9;]*m)*?)\n"
 		"<178>      %d <278>Match zero or more digits                        ([0-9]*?)\n"
 		"<178>      %d <278>Match zero or more digits                        ([0-9]*?)\n"
@@ -4245,12 +4249,11 @@ struct help_type help_table[] =
 		TOKEN_TYPE_COMMAND,
 		TOKEN_TYPE_COMMAND,
 		"<178>Command<278>: #read <178>{<278>filename<178>}\n"
 		"<178>Command<278>: #read <178>{<278>filename<178>}\n"
 		"\n"
 		"\n"
-		"<278>         Reads a commands file into memory.  The coms file is merged in with\n"
-		"<278>         the currently loaded commands.  Duplicate commands are overwritten.\n"
+		"<278>         Reads a commands file into memory.  The commands are merged with the\n"
+		"<278>         currently loaded commands.  Duplicate commands are overwritten.\n"
 		"\n"
 		"\n"
-		"<278>         If you uses braces, { and } you can use several lines for 1 commands.\n"
-		"<278>         This however means you must always match every { with a } for the read\n"
-		"<278>         command to work.\n"
+		"<278>         If you uses braces you can use several lines for each command.  You\n"
+		"<278>         must match every { with a } for the read command to work.\n"
 		"\n"
 		"\n"
 		"<278>         You can comment out triggers using /* text */\n"
 		"<278>         You can comment out triggers using /* text */\n"
 		,
 		,
@@ -4331,13 +4334,14 @@ struct help_type help_table[] =
 	{
 	{
 		"REPEAT",
 		"REPEAT",
 		TOKEN_TYPE_STRING,
 		TOKEN_TYPE_STRING,
-		"<178>Command<278>: #<178>[<078>number<178>] {<278>commands<178>}\n"
+		"<178>Command<278>: #<178>[<078>number<178>] {<278>commands<178>} {<278>..<178>}\n"
 		"\n"
 		"\n"
 		"<278>        Sometimes you want to repeat the same command multiple times. This is\n"
 		"<278>        Sometimes you want to repeat the same command multiple times. This is\n"
 		"<278>        the easiest way to accomplish that.\n"
 		"<278>        the easiest way to accomplish that.\n"
 		"\n"
 		"\n"
-		"<178>Example<278>: #10 {buy bread}\n",
-		
+		"<178>Example<278>: #10 {buy bread}\n"
+		"<178>Example<278>: #2 {buy bread} {buy apple}\n",
+
 		"mathematics statements"
 		"mathematics statements"
 	},
 	},
 	{
 	{
@@ -4413,8 +4417,12 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<178>         #scan {dir} <filename> <variable>\n"
 		"<178>         #scan {dir} <filename> <variable>\n"
 		"\n"
 		"\n"
-		"<278>          The scan dir command will read the given filename or directory and\n"
-		"<278>          store any gathered information into the provided variable.\n"
+		"<278>           The scan dir command will read the given filename or directory and\n"
+		"<278>           store any gathered information into the provided variable.\n"
+		"\n"
+		"<178>         #scan {json} <filename> <variable>\n"
+		"<278>           The scan json command will read the given filename and store the data\n"
+		"<278>           in the provided tintin variable.\n"
 		"\n"
 		"\n"
 		"<278>         <178>#scan {tsv} <filename>\n"
 		"<278>         <178>#scan {tsv} <filename>\n"
 		"\n"
 		"\n"
@@ -4426,9 +4434,9 @@ struct help_type help_table[] =
 		"<278>         <178>#scan {file} <filename> {commands}\n"
 		"<278>         <178>#scan {file} <filename> {commands}\n"
 		"\n"
 		"\n"
 		"<278>           The scan file command reads the given files and executes the\n"
 		"<278>           The scan file command reads the given files and executes the\n"
-		"<278>            commands argument. &0 contains the raw content of the file and\n"
-		"<278>            &1 contains the plain content. &2 contains the raw byte size of the\n"
-		"<278>            file and &3 the plain byte size. &5 contains the line count.\n"
+		"<278>           commands argument. &0 contains the raw content of the file and\n"
+		"<278>           &1 contains the plain content. &2 contains the raw byte size of the\n"
+		"<278>           file and &3 the plain byte size. &5 contains the line count.\n"
 		"\n"
 		"\n"
 		"<278>         <178>#scan {txt} <filename>\n"
 		"<278>         <178>#scan {txt} <filename>\n"
 		"\n"
 		"\n"
@@ -5208,7 +5216,7 @@ struct help_type help_table[] =
 		"<278>         To see the internal index of a variable use &<variable name>. To see\n"
 		"<278>         To see the internal index of a variable use &<variable name>. To see\n"
 		"<278>         the size of a table you would use: &targets[] or &targets[%*]. A non\n"
 		"<278>         the size of a table you would use: &targets[] or &targets[%*]. A non\n"
 		"<278>         existent nested variable will report itself as 0.\n"
 		"<278>         existent nested variable will report itself as 0.\n"
-		"\n" 
+		"\n"
 		"<178>Example<278>: #show {Number of targets starting with A: &targets[A%*]\n"
 		"<178>Example<278>: #show {Number of targets starting with A: &targets[A%*]\n"
 		"\n"
 		"\n"
 		"<278>         In some scripts you need to know the name of a nested variable. This\n"
 		"<278>         In some scripts you need to know the name of a nested variable. This\n"

+ 3 - 3
src/history.c

@@ -113,14 +113,14 @@ struct session *repeat_history(struct session *ses, char *line)
 
 
 			gtd->level->repeat++;
 			gtd->level->repeat++;
 
 
-			ses = script_driver(ses, LIST_COMMAND, root->list[root->used - 1]->arg1);
+			ses = script_driver(ses, LIST_COMMAND, NULL, root->list[root->used - 1]->arg1);
 
 
 			gtd->level->repeat--;
 			gtd->level->repeat--;
 
 
 			return ses;
 			return ses;
 		}
 		}
 	}
 	}
-	tintin_printf2(ses, "#REPEAT: NO MATCH FOUND FOR '%s'", line);	
+	tintin_printf2(ses, "#REPEAT: NO MATCH FOUND FOR '%s'", line);
 
 
 	return ses;
 	return ses;
 }
 }
@@ -258,7 +258,7 @@ DO_HISTORY(history_read)
 
 
 	fclose(file);
 	fclose(file);
 
 
-	if (ses->list[LIST_HISTORY]->used > gtd->history_size) 
+	if (ses->list[LIST_HISTORY]->used > gtd->history_size)
 	{
 	{
 		command(gts, do_configure, "{HISTORY SIZE} {%d}", UMIN(ses->list[LIST_HISTORY]->used, 9999));
 		command(gts, do_configure, "{HISTORY SIZE} {%d}", UMIN(ses->list[LIST_HISTORY]->used, 9999));
 	}
 	}

+ 14 - 20
src/input.c

@@ -174,7 +174,7 @@ void process_input(void)
 	}
 	}
 	else
 	else
 	{
 	{
-		gtd->ses = script_driver(gtd->ses, LIST_COMMAND, gtd->ses->input->buf);
+		gtd->ses = script_driver(gtd->ses, LIST_COMMAND, NULL, gtd->ses->input->buf);
 	}
 	}
 
 
 	if (HAS_BIT(input_ses->telopts, TELOPT_FLAG_ECHO))
 	if (HAS_BIT(input_ses->telopts, TELOPT_FLAG_ECHO))
@@ -311,7 +311,7 @@ void read_line(char *input, int len)
 					cursor_delete(gtd->ses, "");
 					cursor_delete(gtd->ses, "");
 				}
 				}
 
 
-				
+
 				str_ins_printf(&gtd->ses->input->buf, gtd->ses->input->raw_pos, "%.*s", size, gtd->macro_buf);
 				str_ins_printf(&gtd->ses->input->buf, gtd->ses->input->raw_pos, "%.*s", size, gtd->macro_buf);
 
 
 				gtd->ses->input->str_pos += width;
 				gtd->ses->input->str_pos += width;
@@ -337,10 +337,8 @@ void read_line(char *input, int len)
 
 
 				kill_list(gtd->ses->list[LIST_COMMAND]);
 				kill_list(gtd->ses->list[LIST_COMMAND]);
 
 
-				if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH))
-				{
-					cursor_history_find(gtd->ses, "");
-				}
+				cursor_history_find(gtd->ses, "");
+
 				break;
 				break;
 		}
 		}
 	}
 	}
@@ -459,14 +457,14 @@ int check_key(char *input, int len)
 				{
 				{
 					strcpy(buf, node->arg2);
 					strcpy(buf, node->arg2);
 
 
-					show_debug(gtd->ses, LIST_MACRO, COLOR_DEBUG "#DEBUG MACRO " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+					show_debug(gtd->ses, LIST_MACRO, node, COLOR_DEBUG "#DEBUG MACRO " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
 
 
 					if (node->shots && --node->shots == 0)
 					if (node->shots && --node->shots == 0)
 					{
 					{
 						delete_node_list(gtd->ses, LIST_MACRO, node);
 						delete_node_list(gtd->ses, LIST_MACRO, node);
 					}
 					}
 
 
-					script_driver(gtd->ses, LIST_MACRO, buf);
+					script_driver(gtd->ses, LIST_MACRO, node, buf);
 
 
 					if (HAS_BIT(gtd->flags, TINTIN_FLAG_PRESERVEMACRO))
 					if (HAS_BIT(gtd->flags, TINTIN_FLAG_PRESERVEMACRO))
 					{
 					{
@@ -528,11 +526,11 @@ int check_key(char *input, int len)
 					gtd->macro_buf[0] = 0;
 					gtd->macro_buf[0] = 0;
 
 
 					gtd->screen->focus = 1;
 					gtd->screen->focus = 1;
-					
+
 					check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 1, "SCREEN FOCUS", ntos(gtd->screen->focus));
 					check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 1, "SCREEN FOCUS", ntos(gtd->screen->focus));
 
 
 					msdp_update_all("SCREEN_FOCUS", "%d", gtd->screen->focus);
 					msdp_update_all("SCREEN_FOCUS", "%d", gtd->screen->focus);
-					
+
 					pop_call();
 					pop_call();
 					return TRUE;
 					return TRUE;
 				}
 				}
@@ -542,11 +540,11 @@ int check_key(char *input, int len)
 					gtd->macro_buf[0] = 0;
 					gtd->macro_buf[0] = 0;
 
 
 					gtd->screen->focus = 0;
 					gtd->screen->focus = 0;
-					
+
 					check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 1, "SCREEN FOCUS", ntos(gtd->screen->focus));
 					check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 1, "SCREEN FOCUS", ntos(gtd->screen->focus));
-					
+
 					msdp_update_all("SCREEN_FOCUS", "%d", gtd->screen->focus);
 					msdp_update_all("SCREEN_FOCUS", "%d", gtd->screen->focus);
-					 
+
 					pop_call();
 					pop_call();
 					return TRUE;
 					return TRUE;
 				}
 				}
@@ -700,8 +698,8 @@ int check_key(char *input, int len)
 									}
 									}
 									pop_call();
 									pop_call();
 									return FALSE;
 									return FALSE;
-										
-									
+
+
 								default:
 								default:
 									pop_call();
 									pop_call();
 									return FALSE;
 									return FALSE;
@@ -1078,14 +1076,10 @@ void modified_input(void)
 {
 {
 	kill_list(gtd->ses->list[LIST_COMMAND]);
 	kill_list(gtd->ses->list[LIST_COMMAND]);
 
 
-	if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH))
-	{
-		cursor_history_find(gtd->ses, "");
-	}
+	cursor_history_find(gtd->ses, "");
 
 
 	if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYBROWSE))
 	if (HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYBROWSE))
 	{
 	{
 		DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYBROWSE);
 		DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYBROWSE);
 	}
 	}
-
 }
 }

+ 24 - 25
src/line.c

@@ -113,7 +113,7 @@ DO_LINE(line_background)
 
 
 	gtd->level->background++;
 	gtd->level->background++;
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	gtd->level->background--;
 	gtd->level->background--;
 
 
@@ -135,7 +135,7 @@ DO_LINE(line_benchmark)
 
 
 	start = utime();
 	start = utime();
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	end = utime();
 	end = utime();
 
 
@@ -158,7 +158,7 @@ DO_LINE(line_capture)
 		ses->line_capturefile  = strdup(arg1);
 		ses->line_capturefile  = strdup(arg1);
 		ses->line_captureindex = 1;
 		ses->line_captureindex = 1;
 
 
-		ses = script_driver(ses, LIST_COMMAND, arg2);
+		ses = script_driver(ses, LIST_COMMAND, NULL, arg2);
 
 
 		if (ses->line_capturefile)
 		if (ses->line_capturefile)
 		{
 		{
@@ -188,7 +188,7 @@ DO_LINE(line_convert)
 
 
 	gtd->level->convert++;
 	gtd->level->convert++;
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	gtd->level->convert--;
 	gtd->level->convert--;
 
 
@@ -208,7 +208,7 @@ DO_LINE(line_debug)
 
 
 	gtd->level->debug++;
 	gtd->level->debug++;
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	gtd->level->debug--;
 	gtd->level->debug--;
 
 
@@ -239,7 +239,7 @@ DO_LINE(line_gag)
 	{
 	{
 		ses->gagline = 0;
 		ses->gagline = 0;
 	}
 	}
-	show_debug(ses, LIST_GAG, COLOR_DEBUG "#DEBUG LINE GAG " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} " COLOR_COMMAND "[" COLOR_STRING "%d" COLOR_COMMAND "]", arg1, ses->gagline);
+	show_debug(ses, LIST_GAG, NULL, COLOR_DEBUG "#DEBUG LINE GAG " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} " COLOR_COMMAND "[" COLOR_STRING "%d" COLOR_COMMAND "]", arg1, ses->gagline);
 
 
 	return ses;
 	return ses;
 }
 }
@@ -251,13 +251,13 @@ DO_LINE(line_ignore)
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {IGNORE} <COMMAND>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {IGNORE} <COMMAND>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
 	gtd->level->ignore++;
 	gtd->level->ignore++;
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	gtd->level->ignore--;
 	gtd->level->ignore--;
 
 
@@ -279,7 +279,7 @@ DO_LINE(line_local)
 
 
 	SET_BIT(gtd->flags, TINTIN_FLAG_LOCAL);
 	SET_BIT(gtd->flags, TINTIN_FLAG_LOCAL);
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	gtd->level->local--;
 	gtd->level->local--;
 
 
@@ -474,7 +474,7 @@ DO_LINE(line_logmode)
 
 
 	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
 	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
 
 
-	active_ses = script_driver(ses, LIST_COMMAND, arg1);
+	active_ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	ses->log->mode = old_mode;
 	ses->log->mode = old_mode;
 
 
@@ -494,7 +494,7 @@ DO_LINE(line_msdp)
 
 
 	tintin2msdp(arg1, arg2);
 	tintin2msdp(arg1, arg2);
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg2);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg2);
 
 
 	return ses;
 	return ses;
 }
 }
@@ -538,11 +538,11 @@ DO_LINE(line_json)
 
 
 	substitute(ses, arg2, str_sub, SUB_CMD);
 	substitute(ses, arg2, str_sub, SUB_CMD);
 
 
-	ses = script_driver(ses, LIST_COMMAND, str_sub);
+	ses = script_driver(ses, LIST_COMMAND, NULL, str_sub);
 
 
 	return ses;
 	return ses;
 }
 }
-	
+
 DO_LINE(line_multishot)
 DO_LINE(line_multishot)
 {
 {
 	unsigned int shots;
 	unsigned int shots;
@@ -555,7 +555,7 @@ DO_LINE(line_multishot)
 	if (!is_math(ses, arg1) || *arg2 == 0)
 	if (!is_math(ses, arg1) || *arg2 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {MULTISHOT} <NUMBER> <COMMAND>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {MULTISHOT} <NUMBER> <COMMAND>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -563,7 +563,7 @@ DO_LINE(line_multishot)
 
 
 	gtd->level->mshot = shots;
 	gtd->level->mshot = shots;
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg2);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg2);
 
 
 	gtd->level->mshot = 1;
 	gtd->level->mshot = 1;
 
 
@@ -579,7 +579,7 @@ DO_LINE(line_oneshot)
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {ONESHOT} <COMMAND>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {ONESHOT} <COMMAND>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -587,7 +587,7 @@ DO_LINE(line_oneshot)
 
 
 	gtd->level->mshot = 1;
 	gtd->level->mshot = 1;
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	gtd->level->shots--;
 	gtd->level->shots--;
 
 
@@ -601,13 +601,13 @@ DO_LINE(line_quiet)
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {QUIET} <COMMAND>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {QUIET} <COMMAND>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
 	gtd->level->quiet++;
 	gtd->level->quiet++;
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	gtd->level->quiet--;
 	gtd->level->quiet--;
 
 
@@ -627,7 +627,7 @@ DO_LINE(line_strip)
 
 
 	strip_vt102_codes(arg1, arg2);
 	strip_vt102_codes(arg1, arg2);
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg2);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg2);
 
 
 	return ses;
 	return ses;
 }
 }
@@ -670,7 +670,7 @@ DO_LINE(line_substitute)
 
 
 	substitute(ses, arg2, arg3, flags);
 	substitute(ses, arg2, arg3, flags);
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg3);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg3);
 
 
 	return ses;
 	return ses;
 }
 }
@@ -682,7 +682,7 @@ DO_LINE(line_verbatim)
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {VERBATIM} <COMMAND>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {VERBATIM} <COMMAND>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -702,17 +702,16 @@ DO_LINE(line_verbose)
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {VERBOSE} <COMMAND>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {VERBOSE} <COMMAND>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
 	gtd->level->verbose++;
 	gtd->level->verbose++;
 
 
-	ses = script_driver(ses, LIST_COMMAND, arg1);
+	ses = script_driver(ses, LIST_COMMAND, NULL, arg1);
 
 
 	gtd->level->verbose--;
 	gtd->level->verbose--;
 
 
 	return ses;
 	return ses;
 }
 }
 
 
-	

+ 30 - 10
src/main.c

@@ -250,7 +250,7 @@ int main(int argc, char **argv)
 
 
 	if (argc > 1)
 	if (argc > 1)
 	{
 	{
-		while ((c = getopt(argc, argv, "a: e: g G h H M:: r: R:: s t: T v V")) != EOF)
+		while ((c = getopt(argc, argv, "a: e: g G h l H M:: r: R:: s t: T v V")) != EOF)
 		{
 		{
 			switch (c)
 			switch (c)
 			{
 			{
@@ -263,7 +263,7 @@ int main(int argc, char **argv)
 					printf("  -G  Don't show the greeting screen.\n");
 					printf("  -G  Don't show the greeting screen.\n");
 					printf("  -h  This help section.\n");
 					printf("  -h  This help section.\n");
 					printf("  -H  Nohup compatible mode.\n");
 					printf("  -H  Nohup compatible mode.\n");
-					printf("  -M  Matrix Digital Rain.\n");
+					printf("  -l  <rain|regex>\n");
 					printf("  -r  Read given file.\n");
 					printf("  -r  Read given file.\n");
 					printf("  -R  Reattach to daemonized process.\n");
 					printf("  -R  Reattach to daemonized process.\n");
 					printf("  -s  Enable screen reader mode.\n");
 					printf("  -s  Enable screen reader mode.\n");
@@ -302,6 +302,13 @@ int main(int argc, char **argv)
 
 
 	init_tintin(greeting);
 	init_tintin(greeting);
 
 
+	gtd->system->exec = strdup(argv[0]);
+
+	if (!strcmp(gtd->system->exec, "././tt++"))
+	{
+		RESTRING(gtd->system->os, "WINTIN++");
+	}
+
 	RESTRING(gtd->vars[1], argv[0]);
 	RESTRING(gtd->vars[1], argv[0]);
 
 
 	if (argc > 1)
 	if (argc > 1)
@@ -310,7 +317,7 @@ int main(int argc, char **argv)
 
 
 		RESTRING(gtd->vars[2], argv[1]);
 		RESTRING(gtd->vars[2], argv[1]);
 
 
-		while ((c = getopt(argc, argv, "a: e: g G h H M:: r: R:: s t: T v")) != EOF)
+		while ((c = getopt(argc, argv, "a: e: g G h H l: M:: r: R:: s t: T v")) != EOF)
 		{
 		{
 			switch (c)
 			switch (c)
 			{
 			{
@@ -321,19 +328,34 @@ int main(int argc, char **argv)
 
 
 				case 'e':
 				case 'e':
 					gtd->level->input++;
 					gtd->level->input++;
-					gtd->ses = script_driver(gtd->ses, LIST_COMMAND, optarg);
+					gtd->ses = script_driver(gtd->ses, LIST_COMMAND, NULL, optarg);
 					gtd->level->input--;
 					gtd->level->input--;
 					break;
 					break;
 
 
 				case 'g':
 				case 'g':
-					gtd->ses = command(gtd->ses, do_banner, "gui");
+					gtd->ses = command(gtd->ses, do_test, "gui");
 					break;
 					break;
 
 
 				case 'G':
 				case 'G':
 					break;
 					break;
 
 
+				case 'l':
+					if (!strcasecmp(optarg, "rain"))
+					{
+						command(gts, do_test, "rain %s", optarg ? optarg : "");
+					}
+					else if (!strcasecmp(optarg, "regex"))
+					{
+						gtd->ses = command(gtd->ses, do_test, "regex");
+					}
+					else
+					{
+						tintin_printf2(NULL, "Option arguments are: -l <rain|regex>.");
+						exit(1);
+					}
+					break;
+
 				case 'M':
 				case 'M':
-					command(gts, do_test, "rain %s", optarg ? optarg : "");
 					break;
 					break;
 
 
 				case 'r':
 				case 'r':
@@ -380,8 +402,6 @@ int main(int argc, char **argv)
 		command(gts, do_screen, "SET BOTH TinTin++");
 		command(gts, do_screen, "SET BOTH TinTin++");
 	}
 	}
 
 
-	gtd->system->exec = strdup(argv[0]);
-
 	if (argc > 2)
 	if (argc > 2)
 	{
 	{
 		RESTRING(gtd->vars[3], argv[2]);
 		RESTRING(gtd->vars[3], argv[2]);
@@ -469,7 +489,7 @@ void init_tintin(int greeting)
 	gtd->system         = (struct system_data *) calloc(1, sizeof(struct system_data));
 	gtd->system         = (struct system_data *) calloc(1, sizeof(struct system_data));
 
 
 	gtd->system->os     = strdup(getenv("OS")   ? getenv("OS")   : "UNKNOWN");
 	gtd->system->os     = strdup(getenv("OS")   ? getenv("OS")   : "UNKNOWN");
-	gtd->system->home   = strdup(getenv("HOME") ? getenv("HOME") : "~/");
+	gtd->system->home   = strdup(getenv("HOME") ? getenv("HOME") : ".");
 	gtd->system->lang   = strdup(getenv("LANG") ? getenv("LANG") : "UNKNOWN");
 	gtd->system->lang   = strdup(getenv("LANG") ? getenv("LANG") : "UNKNOWN");
 	gtd->system->term   = strdup(getenv("TERM") ? getenv("TERM") : "UNKNOWN");
 	gtd->system->term   = strdup(getenv("TERM") ? getenv("TERM") : "UNKNOWN");
 
 
@@ -733,7 +753,7 @@ void syserr_printf(struct session *ses, char *fmt, ...)
 	char buf[BUFFER_SIZE], name[BUFFER_SIZE], *errstr;
 	char buf[BUFFER_SIZE], name[BUFFER_SIZE], *errstr;
 
 
 	errstr = strerror(errno);
 	errstr = strerror(errno);
-	
+
 	va_list args;
 	va_list args;
 
 
 	va_start(args, fmt);
 	va_start(args, fmt);

+ 33 - 24
src/mapper.c

@@ -397,11 +397,11 @@ void delete_room_data(struct room_data *room)
 	free(room->desc);
 	free(room->desc);
 	free(room->note);
 	free(room->note);
 	free(room->terrain);
 	free(room->terrain);
-	free(room->data); 
+	free(room->data);
 
 
 	return;
 	return;
 }
 }
-	
+
 void delete_room(struct session *ses, int room, int exits)
 void delete_room(struct session *ses, int room, int exits)
 {
 {
 	struct exit_data *exit, *exit_next;
 	struct exit_data *exit, *exit_next;
@@ -957,7 +957,7 @@ int get_terrain_density(struct room_data *room, int width)
 							case TERRAIN_FLAG_WIDE:
 							case TERRAIN_FLAG_WIDE:
 								flag = TERRAIN_FLAG_AMPLE;
 								flag = TERRAIN_FLAG_AMPLE;
 								break;
 								break;
-								
+
 							case TERRAIN_FLAG_WIDE|TERRAIN_FLAG_VAST:
 							case TERRAIN_FLAG_WIDE|TERRAIN_FLAG_VAST:
 								flag = TERRAIN_FLAG_SPARSE;
 								flag = TERRAIN_FLAG_SPARSE;
 								break;
 								break;
@@ -1885,7 +1885,7 @@ int follow_map(struct session *ses, char *argument)
 			else
 			else
 			{
 			{
 				ses->map->nofollow++;
 				ses->map->nofollow++;
-				script_driver(ses, LIST_COMMAND, exit->cmd);
+				script_driver(ses, LIST_COMMAND, NULL, exit->cmd);
 				ses->map->nofollow--;
 				ses->map->nofollow--;
 			}
 			}
 		}
 		}
@@ -1965,7 +1965,7 @@ int follow_map(struct session *ses, char *argument)
 		{
 		{
 			ses->map->nofollow++;
 			ses->map->nofollow++;
 
 
-			script_driver(ses, LIST_COMMAND, argument);
+			script_driver(ses, LIST_COMMAND, NULL, argument);
 
 
 			ses->map->nofollow--;
 			ses->map->nofollow--;
 		}
 		}
@@ -3865,7 +3865,7 @@ void search_keywords(struct session *ses, char *arg, char *out, char *var)
 		}
 		}
 	}
 	}
 
 
-	if (buf[MAP_SEARCH_DESC])
+	if (*buf[MAP_SEARCH_DESC])
 	{
 	{
 		str = buf[MAP_SEARCH_DESC];
 		str = buf[MAP_SEARCH_DESC];
 
 
@@ -4394,7 +4394,7 @@ int find_location(struct session *ses, char *arg)
 	struct listnode *dir;
 	struct listnode *dir;
 	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE];
 	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE];
 	int x, y, z;
 	int x, y, z;
-	
+
 	push_call("find_location(%p,%p)",ses,arg);
 	push_call("find_location(%p,%p)",ses,arg);
 
 
 	if (find_exit(ses, ses->map->in_room, arg))
 	if (find_exit(ses, ses->map->in_room, arg))
@@ -4618,7 +4618,7 @@ int check_global(struct session *ses, int room)
 	{
 	{
 		return FALSE;
 		return FALSE;
 	}
 	}
-	
+
 	if (ses->map->room_list[ses->map->global_vnum] == NULL)
 	if (ses->map->room_list[ses->map->global_vnum] == NULL)
 	{
 	{
 		return FALSE;
 		return FALSE;
@@ -5336,7 +5336,7 @@ void map_mouse_handler(struct session *ses, char *arg1, char *arg2, int row, int
 			check_all_events(ses, EVENT_FLAG_MOUSE, 0, 6, "MAP MOUSE LOCATION", ntos(row), ntos(col), exit, ntos(rev_row), ntos(rev_col), ntos(vnum), exit);
 			check_all_events(ses, EVENT_FLAG_MOUSE, 0, 6, "MAP MOUSE LOCATION", ntos(row), ntos(col), exit, ntos(rev_row), ntos(rev_col), ntos(vnum), exit);
 		}
 		}
 	}
 	}
-		
+
 	pop_call();
 	pop_call();
 	return;
 	return;
 }
 }
@@ -5401,7 +5401,7 @@ DO_MAP(map_at)
 
 
 	ses->map->in_room = new_room;
 	ses->map->in_room = new_room;
 
 
-	script_driver(ses, LIST_COMMAND, arg2);
+	script_driver(ses, LIST_COMMAND, NULL, arg2);
 
 
 	if (ses->map)
 	if (ses->map)
 	{
 	{
@@ -5580,7 +5580,7 @@ DO_MAP(map_delete)
 	if (room == ses->map->in_room || room == ses->map->at_room)
 	if (room == ses->map->in_room || room == ses->map->at_room)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#MAP DELETE: YOU MUST FIRST LEAVE THE ROOM YOU'RE TRYING TO DELETE.");
 		show_error(ses, LIST_COMMAND, "#MAP DELETE: YOU MUST FIRST LEAVE THE ROOM YOU'RE TRYING TO DELETE.");
-		
+
 		return;
 		return;
 	}
 	}
 
 
@@ -5766,7 +5766,7 @@ DO_MAP(map_dig)
 		if (room == ses->map->size)
 		if (room == ses->map->size)
 		{
 		{
 			show_error(ses, LIST_COMMAND, "#MAP DIG: MAXIMUM NUMBER OF ROOMS OF %d REACHED.", ses->map->size);
 			show_error(ses, LIST_COMMAND, "#MAP DIG: MAXIMUM NUMBER OF ROOMS OF %d REACHED.", ses->map->size);
-			
+
 			return;
 			return;
 		}
 		}
 		add_undo(ses, "%d %d %d", room, ses->map->in_room, MAP_UNDO_CREATE|MAP_UNDO_LINK);
 		add_undo(ses, "%d %d %d", room, ses->map->in_room, MAP_UNDO_CREATE|MAP_UNDO_LINK);
@@ -5856,7 +5856,7 @@ void exit_edit(struct session *ses, struct exit_data *exit, char *opt, char *arg
 		else if ((dir = get_exit_dir(ses, arg3)) == 0)
 		else if ((dir = get_exit_dir(ses, arg3)) == 0)
 		{
 		{
 			show_error(ses, LIST_COMMAND, "#MAP %s {%s}: DIRECTION {%s} NOT FOUND.", opt, arg1, arg3);
 			show_error(ses, LIST_COMMAND, "#MAP %s {%s}: DIRECTION {%s} NOT FOUND.", opt, arg1, arg3);
-			
+
 			return;
 			return;
 		}
 		}
 
 
@@ -5969,7 +5969,7 @@ DO_MAP(map_entrance)
 	if (exit == NULL)
 	if (exit == NULL)
 	{
 	{
 		show_message(ses, LIST_COMMAND, "#MAP ENTRANCE: CAN'T FIND EXIT {%s}.", arg1);
 		show_message(ses, LIST_COMMAND, "#MAP ENTRANCE: CAN'T FIND EXIT {%s}.", arg1);
-		
+
 		return;
 		return;
 	}
 	}
 
 
@@ -6585,6 +6585,8 @@ DO_MAP(map_info)
 		add_nest_node_ses(ses, "info[MAP]", "{ROOMS}{%d}", cnt);
 		add_nest_node_ses(ses, "info[MAP]", "{ROOMS}{%d}", cnt);
 		add_nest_node_ses(ses, "info[MAP]", "{ROOMS_MAX}{%d}", ses->map->size);
 		add_nest_node_ses(ses, "info[MAP]", "{ROOMS_MAX}{%d}", ses->map->size);
 
 
+		show_message(ses, LIST_COMMAND, "#MAP INFO: DATA WRITTEN TO {info[MAP]}");
+
 		return;
 		return;
 	}
 	}
 
 
@@ -6846,7 +6848,7 @@ DO_MAP(map_landmark)
 
 
 			show_message(ses, LIST_COMMAND, "#OK: LANDMARK {%s} HAS VNUM {%d} AND IS DESCRIBED AS {%s} WITH SIZE {%s}.", arg1, room, arg3, arg4);
 			show_message(ses, LIST_COMMAND, "#OK: LANDMARK {%s} HAS VNUM {%d} AND IS DESCRIBED AS {%s} WITH SIZE {%s}.", arg1, room, arg3, arg4);
 		}
 		}
-	} 
+	}
 }
 }
 
 
 DO_MAP(map_unlandmark)
 DO_MAP(map_unlandmark)
@@ -7394,7 +7396,7 @@ DO_MAP(map_map)
 					case 'O':
 					case 'O':
 						logit(ses, gtd->out, logfile, LOG_FLAG_LINEFEED);
 						logit(ses, gtd->out, logfile, LOG_FLAG_LINEFEED);
 						break;
 						break;
-					
+
 					case 'L':
 					case 'L':
 						cat_sprintf(arg1, "{%02d}{%s}", ++row, gtd->out);
 						cat_sprintf(arg1, "{%02d}{%s}", ++row, gtd->out);
 						break;
 						break;
@@ -7538,7 +7540,7 @@ DO_MAP(map_map)
 					logit(ses, gtd->out, logfile, LOG_FLAG_LINEFEED);
 					logit(ses, gtd->out, logfile, LOG_FLAG_LINEFEED);
 //					fprintf(logfile, "%s\n", gtd->out);
 //					fprintf(logfile, "%s\n", gtd->out);
 					break;
 					break;
-				
+
 				case 'L':
 				case 'L':
 					cat_sprintf(arg1, "{%02d}{%s}", ++row, gtd->out);
 					cat_sprintf(arg1, "{%02d}{%s}", ++row, gtd->out);
 					break;
 					break;
@@ -7551,7 +7553,7 @@ DO_MAP(map_map)
 				case 'V':
 				case 'V':
 					cat_sprintf(arg1, "%s\n", gtd->out);
 					cat_sprintf(arg1, "%s\n", gtd->out);
 					break;
 					break;
-				
+
 				default:
 				default:
 					tintin_puts2(ses, gtd->out);
 					tintin_puts2(ses, gtd->out);
 					break;
 					break;
@@ -7634,6 +7636,13 @@ DO_MAP(map_offset)
 			ses->map->sav_top_col = get_number(ses, arg2);
 			ses->map->sav_top_col = get_number(ses, arg2);
 			ses->map->sav_bot_row = get_number(ses, arg3);
 			ses->map->sav_bot_row = get_number(ses, arg3);
 			ses->map->sav_bot_col = get_number(ses, arg4);
 			ses->map->sav_bot_col = get_number(ses, arg4);
+
+			if (ses->map->sav_top_row == 0 || ses->map->sav_top_col == 0 || ses->map->sav_bot_row == 0 || ses->map->sav_bot_col == 0)
+			{
+				show_error(ses, LIST_COMMAND, "#ERROR: #MAP OFFSET: INVALID SQUARE: {%s} {%s} {%s} {%s}", arg1, arg2, arg3, arg4);
+
+				return;
+			}
 		}
 		}
 		else
 		else
 		{
 		{
@@ -7683,7 +7692,7 @@ DO_MAP(map_read)
 		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);
 
 
 		fclose(myfile);
 		fclose(myfile);
-		
+
 		return;
 		return;
 	}
 	}
 
 
@@ -7845,7 +7854,7 @@ DO_MAP(map_read)
 
 
 			case '#':
 			case '#':
 				buffer[0] = gtd->tintin_char;
 				buffer[0] = gtd->tintin_char;
-				ses = script_driver(ses, LIST_COMMAND, buffer);
+				ses = script_driver(ses, LIST_COMMAND, NULL, buffer);
 				break;
 				break;
 
 
 			case  0:
 			case  0:
@@ -8058,7 +8067,7 @@ DO_MAP(map_roomflag)
 
 
 	if (*arg2 == 0)
 	if (*arg2 == 0)
 	{
 	{
-		TOG_BIT(ses->map->room_list[ses->map->in_room]->flags, flag);	
+		TOG_BIT(ses->map->room_list[ses->map->in_room]->flags, flag);
 	}
 	}
 	else if (is_abbrev(arg2, "ON"))
 	else if (is_abbrev(arg2, "ON"))
 	{
 	{
@@ -8745,7 +8754,7 @@ DO_MAP(map_vnum)
 	{
 	{
 		vnum2 = vnum1;
 		vnum2 = vnum1;
 	}
 	}
-	
+
 	if (vnum1 <= 0 || vnum1 >= ses->map->size || vnum2 <= 0 || vnum2 >= ses->map->size)
 	if (vnum1 <= 0 || vnum1 >= ses->map->size || vnum2 <= 0 || vnum2 >= ses->map->size)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#MAP VNUM {%s} {%s} - VNUMS MUST BE BETWEEN {1} and {%d}", arg1, arg2, ses->map->size - 1);
 		show_error(ses, LIST_COMMAND, "#MAP VNUM {%s} {%s} - VNUMS MUST BE BETWEEN {1} and {%d}", arg1, arg2, ses->map->size - 1);
@@ -8867,7 +8876,7 @@ DO_MAP(map_write)
 	{
 	{
 		fprintf(file, "LM {%s} {%d} {%s} {%s}\n", root->list[index]->arg1, root->list[index]->val32[0], root->list[index]->arg3, root->list[index]->arg4);
 		fprintf(file, "LM {%s} {%d} {%s} {%s}\n", root->list[index]->arg1, root->list[index]->val32[0], root->list[index]->arg3, root->list[index]->arg4);
 	}
 	}
-	fprintf(file, "\n\n");	
+	fprintf(file, "\n\n");
 
 
 	root = ses->list[LIST_TERRAIN];
 	root = ses->list[LIST_TERRAIN];
 
 
@@ -8875,7 +8884,7 @@ DO_MAP(map_write)
 	{
 	{
 		fprintf(file, "T {%s} {%s} {%s}\n", root->list[index]->arg1, root->list[index]->arg2, root->list[index]->arg3);
 		fprintf(file, "T {%s} {%s} {%s}\n", root->list[index]->arg1, root->list[index]->arg2, root->list[index]->arg3);
 	}
 	}
-	fprintf(file, "\n\n");	
+	fprintf(file, "\n\n");
 
 
 	for (index = 0 ; index < ses->map->size ; index++)
 	for (index = 0 ; index < ses->map->size ; index++)
 	{
 	{

+ 25 - 25
src/math.c

@@ -204,7 +204,7 @@ long double get_root(long double value, long double power)
 	{
 	{
 		mid = top / 2;
 		mid = top / 2;
 		sum = bot + mid;
 		sum = bot + mid;
-		
+
 		if (powl(sum, power) <= value)
 		if (powl(sum, power) <= value)
 		{
 		{
 			bot += mid;
 			bot += mid;
@@ -223,7 +223,7 @@ long double get_double(struct session *ses, char *str)
 
 
 	return val;
 	return val;
 }
 }
-	
+
 void get_number_string(struct session *ses, char *str, char *result)
 void get_number_string(struct session *ses, char *str, char *result)
 {
 {
 	long double val = get_number(ses, str);
 	long double val = get_number(ses, str);
@@ -242,7 +242,7 @@ long double mathswitch(struct session *ses, char *left, char *right)
 
 
 /*
 /*
 	Flexible tokenized mathematical expression interpreter
 	Flexible tokenized mathematical expression interpreter
-	
+
 	If seed is set it forces floating point math
 	If seed is set it forces floating point math
 */
 */
 
 
@@ -473,7 +473,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 						{
 						{
 							if (debug)
 							if (debug)
 							{
 							{
-								show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: \x7B FOUND INSIDE A NUMBER");
+								show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: \x7B FOUND INSIDE A NUMBER");
 							}
 							}
 							pop_call();
 							pop_call();
 							return FALSE;
 							return FALSE;
@@ -488,7 +488,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 						{
 						{
 							if (debug)
 							if (debug)
 							{
 							{
-								show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: \" FOUND INSIDE A NUMBER");
+								show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: \" FOUND INSIDE A NUMBER");
 							}
 							}
 							pop_call();
 							pop_call();
 							return FALSE;
 							return FALSE;
@@ -503,7 +503,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 						{
 						{
 							if (debug)
 							if (debug)
 							{
 							{
-								show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: PARANTESES FOUND INSIDE A NUMBER");
+								show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: PARANTESES FOUND INSIDE A NUMBER");
 							}
 							}
 							pop_call();
 							pop_call();
 							return FALSE;
 							return FALSE;
@@ -527,7 +527,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 						}
 						}
 						*pta++ = *pti++;
 						*pta++ = *pti++;
 						break;
 						break;
-						
+
 					case '.':
 					case '.':
 						if (pti[1] == '.')
 						if (pti[1] == '.')
 						{
 						{
@@ -556,7 +556,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 							{
 							{
 								if (debug)
 								if (debug)
 								{
 								{
-									show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: MORE THAN ONE POINT FOUND INSIDE A NUMBER");
+									show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: MORE THAN ONE POINT FOUND INSIDE A NUMBER");
 								}
 								}
 								precision = 0;
 								precision = 0;
 								pop_call();
 								pop_call();
@@ -587,7 +587,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 						{
 						{
 							if (debug)
 							if (debug)
 							{
 							{
-								show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: EXPRESSION STARTED WITH AN OPERATOR.");
+								show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: EXPRESSION STARTED WITH AN OPERATOR.");
 							}
 							}
 							pop_call();
 							pop_call();
 							return FALSE;
 							return FALSE;
@@ -608,7 +608,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 
 
 							if (debug)
 							if (debug)
 							{
 							{
-								show_debug(ses, LIST_VARIABLE, "#DEBUG MATH {%s}: FOUND OPERATOR %s WHILE EXPECTING A VALUE.", str, buf3);
+								show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH {%s}: FOUND OPERATOR %s WHILE EXPECTING A VALUE.", str, buf3);
 							}
 							}
 							pop_call();
 							pop_call();
 							return FALSE;
 							return FALSE;
@@ -630,7 +630,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 
 
 							if (debug)
 							if (debug)
 							{
 							{
-								show_debug(ses, LIST_VARIABLE, "#DEBUG MATH {%s}: INVALID NUMBER %s.", str, buf3);
+								show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH {%s}: INVALID NUMBER %s.", str, buf3);
 							}
 							}
 
 
 							pop_call();
 							pop_call();
@@ -709,7 +709,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 
 
 						if (debug)
 						if (debug)
 						{
 						{
-							show_debug(ses, LIST_VARIABLE, "#DEBUG MATH {%s}: INVALID NUMBER %s.", str, buf3);
+							show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH {%s}: INVALID NUMBER %s.", str, buf3);
 						}
 						}
 						pop_call();
 						pop_call();
 						return FALSE;
 						return FALSE;
@@ -783,7 +783,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 						{
 						{
 							if (debug)
 							if (debug)
 							{
 							{
-								show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: UNKNOWN OPERATOR: %c%c", pti[0], pti[1]);
+								show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: UNKNOWN OPERATOR: %c%c", pti[0], pti[1]);
 							}
 							}
 							pop_call();
 							pop_call();
 							return FALSE;
 							return FALSE;
@@ -815,13 +815,13 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 								*pta++ = *pti++;
 								*pta++ = *pti++;
 								MATH_NODE(EXP_OPERATOR, EXP_PR_INTMUL, EXP_NUMBER);
 								MATH_NODE(EXP_OPERATOR, EXP_PR_INTMUL, EXP_NUMBER);
 								break;
 								break;
-							
+
 							default:
 							default:
 								MATH_NODE(EXP_OPERATOR, EXP_PR_INTMUL, EXP_NUMBER);
 								MATH_NODE(EXP_OPERATOR, EXP_PR_INTMUL, EXP_NUMBER);
 								break;
 								break;
 						}
 						}
 						break;
 						break;
-	
+
 					case '/':
 					case '/':
 						*pta++ = *pti++;
 						*pta++ = *pti++;
 
 
@@ -956,7 +956,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 							default:
 							default:
 								if (debug)
 								if (debug)
 								{
 								{
-									show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: UNKNOWN OPERATOR: %c%c", pti[-1], pti[0]);
+									show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: UNKNOWN OPERATOR: %c%c", pti[-1], pti[0]);
 								}
 								}
 								pop_call();
 								pop_call();
 								return FALSE;
 								return FALSE;
@@ -966,7 +966,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 					default:
 					default:
 						if (debug)
 						if (debug)
 						{
 						{
-							show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: UNKNOWN OPERATOR: %c", *pti);
+							show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: UNKNOWN OPERATOR: %c", *pti);
 						}
 						}
 						pop_call();
 						pop_call();
 						return FALSE;
 						return FALSE;
@@ -979,7 +979,7 @@ int mathexp_tokenize(struct session *ses, char *str, int seed, int debug)
 	{
 	{
 		if (debug)
 		if (debug)
 		{
 		{
-			show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: UNMATCHED PARENTHESES, LEVEL: %d", level);
+			show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: UNMATCHED PARENTHESES, LEVEL: %d", level);
 		}
 		}
 		pop_call();
 		pop_call();
 		return FALSE;
 		return FALSE;
@@ -1070,7 +1070,7 @@ void mathexp_compute(struct session *ses, struct math_node *node)
 		case EXP_OP_DICE:
 		case EXP_OP_DICE:
 			if (node->next->val <= 0)
 			if (node->next->val <= 0)
 			{
 			{
-				show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: INVALID DICE: %lld", (long long) node->next->val);
+				show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: INVALID DICE: %lld", (long long) node->next->val);
 				value = 0;
 				value = 0;
 			}
 			}
 			else
 			else
@@ -1094,7 +1094,7 @@ void mathexp_compute(struct session *ses, struct math_node *node)
 		case EXP_OP_DIVIDE:
 		case EXP_OP_DIVIDE:
 			if (node->next->val == 0)
 			if (node->next->val == 0)
 			{
 			{
-				show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: DIVISION BY ZERO.");
+				show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: DIVISION BY ZERO.");
 				value = 0;
 				value = 0;
 				precision = 0;
 				precision = 0;
 			}
 			}
@@ -1182,7 +1182,7 @@ void mathexp_compute(struct session *ses, struct math_node *node)
 		case EXP_OP_EQUAL:
 		case EXP_OP_EQUAL:
 			value = tineval(ses, node->prev, node->next) != 0;
 			value = tineval(ses, node->prev, node->next) != 0;
 			break;
 			break;
-		
+
 		case EXP_OP_COMPARE:
 		case EXP_OP_COMPARE:
 			value = tincmp(node->prev, node->next) == 0;
 			value = tincmp(node->prev, node->next) == 0;
 			break;
 			break;
@@ -1190,13 +1190,13 @@ void mathexp_compute(struct session *ses, struct math_node *node)
 		case EXP_OP_NOT_EQUAL:
 		case EXP_OP_NOT_EQUAL:
 			value = tineval(ses, node->prev, node->next) == 0;
 			value = tineval(ses, node->prev, node->next) == 0;
 			break;
 			break;
-		
+
 		case EXP_OP_NOT_COMPARE:
 		case EXP_OP_NOT_COMPARE:
 			value = tincmp(node->prev, node->next) != 0;
 			value = tincmp(node->prev, node->next) != 0;
 			break;
 			break;
 
 
 		default:
 		default:
-			show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: UNKNOWN OPERATOR: %c%c%c", (int) node->val % 128, (int) node->val % 16384 / 128, (int) node->val % 2097152 / 16384);
+			show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: UNKNOWN OPERATOR: %c%c%c", (int) node->val % 128, (int) node->val % 16384 / 128, (int) node->val % 2097152 / 16384);
 			value = 0;
 			value = 0;
 			break;
 			break;
 	}
 	}
@@ -1526,7 +1526,7 @@ long double tincmp(struct math_node *left, struct math_node *right)
 {
 {
 	if (left->type != right->type)
 	if (left->type != right->type)
 	{
 	{
-		show_debug(gtd->ses, LIST_VARIABLE, "#DEBUG MATH: COMPARING STRING WITH A NUMBER.");
+		show_debug(gtd->ses, LIST_VARIABLE, NULL, "#DEBUG MATH: COMPARING STRING WITH A NUMBER.");
 
 
 		return 0;
 		return 0;
 	}
 	}
@@ -1545,7 +1545,7 @@ long double tineval(struct session *ses, struct math_node *left, struct math_nod
 {
 {
 	if (left->type != right->type)
 	if (left->type != right->type)
 	{
 	{
-		show_debug(ses, LIST_VARIABLE, "#DEBUG MATH: COMPARING %s WITH %s.", left->type == EXP_NUMBER ? "NUMBER" : "STRING", right->type == EXP_NUMBER ? "NUMBER" : "STRING");
+		show_debug(ses, LIST_VARIABLE, NULL, "#DEBUG MATH: COMPARING %s WITH %s.", left->type == EXP_NUMBER ? "NUMBER" : "STRING", right->type == EXP_NUMBER ? "NUMBER" : "STRING");
 
 
 		return 0;
 		return 0;
 	}
 	}

+ 1 - 1
src/mccp.c

@@ -36,7 +36,7 @@ void *zlib_alloc( void *opaque, unsigned int items, unsigned int size )
 }
 }
 
 
 
 
-void zlib_free( void *opaque, void *address ) 
+void zlib_free( void *opaque, void *address )
 {
 {
 	free(address);
 	free(address);
 }
 }

+ 1 - 1
src/memory.c

@@ -423,7 +423,7 @@ char *str_cat_printf(char **str, char *fmt, ...)
 	int len;
 	int len;
 
 
 	va_start(args, fmt);
 	va_start(args, fmt);
-	
+
 	len = vasprintf(&arg, fmt, args);
 	len = vasprintf(&arg, fmt, args);
 
 
 	va_end(args);
 	va_end(args);

+ 48 - 0
src/misc.c

@@ -26,6 +26,7 @@
 
 
 #include "tintin.h"
 #include "tintin.h"
 
 
+#include "gui.h"
 
 
 DO_COMMAND(do_bell)
 DO_COMMAND(do_bell)
 {
 {
@@ -214,6 +215,53 @@ DO_COMMAND(do_test)
 		return ses;
 		return ses;
 	}
 	}
 
 
+	if (!strcmp(arg1, "gui"))
+	{
+		char data[BUFFER_SIZE];
+		FILE *file;
+		size_t len;
+
+		strcpy(data, tt_gui);
+
+		len = strlen(data);
+
+		file = fmemopen(data, len, "r");
+
+		gtd->level->quiet++;
+
+		ses = read_file(ses, file, "tt_gui.h");
+
+		gtd->level->quiet--;
+
+		fclose(file);
+
+		return ses;
+	}
+
+	if (!strcmp(arg1, "regex"))
+	{
+		char data[BUFFER_SIZE];
+		FILE *file;
+		size_t len;
+
+		strcpy(data, tt_regex);
+
+		len = strlen(data);
+
+		file = fmemopen(data, len, "r");
+
+		gtd->level->quiet++;
+
+		ses = read_file(ses, file, "tt_regex.h");
+
+		gtd->level->quiet--;
+
+		fclose(file);
+
+		return ses;
+
+	}
+
 	return ses;
 	return ses;
 }
 }
 
 

+ 6 - 6
src/msdp.c

@@ -277,7 +277,7 @@ void process_msdp_index_val(struct session *ses, struct port_data *buddy, int va
 			msdp_table[var_index].fun(ses, buddy, val_index);
 			msdp_table[var_index].fun(ses, buddy, val_index);
 		}
 		}
 	}
 	}
-} 
+}
 
 
 // 1d array support for commands
 // 1d array support for commands
 
 
@@ -377,7 +377,7 @@ void process_msdp_varval(struct session *ses, struct port_data *buddy, char *var
 		}
 		}
 		return;
 		return;
 	}
 	}
-} 
+}
 
 
 void msdp_command_list(struct session *ses, struct port_data *buddy, int index)
 void msdp_command_list(struct session *ses, struct port_data *buddy, int index)
 {
 {
@@ -462,7 +462,7 @@ void msdp_command_send(struct session *ses, struct port_data *buddy, int index)
 {
 {
 	if (HAS_BIT(buddy->msdp_data[index]->flags, MSDP_FLAG_SENDABLE))
 	if (HAS_BIT(buddy->msdp_data[index]->flags, MSDP_FLAG_SENDABLE))
 	{
 	{
-		SET_BIT(buddy->msdp_data[index]->flags, MSDP_FLAG_UPDATED);	
+		SET_BIT(buddy->msdp_data[index]->flags, MSDP_FLAG_UPDATED);
 		SET_BIT(buddy->comm_flags, COMM_FLAG_MSDPUPDATE);
 		SET_BIT(buddy->comm_flags, COMM_FLAG_MSDPUPDATE);
 	}
 	}
 }
 }
@@ -613,7 +613,7 @@ void msdp_configure_arachnos(struct session *ses, struct port_data *buddy, int i
 				{
 				{
 					timeval_t = (time_t) atoll(val);
 					timeval_t = (time_t) atoll(val);
 					timeval_tm = *localtime(&timeval_t);
 					timeval_tm = *localtime(&timeval_t);
-					
+
 					strftime(msg_time, 20, "%T %D", &timeval_tm);
 					strftime(msg_time, 20, "%T %D", &timeval_tm);
 				}
 				}
 				else if (!strcmp(var, "MSG_BODY"))
 				else if (!strcmp(var, "MSG_BODY"))
@@ -624,14 +624,14 @@ void msdp_configure_arachnos(struct session *ses, struct port_data *buddy, int i
 				{
 				{
 					timeval_t = (time_t) atoll(val);
 					timeval_t = (time_t) atoll(val);
 					timeval_tm = *localtime(&timeval_t);
 					timeval_tm = *localtime(&timeval_t);
-					
+
 					strftime(mud_uptime, 20, "%T %D", &timeval_tm);
 					strftime(mud_uptime, 20, "%T %D", &timeval_tm);
 				}
 				}
 				else if (!strcmp(var, "MUD_UPDATE"))
 				else if (!strcmp(var, "MUD_UPDATE"))
 				{
 				{
 					timeval_t = (time_t) atoll(val);
 					timeval_t = (time_t) atoll(val);
 					timeval_tm = *localtime(&timeval_t);
 					timeval_tm = *localtime(&timeval_t);
-					
+
 					strftime(mud_update, 20, "%T %D", &timeval_tm);
 					strftime(mud_update, 20, "%T %D", &timeval_tm);
 				}
 				}
 				else if (!strcmp(var, "MUD_PLAYERS"))
 				else if (!strcmp(var, "MUD_PLAYERS"))

+ 3 - 3
src/nest.c

@@ -137,7 +137,7 @@ struct listnode *search_nest_node_ses(struct session *ses, char *variable)
 	return NULL;
 	return NULL;
 }
 }
 
 
-	
+
 struct listnode *search_nest_node(struct listroot *root, char *variable)
 struct listnode *search_nest_node(struct listroot *root, char *variable)
 {
 {
 	char name[BUFFER_SIZE], *arg;
 	char name[BUFFER_SIZE], *arg;
@@ -282,7 +282,7 @@ void update_nest_node(struct listroot *root, char *arg)
 		{
 		{
 			update_nest_node(update_nest_root(root, arg1), arg2);
 			update_nest_node(update_nest_root(root, arg1), arg2);
 		}
 		}
-		else if (*arg1)
+		else //if (*arg1)
 		{
 		{
 			update_node_list(root, arg1, arg2, "", "");
 			update_node_list(root, arg1, arg2, "", "");
 		}
 		}
@@ -370,7 +370,7 @@ int delete_nest_node_with_wild(struct listroot *root, char *variable)
 				{
 				{
 					show_message(root->ses, LIST_VARIABLE, "#OK. {%s} IS NO LONGER A VARIABLE.", root->list[index]->arg1);
 					show_message(root->ses, LIST_VARIABLE, "#OK. {%s} IS NO LONGER A VARIABLE.", root->list[index]->arg1);
 				}
 				}
-				
+
 				delete_index_list(root, index);
 				delete_index_list(root, index);
 
 
 				found = TRUE;
 				found = TRUE;

+ 3 - 3
src/net.c

@@ -354,7 +354,7 @@ void write_line_mud(struct session *ses, char *line, int size)
 				syserr_printf(ses, "write_line_mud: write");
 				syserr_printf(ses, "write_line_mud: write");
 			}
 			}
 		}
 		}
-		
+
 		if (result == -1)
 		if (result == -1)
 		{
 		{
 			cleanup_session(ses);
 			cleanup_session(ses);
@@ -690,7 +690,7 @@ void process_one_line(struct session *ses, char *linebuf, int prompt)
 
 
 		strip_vt102_codes(linebuf, temp);
 		strip_vt102_codes(linebuf, temp);
 
 
-		show_debug(ses, LIST_GAG, COLOR_DEBUG "#DEBUG GAG " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} " COLOR_COMMAND "[" COLOR_STRING "%d" COLOR_COMMAND "]", temp, ses->gagline + 1);
+		show_debug(ses, LIST_GAG, NULL, COLOR_DEBUG "#DEBUG GAG " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} " COLOR_COMMAND "[" COLOR_STRING "%d" COLOR_COMMAND "]", temp, ses->gagline + 1);
 
 
 		pop_call();
 		pop_call();
 		return;
 		return;
@@ -714,7 +714,7 @@ void process_one_line(struct session *ses, char *linebuf, int prompt)
 	if (ses == gtd->ses)
 	if (ses == gtd->ses)
 	{
 	{
 		char *output = str_alloc_stack(0);
 		char *output = str_alloc_stack(0);
-		
+
 		str_cpy(&output, linebuf);
 		str_cpy(&output, linebuf);
 
 
 		print_line(ses, &output, prompt);
 		print_line(ses, &output, prompt);

+ 30 - 19
src/parse.c

@@ -183,6 +183,7 @@ int is_vowel(char *str)
 struct session *parse_input(struct session *ses, char *input)
 struct session *parse_input(struct session *ses, char *input)
 {
 {
 	char *line;
 	char *line;
+	struct listnode *node;
 
 
 	push_call("parse_input(%s,%s)",ses->name,input);
 	push_call("parse_input(%s,%s)",ses->name,input);
 /*
 /*
@@ -200,9 +201,11 @@ struct session *parse_input(struct session *ses, char *input)
 	{
 	{
 		sub_arg_all(ses, input, line, 1, SUB_SEC);
 		sub_arg_all(ses, input, line, 1, SUB_SEC);
 
 
-		if (check_all_aliases(ses, line))
+		node = check_all_aliases(ses, line);
+
+		if (node)
 		{
 		{
-			ses = script_driver(ses, LIST_ALIAS, line);
+			ses = script_driver(ses, LIST_ALIAS, node, line);
 		}
 		}
 		else if (HAS_BIT(ses->config_flags, CONFIG_FLAG_SPEEDWALK) && is_speedwalk(ses, line))
 		else if (HAS_BIT(ses->config_flags, CONFIG_FLAG_SPEEDWALK) && is_speedwalk(ses, line))
 		{
 		{
@@ -233,21 +236,25 @@ struct session *parse_input(struct session *ses, char *input)
 
 
 		if (parse_command(ses, line))
 		if (parse_command(ses, line))
 		{
 		{
-			ses = script_driver(ses, LIST_COMMAND, line);
-		}
-		else if (check_all_aliases(ses, line))
-		{
-			ses = script_driver(ses, LIST_ALIAS, line);
-		}
-		else if (HAS_BIT(ses->config_flags, CONFIG_FLAG_SPEEDWALK) && is_speedwalk(ses, line))
-		{
-			process_speedwalk(ses, line);
+			ses = script_driver(ses, LIST_COMMAND, NULL, line);
 		}
 		}
 		else
 		else
 		{
 		{
-			write_mud(ses, line, SUB_VAR|SUB_FUN|SUB_ESC|SUB_EOL);
-		}
+			node = check_all_aliases(ses, line);
 
 
+			if (node)
+			{
+				ses = script_driver(ses, LIST_ALIAS, node, line);
+			}
+			else if (HAS_BIT(ses->config_flags, CONFIG_FLAG_SPEEDWALK) && is_speedwalk(ses, line))
+			{
+				process_speedwalk(ses, line);
+			}
+			else
+			{
+				write_mud(ses, line, SUB_VAR|SUB_FUN|SUB_ESC|SUB_EOL);
+			}
+		}
 		if (*input == COMMAND_SEPARATOR)
 		if (*input == COMMAND_SEPARATOR)
 		{
 		{
 			input++;
 			input++;
@@ -452,9 +459,13 @@ struct session *parse_tintin_command(struct session *ses, char *input)
 
 
 		input = get_arg_in_braces(ses, input, line, GET_ALL);
 		input = get_arg_in_braces(ses, input, line, GET_ALL);
 
 
-		while (cnt-- > 0)
+		while (*line)
 		{
 		{
-			ses = script_driver(ses, LIST_COMMAND, line);
+			for (int i = cnt ; i > 0 ; i--)
+			{
+				ses = script_driver(ses, LIST_COMMAND, NULL, line);
+			}
+			input = get_arg_in_braces(ses, input, line, GET_ALL);
 		}
 		}
 		return ses;
 		return ses;
 	}
 	}
@@ -469,7 +480,7 @@ struct session *parse_tintin_command(struct session *ses, char *input)
 
 
 			substitute(ses, line, line, SUB_VAR|SUB_FUN);
 			substitute(ses, line, line, SUB_VAR|SUB_FUN);
 
 
-			script_driver(sesptr, LIST_COMMAND, line);
+			script_driver(sesptr, LIST_COMMAND, NULL, line);
 
 
 			return ses;
 			return ses;
 		}
 		}
@@ -598,7 +609,7 @@ char *get_arg_all(struct session *ses, char *string, char *result, int verbatim)
 			break;
 			break;
 		}
 		}
 	}
 	}
-	*pto = '\0'; 
+	*pto = '\0';
 
 
 	return pti;
 	return pti;
 }
 }
@@ -709,7 +720,7 @@ char *sub_arg_in_braces(struct session *ses, char *string, char *result, int fla
 	if (*string == 0)
 	if (*string == 0)
 	{
 	{
 		*result = 0;
 		*result = 0;
-		
+
 		return string;
 		return string;
 	}
 	}
 
 
@@ -775,7 +786,7 @@ char *get_arg_with_spaces(struct session *ses, char *string, char *result, int f
 		}
 		}
 		*pto++ = *pti++;
 		*pto++ = *pti++;
 	}
 	}
-	*pto = '\0'; 
+	*pto = '\0';
 
 
 	return pti;
 	return pti;
 }
 }

+ 12 - 13
src/path.c

@@ -546,7 +546,7 @@ DO_PATH(path_run)
 	{
 	{
 		if (*arg1)
 		if (*arg1)
 		{
 		{
-		
+
 			delay = (long long) (get_number(ses, arg1) * 1000000.0);
 			delay = (long long) (get_number(ses, arg1) * 1000000.0);
 			total = 0;
 			total = 0;
 
 
@@ -565,7 +565,7 @@ DO_PATH(path_run)
 		{
 		{
 			while (root->update < root->used)
 			while (root->update < root->used)
 			{
 			{
-				script_driver(ses, LIST_COMMAND, root->list[root->update++]->arg1);
+				script_driver(ses, LIST_COMMAND, NULL, root->list[root->update++]->arg1);
 			}
 			}
 			check_all_events(ses, EVENT_FLAG_MAP, 0, 0, "END OF RUN");
 			check_all_events(ses, EVENT_FLAG_MAP, 0, 0, "END OF RUN");
 		}
 		}
@@ -593,7 +593,7 @@ DO_PATH(path_walk)
 		}
 		}
 		else
 		else
 		{
 		{
-			script_driver(ses, LIST_COMMAND, root->list[--root->update]->arg2);
+			script_driver(ses, LIST_COMMAND, NULL, root->list[--root->update]->arg2);
 
 
 			if (root->update == 0)
 			if (root->update == 0)
 			{
 			{
@@ -609,7 +609,7 @@ DO_PATH(path_walk)
 		}
 		}
 		else
 		else
 		{
 		{
-			script_driver(ses, LIST_COMMAND, root->list[root->update++]->arg1);
+			script_driver(ses, LIST_COMMAND, NULL, root->list[root->update++]->arg1);
 
 
 			if (root->update == root->used)
 			if (root->update == root->used)
 			{
 			{
@@ -931,7 +931,7 @@ DO_PATH(path_undo)
 	if (root->update != root->used)
 	if (root->update != root->used)
 	{
 	{
 		show_message(ses, LIST_COMMAND, "#ERROR: #PATH UNDO: YOUR POSITION IS NOT AT END OF PATH.");
 		show_message(ses, LIST_COMMAND, "#ERROR: #PATH UNDO: YOUR POSITION IS NOT AT END OF PATH.");
-	
+
 		return;
 		return;
 	}
 	}
 
 
@@ -944,7 +944,7 @@ DO_PATH(path_undo)
 
 
 	DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
 	DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
 
 
-	script_driver(ses, LIST_COMMAND, root->list[root->used - 1]->arg2);
+	script_driver(ses, LIST_COMMAND, NULL, root->list[root->used - 1]->arg2);
 
 
 	SET_BIT(ses->flags, SES_FLAG_PATHMAPPING);
 	SET_BIT(ses->flags, SES_FLAG_PATHMAPPING);
 
 
@@ -965,7 +965,7 @@ void check_append_path(struct session *ses, char *forward, char *backward, doubl
 	{
 	{
 		if ((node = search_node_list(ses->list[LIST_PATHDIR], forward)))
 		if ((node = search_node_list(ses->list[LIST_PATHDIR], forward)))
 		{
 		{
-			show_debug(ses, LIST_PATHDIR, "#DEBUG PATHDIR {%s} {%s}", node->arg1, node->arg2);
+			show_debug(ses, LIST_PATHDIR, node, "#DEBUG PATHDIR {%s} {%s}", node->arg1, node->arg2);
 
 
 			create_node_list(root, node->arg1, node->arg2, ftos(delay), "");
 			create_node_list(root, node->arg1, node->arg2, ftos(delay), "");
 
 
@@ -973,25 +973,25 @@ void check_append_path(struct session *ses, char *forward, char *backward, doubl
 		}
 		}
 		else if (force)
 		else if (force)
 		{
 		{
-			show_debug(ses, LIST_PATHDIR, "#DEBUG PATHDIR {%s} {%s}", forward, backward);
-				
+			show_debug(ses, LIST_PATHDIR, NULL, "#DEBUG PATHDIR {%s} {%s}", forward, backward);
+
 			create_node_list(root, forward, backward, ftos(delay), "");
 			create_node_list(root, forward, backward, ftos(delay), "");
 
 
 			root->update = root->used;
 			root->update = root->used;
 		}
 		}
-				
+
 	}
 	}
 	else
 	else
 	{
 	{
 		if ((node = search_node_list(ses->list[LIST_PATHDIR], forward)))
 		if ((node = search_node_list(ses->list[LIST_PATHDIR], forward)))
 		{
 		{
-			show_debug(ses, LIST_PATHDIR, "#DEBUG PATHDIR {%s} {%s}", node->arg1, node->arg2);
+			show_debug(ses, LIST_PATHDIR, node, "#DEBUG PATHDIR {%s} {%s}", node->arg1, node->arg2);
 
 
 			create_node_list(root, node->arg1, node->arg2, ftos(delay), "");
 			create_node_list(root, node->arg1, node->arg2, ftos(delay), "");
 		}
 		}
 		else
 		else
 		{
 		{
-			show_debug(ses, LIST_PATHDIR, "#DEBUG PATHDIR {%s} {%s}", forward, backward);
+			show_debug(ses, LIST_PATHDIR, NULL, "#DEBUG PATHDIR {%s} {%s}", forward, backward);
 
 
 			create_node_list(root, forward, backward, ftos(delay), "");
 			create_node_list(root, forward, backward, ftos(delay), "");
 		}
 		}
@@ -1166,4 +1166,3 @@ DO_PATH(path_end)
 		show_message(ses, LIST_COMMAND, "#PATH: YOU ARE NOT MAPPING A PATH.");
 		show_message(ses, LIST_COMMAND, "#PATH: YOU ARE NOT MAPPING A PATH.");
 	}
 	}
 }
 }
-	

+ 11 - 7
src/port.c

@@ -95,7 +95,7 @@ DO_PORT(port_initialize)
 	if (*arg1 == 0 || *arg2 == 0)
 	if (*arg1 == 0 || *arg2 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #PORT INITIALIZE {NAME} {PORT} {FILE}");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #PORT INITIALIZE {NAME} {PORT} {FILE}");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -141,7 +141,7 @@ DO_PORT(port_initialize)
 			return ses;
 			return ses;
 		}
 		}
 
 
-		ld.l_onoff  = 0; 
+		ld.l_onoff  = 0;
 		ld.l_linger = 100;
 		ld.l_linger = 100;
 
 
 		setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &ld, sizeof(ld));
 		setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *) &ld, sizeof(ld));
@@ -392,6 +392,8 @@ void process_port_connections(struct session *ses, fd_set *read_set, fd_set *wri
 			FD_CLR(buddy->fd, read_set);
 			FD_CLR(buddy->fd, read_set);
 
 
 			close_port(ses, buddy, TRUE);
 			close_port(ses, buddy, TRUE);
+
+			continue;
 		}
 		}
 		else if (FD_ISSET(buddy->fd, read_set))
 		else if (FD_ISSET(buddy->fd, read_set))
 		{
 		{
@@ -401,6 +403,8 @@ void process_port_connections(struct session *ses, fd_set *read_set, fd_set *wri
 				FD_CLR(buddy->fd, read_set);
 				FD_CLR(buddy->fd, read_set);
 
 
 				close_port(ses, buddy, TRUE);
 				close_port(ses, buddy, TRUE);
+
+				continue;
 			}
 			}
 		}
 		}
 
 
@@ -693,7 +697,7 @@ DO_PORT(port_call)
 		if (error)
 		if (error)
 		{
 		{
 			port_printf(ses, "Failed to call %s, unknown host.", host);
 			port_printf(ses, "Failed to call %s, unknown host.", host);
-			
+
 			return ses;
 			return ses;
 		}
 		}
 	}
 	}
@@ -1054,7 +1058,7 @@ DO_PORT(port_flag)
 		else
 		else
 		{
 		{
 			tintin_printf2(ses, "#SYNTAX: #PORT FLAG DND [ON|OFF]");
 			tintin_printf2(ses, "#SYNTAX: #PORT FLAG DND [ON|OFF]");
-			
+
 			return ses;
 			return ses;
 		}
 		}
 
 
@@ -1084,7 +1088,7 @@ DO_PORT(port_flag)
 		else
 		else
 		{
 		{
 			tintin_printf2(ses, "#SYNTAX: #PORT FLAG PRIVATE [ON|OFF]");
 			tintin_printf2(ses, "#SYNTAX: #PORT FLAG PRIVATE [ON|OFF]");
-			
+
 			return ses;
 			return ses;
 		}
 		}
 
 
@@ -1169,7 +1173,7 @@ DO_PORT(port_ignore)
 	{
 	{
 		port_printf(ses, "You are no longer ignoring %s.", buddy->name);
 		port_printf(ses, "You are no longer ignoring %s.", buddy->name);
 	}
 	}
-	
+
 	return ses;
 	return ses;
 }
 }
 
 
@@ -1281,7 +1285,7 @@ DO_PORT(port_rank)
 	else
 	else
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #PORT RANK <NAME> <SPY|SCOUT>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #PORT RANK <NAME> <SPY|SCOUT>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 

+ 6 - 8
src/regex.c

@@ -73,7 +73,7 @@ DO_COMMAND(do_regexp)
 		{
 		{
 			substitute(ses, arg3, arg3, SUB_CMD);
 			substitute(ses, arg3, arg3, SUB_CMD);
 
 
-			ses = script_driver(ses, LIST_COMMAND, arg3);
+			ses = script_driver(ses, LIST_COMMAND, NULL, arg3);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -83,7 +83,7 @@ DO_COMMAND(do_regexp)
 
 
 			if (*arg4)
 			if (*arg4)
 			{
 			{
-				ses = script_driver(ses, LIST_COMMAND, arg4);
+				ses = script_driver(ses, LIST_COMMAND, NULL, arg4);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -212,12 +212,10 @@ pcre *regexp_compile(struct session *ses, char *exp, int comp_option)
 
 
 int check_one_regexp(struct session *ses, struct listnode *node, char *line, char *original, int comp_option)
 int check_one_regexp(struct session *ses, struct listnode *node, char *line, char *original, int comp_option)
 {
 {
-	char *exp, *str;
+	char *exp, *str, result[BUFFER_SIZE];
 
 
 	if (node->regex == NULL)
 	if (node->regex == NULL)
 	{
 	{
-		char result[BUFFER_SIZE];
-
 		substitute(ses, node->arg1, result, SUB_VAR|SUB_FUN);
 		substitute(ses, node->arg1, result, SUB_VAR|SUB_FUN);
 
 
 		exp = result;
 		exp = result;
@@ -235,7 +233,7 @@ int check_one_regexp(struct session *ses, struct listnode *node, char *line, cha
 	else
 	else
 	{
 	{
 		str = line;
 		str = line;
-	}	
+	}
 
 
 	return tintin_regexp(ses, node->regex, str, exp, comp_option, REGEX_FLAG_ARG);
 	return tintin_regexp(ses, node->regex, str, exp, comp_option, REGEX_FLAG_ARG);
 }
 }
@@ -931,7 +929,7 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 				}
 				}
 				{
 				{
 					int i = 1;
 					int i = 1;
-	
+
 					while (pti[i] == '$') i++;
 					while (pti[i] == '$') i++;
 
 
 					if (pti[i])
 					if (pti[i])
@@ -1013,7 +1011,7 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 						pti += 2;
 						pti += 2;
 						pto += sprintf(pto, "%s", *pti == 0 ? "([^\\x20-\\xfe]*)" : "([^\\x20-\\xfe]*?)");
 						pto += sprintf(pto, "%s", *pti == 0 ? "([^\\x20-\\xfe]*)" : "([^\\x20-\\xfe]*?)");
 						break;
 						break;
-						
+
 					case 's':
 					case 's':
 						pti += 2;
 						pti += 2;
 						pto += sprintf(pto, "%s", *pti == 0 ? "(\\s*)" : "(\\s*?)");
 						pto += sprintf(pto, "%s", *pti == 0 ? "(\\s*)" : "(\\s*?)");

+ 224 - 14
src/scan.c

@@ -42,6 +42,7 @@ DO_SCAN(scan_csv);
 DO_SCAN(scan_dir);
 DO_SCAN(scan_dir);
 DO_SCAN(scan_file);
 DO_SCAN(scan_file);
 DO_SCAN(scan_forward);
 DO_SCAN(scan_forward);
+DO_SCAN(scan_json);
 DO_SCAN(scan_tsv);
 DO_SCAN(scan_tsv);
 DO_SCAN(scan_txt);
 DO_SCAN(scan_txt);
 
 
@@ -66,6 +67,7 @@ struct scan_type scan_table[] =
 	{       "DIR",              scan_dir,     SCAN_FLAG_NONE,                "Scan a directory to a variable."    },
 	{       "DIR",              scan_dir,     SCAN_FLAG_NONE,                "Scan a directory to a variable."    },
 	{       "FILE",             scan_file,    SCAN_FLAG_FILE,                "Scan a file all at once."           },
 	{       "FILE",             scan_file,    SCAN_FLAG_FILE,                "Scan a file all at once."           },
 	{       "FORWARD",          scan_forward, SCAN_FLAG_FILE,                "Scan a file and send each line."    },
 	{       "FORWARD",          scan_forward, SCAN_FLAG_FILE,                "Scan a file and send each line."    },
+	{       "JSON",             scan_json,    SCAN_FLAG_FILE,                "Scan a json file."                  },
 	{       "TSV",              scan_tsv,     SCAN_FLAG_FILE|SCAN_FLAG_SCAN, "Scan a tab separated value file."   },
 	{       "TSV",              scan_tsv,     SCAN_FLAG_FILE|SCAN_FLAG_SCAN, "Scan a tab separated value file."   },
 	{       "TXT",              scan_txt,     SCAN_FLAG_FILE|SCAN_FLAG_SCAN, "Scan a text file line by line."     },
 	{       "TXT",              scan_txt,     SCAN_FLAG_FILE|SCAN_FLAG_SCAN, "Scan a text file line by line."     },
 	{       "",                 NULL,         0,                             ""                                   }
 	{       "",                 NULL,         0,                             ""                                   }
@@ -239,7 +241,7 @@ DO_SCAN(scan_csv)
 		}
 		}
 		else
 		else
 		{
 		{
-		
+
 			arg = strchr(line, '\n');
 			arg = strchr(line, '\n');
 
 
 			if (arg)
 			if (arg)
@@ -347,12 +349,12 @@ DO_SCAN(scan_dir)
 			arg = strchr(arg, '\\');
 			arg = strchr(arg, '\\');
 		}
 		}
 
 
-		add_nest_node_ses(ses, arg2, "{%s}{{FILE}{%d}{MODE}{%u}{SIZE}{%u}{TIME}{%lld}}",
+		add_nest_node_ses(ses, arg2, "{%s}{{FILE}{%d}{MODE}{%u}{SIZE}{%lld}{TIME}{%lld}}",
 			arg,
 			arg,
 			!S_ISDIR(info.st_mode),
 			!S_ISDIR(info.st_mode),
 			info.st_mode,
 			info.st_mode,
-			info.st_size,
-			info.st_mtime);
+			(long long) info.st_size,
+			(long long) info.st_mtime);
 
 
 		return ses;
 		return ses;
 	}
 	}
@@ -368,12 +370,12 @@ DO_SCAN(scan_dir)
 			continue;
 			continue;
 		}
 		}
 
 
-		add_nest_node_ses(ses, arg2, "{%s}{{FILE}{%d}{MODE}{%u}{SIZE}{%u}{TIME}{%lld}}",
+		add_nest_node_ses(ses, arg2, "{%s}{{FILE}{%d}{MODE}{%u}{SIZE}{%lld}{TIME}{%lld}}",
 			dirlist[index]->d_name,
 			dirlist[index]->d_name,
 			!S_ISDIR(info.st_mode),
 			!S_ISDIR(info.st_mode),
 			info.st_mode,
 			info.st_mode,
-			info.st_size,
-			info.st_mtime);
+			(long long) info.st_size,
+			(long long) info.st_mtime);
 	}
 	}
 
 
 	for (index = 0 ; index < size ; index++)
 	for (index = 0 ; index < size ; index++)
@@ -403,24 +405,24 @@ DO_SCAN(scan_file)
 	}
 	}
 
 
 	str_rip = str_alloc_stack(str_len(str_out));
 	str_rip = str_alloc_stack(str_len(str_out));
+	str_sub = str_alloc_stack(str_len(str_rip) * 4 + BUFFER_SIZE);
 
 
 	strip_vt102_codes(str_out, str_rip);
 	strip_vt102_codes(str_out, str_rip);
+	substitute(ses, str_rip, str_sub, SUB_SEC);
 
 
 	RESTRING(gtd->cmds[0], str_out);
 	RESTRING(gtd->cmds[0], str_out);
-	RESTRING(gtd->cmds[1], str_rip);
+	RESTRING(gtd->cmds[1], str_sub);
 	RESTRING(gtd->cmds[2], ntos(str_len(str_out)));
 	RESTRING(gtd->cmds[2], ntos(str_len(str_out)));
-	RESTRING(gtd->cmds[3], ntos(strlen(str_rip)));
+	RESTRING(gtd->cmds[3], ntos(strlen(str_sub)));
 	RESTRING(gtd->cmds[4], ntos(cnt));
 	RESTRING(gtd->cmds[4], ntos(cnt));
 
 
 	gtd->cmdc = 5;
 	gtd->cmdc = 5;
 
 
-	str_sub = str_alloc_stack(strlen(arg) * 2);
-
 	substitute(ses, arg2, str_sub, SUB_CMD);
 	substitute(ses, arg2, str_sub, SUB_CMD);
 
 
 	show_message(ses, LIST_COMMAND, "#SCAN FILE: FILE {%s} SCANNED.", arg1);
 	show_message(ses, LIST_COMMAND, "#SCAN FILE: FILE {%s} SCANNED.", arg1);
 
 
-	ses = script_driver(ses, LIST_COMMAND, str_sub);
+	ses = script_driver(ses, LIST_COMMAND, NULL, str_sub);
 
 
 	return ses;
 	return ses;
 }
 }
@@ -465,6 +467,214 @@ DO_SCAN(scan_forward)
 	return ses;
 	return ses;
 }
 }
 
 
+DO_SCAN(scan_json)
+{
+	char *src, *pto, mod[STRING_SIZE];
+	int i, size, state[100], nest, type;
+
+	arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
+
+	if (*arg2 == 0)
+	{
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #SCAN JSON <%s> <VARIABLE>.", arg1);
+
+		return ses;
+	}
+
+	mod[0] = state[0] = nest = type = 0;
+
+	fseek(fp, 0, SEEK_END);
+	size = ftell(fp);
+	fseek(fp, 0, SEEK_SET);
+
+	src = malloc(size + 1);
+
+	fread(src, size, 1, fp);
+
+	src[size] = 0;
+
+	i = 0;
+	pto = mod;
+
+	while (i < size && nest < 99 && nest >= 0)
+	{
+		switch (src[i])
+		{
+			case ' ':
+			case '\t':
+			case '\n':
+			case '\r':
+				i++;
+				break;
+
+			case '{':
+				if (state[nest])
+				{
+					pto += sprintf(pto, "{%d}", state[nest]++);
+				}
+				if (nest != 0)
+				{
+					*pto++ = '{';
+				}
+				i++;
+				state[++nest] = 0;
+				break;
+
+			case '}':
+				nest--;
+				i++;
+				if (nest != 0)
+				{
+					*pto++ = '}';
+				}
+				break;
+
+			case '[':
+				if (nest != 0)
+				{
+					*pto++ = '{';
+				}
+				i++;
+				state[++nest] = 1;
+//				pto += sprintf(pto, "{%d}", state[nest]);
+				break;
+
+			case ']':
+				nest--;
+				i++;
+				if (nest != 0)
+				{
+					*pto++ = '}';
+				}
+				break;
+
+			case ':':
+				i++;
+				break;
+
+			case ',':
+				i++;
+				break;
+
+			case '"':
+				i++;
+				if (state[nest])
+				{
+					pto += sprintf(pto, "{%d}", state[nest]++);
+				}
+				if (nest)
+				{
+					*pto++ = '{';
+				}
+				type = 1;
+
+				while (i < size && type == 1)
+				{
+					switch (src[i])
+					{
+						case '\\':
+							i++;
+
+							if (i < size && src[i] == '"')
+							{
+								*pto++ = src[i++];
+							}
+							else
+							{
+								*pto++ = '\\';
+							}
+							break;
+
+						case '"':
+							i++;
+							type = 0;
+							break;
+
+						case '{':
+							i++;
+							*pto++ = '\\';
+							*pto++ = 'x';
+							*pto++ = '7';
+							*pto++ = 'B';
+							break;
+
+						case '}':
+							i++;
+							*pto++ = '\\';
+							*pto++ = 'x';
+							*pto++ = '7';
+							*pto++ = 'D';
+							break;
+
+						case COMMAND_SEPARATOR:
+							i++;
+							*pto++ = '\\';
+							*pto++ = COMMAND_SEPARATOR;
+							break;
+
+						default:
+							*pto++ = src[i++];
+							break;
+					}
+				}
+
+				if (nest)
+				{
+					*pto++ = '}';
+				}
+				break;
+
+			default:
+				if (state[nest])
+				{
+					pto += sprintf(pto, "{%d}", state[nest]++);
+				}
+				if (nest)
+				{
+					*pto++ = '{';
+				}
+
+				type = 1;
+
+				while (i < size && type == 1)
+				{
+					switch (src[i])
+					{
+						case '}':
+						case ']':
+						case ',':
+						case ':':
+							type = 0;
+							break;
+
+						case ' ':
+							i++;
+							break;
+
+						default:
+							*pto++ = src[i++];
+							break;
+					}
+				}
+
+				if (nest)
+				{
+					*pto++ = '}';
+				}
+				break;
+		}
+	}
+	*pto = 0;
+
+	free(src);
+
+	show_message(ses, LIST_COMMAND, "#SCAN JSON: FILE {%s} SCANNED AND SAVED TO VARIABLE {%s}.", arg1, arg2);
+
+	add_nest_node_ses(ses, arg2, mod);
+
+	return ses;
+}
+
 /* support routines for tab separated value files */
 /* support routines for tab separated value files */
 
 
 char *get_arg_stop_tabs(struct session *ses, char *string, char *result, int flag)
 char *get_arg_stop_tabs(struct session *ses, char *string, char *result, int flag)
@@ -505,7 +715,7 @@ DO_SCAN(scan_tsv)
 		}
 		}
 		else
 		else
 		{
 		{
-		
+
 			arg = strchr(line, '\n');
 			arg = strchr(line, '\n');
 
 
 			if (arg)
 			if (arg)
@@ -581,7 +791,7 @@ DO_SCAN(scan_txt)
 		}
 		}
 		else
 		else
 		{
 		{
-		
+
 			arg = strchr(line, '\n');
 			arg = strchr(line, '\n');
 
 
 			if (arg)
 			if (arg)

+ 8 - 8
src/screen.c

@@ -377,7 +377,7 @@ DO_SCREEN(screen_cursor)
 	else
 	else
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #SCREEN {CURSOR} {HIDE|SHOW|BLINK|STEADY}");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #SCREEN {CURSOR} {HIDE|SHOW|BLINK|STEADY}");
-	}	
+	}
 }
 }
 
 
 DO_SCREEN(screen_clear)
 DO_SCREEN(screen_clear)
@@ -483,9 +483,9 @@ DO_SCREEN(screen_fill)
 			command(ses, do_screen, "CLEAR SPLIT");
 			command(ses, do_screen, "CLEAR SPLIT");
 		}
 		}
 
 
-		if (ses->split->sav_top_row > 0)
+		if (ses->split->top_row > 1)
 		{
 		{
-			if (ses->split->sav_top_row == 1)
+			if (ses->split->top_row == 2)
 			{
 			{
 				command(ses, do_draw, "%s LINE %d %d %d %d", arg2, 1, 1, ses->split->top_row - 1, gtd->screen->cols);
 				command(ses, do_draw, "%s LINE %d %d %d %d", arg2, 1, 1, ses->split->top_row - 1, gtd->screen->cols);
 			}
 			}
@@ -499,9 +499,9 @@ DO_SCREEN(screen_fill)
 
 
 		if (ses->split->sav_bot_row)
 		if (ses->split->sav_bot_row)
 		{
 		{
-			if (ses->split->sav_bot_row - inputline_max_row() >= 0)
+			if (ses->split->bot_row + inputline_max_row() < gtd->screen->rows)
 			{
 			{
-				if (ses->split->sav_bot_row - inputline_max_row() == 0)
+				if (ses->split->bot_row + inputline_max_row() == gtd->screen->rows - 1)
 				{
 				{
 					command(ses, do_draw, "%s LINE %d %d %d %d", arg2, ses->split->bot_row + 1, 1, gtd->screen->rows - inputline_max_row(), gtd->screen->cols);
 					command(ses, do_draw, "%s LINE %d %d %d %d", arg2, ses->split->bot_row + 1, 1, gtd->screen->rows - inputline_max_row(), gtd->screen->cols);
 				}
 				}
@@ -539,7 +539,7 @@ DO_SCREEN(screen_fill)
 				{
 				{
 					if (ses->split->sav_top_row > 1)
 					if (ses->split->sav_top_row > 1)
 					{
 					{
-						command(ses, do_draw, "%s HORIZONTAL TEED TOP RIGHT CORNER %d %d %d %d", arg2, ses->split->top_row - 1, ses->split->bot_col + 1, ses->split->bot_row + 1, ses->split->bot_col + 1);						
+						command(ses, do_draw, "%s HORIZONTAL TEED TOP RIGHT CORNER %d %d %d %d", arg2, ses->split->top_row - 1, ses->split->bot_col + 1, ses->split->bot_row + 1, ses->split->bot_col + 1);
 					}
 					}
 					if (ses->split->sav_bot_row > 1)
 					if (ses->split->sav_bot_row > 1)
 					{
 					{
@@ -618,7 +618,7 @@ DO_SCREEN(screen_get)
 	{
 	{
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {FOCUS} <VAR>");
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {FOCUS} <VAR>");
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {ROWS|COLS|HEIGHT|WIDTH} <VAR>");
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {ROWS|COLS|HEIGHT|WIDTH} <VAR>");
-		
+
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {CHAR_HEIGHT|CHAR_WIDTH}");
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {CHAR_HEIGHT|CHAR_WIDTH}");
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {SPLIT_TOP_BAR|SPLIT_BOT_BAR|SPLIT_LEFT_BAR|SPLIT_RIGHT_BAR} <VAR>");
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {SPLIT_TOP_BAR|SPLIT_BOT_BAR|SPLIT_LEFT_BAR|SPLIT_RIGHT_BAR} <VAR>");
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {SCROLL_TOP_ROW|SCROLL_TOP_COL|SCROLL_BOT_ROW|SCROLL_BOT_COL} <VAR>");
 		tintin_printf2(ses, "#SYNTAX: #SCREEN {GET} {SCROLL_TOP_ROW|SCROLL_TOP_COL|SCROLL_BOT_ROW|SCROLL_BOT_COL} <VAR>");
@@ -1712,7 +1712,7 @@ DO_SCREEN(screen_info)
 		set_nest_node_ses(ses, arg2, "{SCROLLMODE}{%d}", HAS_BIT(gtd->screen->flags, SCREEN_FLAG_SCROLLMODE));
 		set_nest_node_ses(ses, arg2, "{SCROLLMODE}{%d}", HAS_BIT(gtd->screen->flags, SCREEN_FLAG_SCROLLMODE));
 
 
 		show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SCREEN]}");
 		show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SCREEN]}");
-		
+
 		return;
 		return;
 	}
 	}
 	if (*arg1)
 	if (*arg1)

+ 8 - 3
src/session.c

@@ -43,7 +43,7 @@ DO_COMMAND(do_all)
 
 
 			if (!HAS_BIT(sesptr->flags, SES_FLAG_CLOSED))
 			if (!HAS_BIT(sesptr->flags, SES_FLAG_CLOSED))
 			{
 			{
-				script_driver(sesptr, LIST_COMMAND, arg1);
+				script_driver(sesptr, LIST_COMMAND, NULL, arg1);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -161,7 +161,7 @@ DO_COMMAND(do_snoop)
 
 
 	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);
-	
+
 	if (*arg1)
 	if (*arg1)
 	{
 	{
 		sesptr = find_session(arg1);
 		sesptr = find_session(arg1);
@@ -169,7 +169,7 @@ DO_COMMAND(do_snoop)
 		if (sesptr == NULL)
 		if (sesptr == NULL)
 		{
 		{
 			show_error(ses, LIST_COMMAND, "#SNOOP: THERE'S NO SESSION NAMED {%s}.", arg1);
 			show_error(ses, LIST_COMMAND, "#SNOOP: THERE'S NO SESSION NAMED {%s}.", arg1);
-			
+
 			return ses;
 			return ses;
 		}
 		}
 	}
 	}
@@ -775,6 +775,11 @@ void dispose_session(struct session *ses)
 		delete_map(ses);
 		delete_map(ses);
 	}
 	}
 
 
+	for (index = 0 ; index < LIST_MAX ; index++)
+	{
+		kill_list(ses->list[index]);
+	}
+
 	for (index = 0 ; index < LIST_MAX ; index++)
 	for (index = 0 ; index < LIST_MAX ; index++)
 	{
 	{
 		free_list(ses->list[index]);
 		free_list(ses->list[index]);

+ 11 - 8
src/show.c

@@ -61,7 +61,7 @@ DO_COMMAND(do_showme)
 	{
 	{
 		ses->gagline--;
 		ses->gagline--;
 
 
-		show_debug(ses, LIST_GAG, COLOR_DEBUG "#DEBUG GAG " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} " COLOR_COMMAND "[" COLOR_STRING "%d" COLOR_COMMAND "]", arg1, ses->gagline + 1);
+		show_debug(ses, LIST_GAG, NULL, COLOR_DEBUG "#DEBUG GAG " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} " COLOR_COMMAND "[" COLOR_STRING "%d" COLOR_COMMAND "]", arg1, ses->gagline + 1);
 
 
 		return ses;
 		return ses;
 	}
 	}
@@ -272,7 +272,7 @@ void show_error(struct session *ses, int index, char *format, ...)
 	return;
 	return;
 }
 }
 
 
-void show_debug(struct session *ses, int index, char *format, ...)
+void show_debug(struct session *ses, int index, struct listnode *node, char *format, ...)
 {
 {
 	struct listroot *root;
 	struct listroot *root;
 	char *buffer;
 	char *buffer;
@@ -282,10 +282,13 @@ void show_debug(struct session *ses, int index, char *format, ...)
 
 
 	root = ses->list[index];
 	root = ses->list[index];
 
 
-	if (gtd->level->debug == 0 && !HAS_BIT(root->flags, LIST_FLAG_DEBUG) && !HAS_BIT(root->flags, LIST_FLAG_LOG))
+	if (node == NULL || !HAS_BIT(node->flags, NODE_FLAG_DEBUG))
 	{
 	{
-		pop_call();
-		return;
+		if (gtd->level->debug == 0 && !HAS_BIT(root->flags, LIST_FLAG_DEBUG) && !HAS_BIT(root->flags, LIST_FLAG_LOG))
+		{
+			pop_call();
+			return;
+		}
 	}
 	}
 
 
 	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_REFORMAT, 1, 0, "REFORMAT %s", format))
 	if (HAS_BIT(gtd->event_flags, EVENT_FLAG_REFORMAT) && check_all_events(ses, EVENT_FLAG_REFORMAT, 1, 0, "REFORMAT %s", format))
@@ -303,7 +306,7 @@ void show_debug(struct session *ses, int index, char *format, ...)
 	}
 	}
 	va_end(args);
 	va_end(args);
 
 
-	if (gtd->level->debug || HAS_BIT(root->flags, LIST_FLAG_DEBUG))
+	if (gtd->level->debug || HAS_BIT(root->flags, LIST_FLAG_DEBUG) || (node != NULL && HAS_BIT(node->flags, NODE_FLAG_DEBUG)))
 	{
 	{
 		gtd->level->verbose++;
 		gtd->level->verbose++;
 
 
@@ -322,7 +325,7 @@ void show_debug(struct session *ses, int index, char *format, ...)
 		}
 		}
 	}
 	}
 	end:
 	end:
-	
+
 	free(buffer);
 	free(buffer);
 
 
 	pop_call();
 	pop_call();
@@ -589,7 +592,7 @@ void tintin_puts(struct session *ses, char *string)
 
 
 		gtd->level->ignore++;
 		gtd->level->ignore++;
 
 
-		show_debug(ses, LIST_GAG, COLOR_DEBUG "#DEBUG GAG " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} " COLOR_COMMAND "[" COLOR_STRING "%d" COLOR_COMMAND "]", string, ses->gagline + 1);
+		show_debug(ses, LIST_GAG, NULL, COLOR_DEBUG "#DEBUG GAG " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} " COLOR_COMMAND "[" COLOR_STRING "%d" COLOR_COMMAND "]", string, ses->gagline + 1);
 
 
 		gtd->level->ignore--;
 		gtd->level->ignore--;
 	}
 	}

+ 6 - 6
src/sort.c

@@ -218,7 +218,7 @@ void quad_swap32(int *array, int *swap, size_t nmemb, CMPFUNC *cmp)
 
 
 				pta -= 8;
 				pta -= 8;
 
 
-				*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; 
+				*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++;
 
 
 				pta += 8;
 				pta += 8;
 
 
@@ -226,7 +226,7 @@ void quad_swap32(int *array, int *swap, size_t nmemb, CMPFUNC *cmp)
 
 
 				pta -= 8;
 				pta -= 8;
 
 
-				*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; 
+				*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++;
 
 
 				pta += 4;
 				pta += 4;
 
 
@@ -238,7 +238,7 @@ void quad_swap32(int *array, int *swap, size_t nmemb, CMPFUNC *cmp)
 
 
 			pta -= 8;
 			pta -= 8;
 
 
-			*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; 
+			*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++;
 
 
 			pta += 4;
 			pta += 4;
 		}
 		}
@@ -562,7 +562,7 @@ void quad_swap64(long long *array, long long *swap, size_t nmemb, CMPFUNC *cmp)
 
 
 				pta -= 8;
 				pta -= 8;
 
 
-				*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; 
+				*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++;
 
 
 				pta += 8;
 				pta += 8;
 
 
@@ -570,7 +570,7 @@ void quad_swap64(long long *array, long long *swap, size_t nmemb, CMPFUNC *cmp)
 
 
 				pta -= 8;
 				pta -= 8;
 
 
-				*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; 
+				*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++;
 
 
 				pta += 4;
 				pta += 4;
 
 
@@ -582,7 +582,7 @@ void quad_swap64(long long *array, long long *swap, size_t nmemb, CMPFUNC *cmp)
 
 
 			pta -= 8;
 			pta -= 8;
 
 
-			*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; 
+			*pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++; *pts++ = *pta++;
 
 
 			pta += 4;
 			pta += 4;
 		}
 		}

+ 4 - 4
src/split.c

@@ -68,7 +68,7 @@ DO_COMMAND(do_split)
 	if (*arg)
 	if (*arg)
 	{
 	{
 		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);
-		
+
 		input = get_number(ses, arg1);
 		input = get_number(ses, arg1);
 
 
 		input *= -1;
 		input *= -1;
@@ -331,8 +331,8 @@ void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 	{
 	{
 		snprintf(buf1, BUFFER_SIZE, "%.*s", raw_len_str(ses, prompt, 0, gtd->screen->cols - col), prompt);
 		snprintf(buf1, BUFFER_SIZE, "%.*s", raw_len_str(ses, prompt, 0, gtd->screen->cols - col), prompt);
 
 
-		show_debug(ses, LIST_PROMPT, "#DEBUG PROMPT {%s}", prompt);
-		show_debug(ses, LIST_PROMPT, "#PROMPT WIDTH %d WITH OFFSET %d LONGER THAN ROW SIZE %d.", width, col, gtd->screen->cols);
+		show_debug(ses, LIST_PROMPT, NULL, "#DEBUG PROMPT {%s}", prompt);
+		show_debug(ses, LIST_PROMPT, NULL, "#PROMPT WIDTH %d WITH OFFSET %d LONGER THAN ROW SIZE %d.", width, col, gtd->screen->cols);
 	}
 	}
 
 
 	save_pos(ses);
 	save_pos(ses);
@@ -358,7 +358,7 @@ void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 		{
 		{
 			erase_cols(gtd->screen->cols);
 			erase_cols(gtd->screen->cols);
 		}
 		}
-	
+
 		print_stdout(0, 0, "%s", buf1);
 		print_stdout(0, 0, "%s", buf1);
 	}
 	}
 
 

+ 16 - 12
src/ssl.c

@@ -59,7 +59,7 @@ gnutls_session_t ssl_negotiate(struct session *ses)
 	gnutls_session_t ssl_ses;
 	gnutls_session_t ssl_ses;
 
 
 	int ret;
 	int ret;
-	
+
 	if (!ssl_cred)
 	if (!ssl_cred)
 	{
 	{
 		gnutls_global_init();
 		gnutls_global_init();
@@ -72,7 +72,7 @@ gnutls_session_t ssl_negotiate(struct session *ses)
 	gnutls_transport_set_ptr(ssl_ses, (gnutls_transport_ptr_t) (long int) ses->socket);
 	gnutls_transport_set_ptr(ssl_ses, (gnutls_transport_ptr_t) (long int) ses->socket);
 	gnutls_server_name_set(ssl_ses, GNUTLS_NAME_DNS, ses->session_host, strlen(ses->session_host));
 	gnutls_server_name_set(ssl_ses, GNUTLS_NAME_DNS, ses->session_host, strlen(ses->session_host));
 
 
-	do 
+	do
 	{
 	{
 		ret = gnutls_handshake(ssl_ses);
 		ret = gnutls_handshake(ssl_ses);
 	}
 	}
@@ -137,7 +137,7 @@ static void load_cert(struct session *ses, gnutls_x509_crt_t *cert)
 	char cert_file[STRING_SIZE];
 	char cert_file[STRING_SIZE];
 	FILE *fp;
 	FILE *fp;
 	gnutls_datum_t bptr;
 	gnutls_datum_t bptr;
-	
+
 	if (!get_cert_file(ses, cert_file))
 	if (!get_cert_file(ses, cert_file))
 	{
 	{
 		return;
 		return;
@@ -152,7 +152,7 @@ static void load_cert(struct session *ses, gnutls_x509_crt_t *cert)
 	bptr.data = (unsigned char *) cert_file;
 	bptr.data = (unsigned char *) cert_file;
 
 
 	fclose(fp);
 	fclose(fp);
-	
+
 	gnutls_x509_crt_init(cert);
 	gnutls_x509_crt_init(cert);
 
 
 	if (gnutls_x509_crt_import(*cert, &bptr, GNUTLS_X509_FMT_PEM))
 	if (gnutls_x509_crt_import(*cert, &bptr, GNUTLS_X509_FMT_PEM))
@@ -168,7 +168,7 @@ static void save_cert(struct session *ses, gnutls_x509_crt_t cert, int new)
 	char filename[BUFFER_SIZE], buf[STRING_SIZE];
 	char filename[BUFFER_SIZE], buf[STRING_SIZE];
 	FILE *fp;
 	FILE *fp;
 	size_t len;
 	size_t len;
-	
+
 	len = STRING_SIZE;
 	len = STRING_SIZE;
 
 
 	if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, buf, &len))
 	if (gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, buf, &len))
@@ -233,7 +233,7 @@ static int diff_certs(gnutls_x509_crt_t c1, gnutls_x509_crt_t c2)
 {
 {
 	char buf1[STRING_SIZE], buf2[STRING_SIZE];
 	char buf1[STRING_SIZE], buf2[STRING_SIZE];
 	size_t len1, len2;
 	size_t len1, len2;
-	
+
 	len1 = len2 = STRING_SIZE;
 	len1 = len2 = STRING_SIZE;
 
 
 	if (gnutls_x509_crt_export(c1, GNUTLS_X509_FMT_DER, buf1, &len1))
 	if (gnutls_x509_crt_export(c1, GNUTLS_X509_FMT_DER, buf1, &len1))
@@ -262,7 +262,7 @@ static int ssl_check_cert(struct session *ses, gnutls_session_t ssl_ses)
 	gnutls_x509_crt_t cert, oldcert;
 	gnutls_x509_crt_t cert, oldcert;
 	const gnutls_datum_t *cert_list;
 	const gnutls_datum_t *cert_list;
 	unsigned int cert_list_size;
 	unsigned int cert_list_size;
-	char *err = 0;
+	char *err = NULL;
 
 
 	oldcert = 0;
 	oldcert = 0;
 
 
@@ -273,13 +273,13 @@ static int ssl_check_cert(struct session *ses, gnutls_session_t ssl_ses)
 		err = "#SSL: SERVER DOES NOT USE x509 -> NO KEY RETENTION.";
 		err = "#SSL: SERVER DOES NOT USE x509 -> NO KEY RETENTION.";
 		goto nocert;
 		goto nocert;
 	}
 	}
-	
+
 	if ((cert_list = gnutls_certificate_get_peers(ssl_ses, &cert_list_size)) == NULL)
 	if ((cert_list = gnutls_certificate_get_peers(ssl_ses, &cert_list_size)) == NULL)
 	{
 	{
 		err = "#SSL: SERVER HAS NO x509 CERTIFICATE -> NO KEY RETENTION.";
 		err = "#SSL: SERVER HAS NO x509 CERTIFICATE -> NO KEY RETENTION.";
 		goto nocert;
 		goto nocert;
 	}
 	}
-	
+
 	gnutls_x509_crt_init(&cert);
 	gnutls_x509_crt_init(&cert);
 
 
 	if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
 	if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
@@ -296,7 +296,7 @@ static int ssl_check_cert(struct session *ses, gnutls_session_t ssl_ses)
 
 
 		err = buf2;
 		err = buf2;
 	}
 	}
-	
+
 	if (gnutls_x509_crt_get_expiration_time(cert) < t)
 	if (gnutls_x509_crt_get_expiration_time(cert) < t)
 	{
 	{
 		sprintf(buf2, "CERTIFICATE HAS EXPIRED (%s)", str_time(ses, "%c", gnutls_x509_crt_get_expiration_time(cert)));
 		sprintf(buf2, "CERTIFICATE HAS EXPIRED (%s)", str_time(ses, "%c", gnutls_x509_crt_get_expiration_time(cert)));
@@ -316,7 +316,11 @@ static int ssl_check_cert(struct session *ses, gnutls_session_t ssl_ses)
 		{
 		{
 			if (err)
 			if (err)
 			{
 			{
-				sprintf(buf2, "CERTIFICATE MISMATCH, AND NEW %s", err);
+				char temp[BUFFER_SIZE];
+
+				snprintf(temp, BUFFER_SIZE - 1, "CERTIFICATE MISMATCH, AND NEW %s", err);
+
+				strcpy(buf2, temp);
 			}
 			}
 			else
 			else
 			{
 			{
@@ -351,7 +355,7 @@ static int ssl_check_cert(struct session *ses, gnutls_session_t ssl_ses)
 
 
 badcert:
 badcert:
 	gnutls_x509_crt_deinit(cert);
 	gnutls_x509_crt_deinit(cert);
-	
+
 nocert:
 nocert:
 	if (oldcert)
 	if (oldcert)
 	{
 	{

+ 3 - 3
src/string.c

@@ -169,7 +169,7 @@ int raw_len_str(struct session *ses, char *str, int start, int end)
 			continue;
 			continue;
 		}
 		}
 		else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
 		else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
-		{ 
+		{
 			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 
 
 			if (str_cnt >= start)
 			if (str_cnt >= start)
@@ -228,7 +228,7 @@ int raw_len_str_min(struct session *ses, char *str, int start, int end)
 			continue;
 			continue;
 		}
 		}
 		else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
 		else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
-		{    
+		{
 			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 
 
 			if (str_cnt >= start)
 			if (str_cnt >= start)
@@ -287,7 +287,7 @@ int raw_len_str_opt(struct session *ses, char *str, int start, int end)
 		}
 		}
 
 
 		if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
 		if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
-		{    
+		{
 			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 
 
 			if (str_cnt >= start)
 			if (str_cnt >= start)

+ 7 - 7
src/substitute.c

@@ -937,7 +937,7 @@ int color_gradient(char *pti, int min, int max)
 						}
 						}
 						lvl++;
 						lvl++;
 					}
 					}
-					
+
 					if (buf[1] > 'a' && pti[6] < buf[1])
 					if (buf[1] > 'a' && pti[6] < buf[1])
 					{
 					{
 						buf[1]--;
 						buf[1]--;
@@ -1004,7 +1004,7 @@ int color_gradient(char *pti, int min, int max)
 						}
 						}
 						lvl++;
 						lvl++;
 					}
 					}
-					
+
 					if (pti[6] < buf[1])
 					if (pti[6] < buf[1])
 					{
 					{
 						buf[1]--;
 						buf[1]--;
@@ -1193,7 +1193,7 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 					{
 					{
 						substitute(ses, temp, buf, flags_neol);
 						substitute(ses, temp, buf, flags_neol);
 					}
 					}
-					show_debug(ses, LIST_FUNCTION, COLOR_DEBUG "#DEBUG FUNCTION " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+					show_debug(ses, LIST_FUNCTION, node, COLOR_DEBUG "#DEBUG FUNCTION " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
 
 
 					RESTRING(gtd->vars[0], buf);
 					RESTRING(gtd->vars[0], buf);
 
 
@@ -1228,7 +1228,7 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 						delete_node_list(ses, LIST_FUNCTION, node);
 						delete_node_list(ses, LIST_FUNCTION, node);
 					}
 					}
 
 
-					script_driver(ses, LIST_FUNCTION, buf);
+					script_driver(ses, LIST_FUNCTION, node, buf);
 
 
 					node = search_nest_node_ses(ses, "result");
 					node = search_nest_node_ses(ses, "result");
 
 
@@ -1823,7 +1823,7 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 						else if (pti[1] >= 'a' && pti[1] <= 'f' && pti[2] >= 'a' && pti[2] <= 'f' && pti[3] >= 'a' && pti[3] <= 'f' && pti[4] == '>')
 						else if (pti[1] >= 'a' && pti[1] <= 'f' && pti[2] >= 'a' && pti[2] <= 'f' && pti[3] >= 'a' && pti[3] <= 'f' && pti[4] == '>')
 						{
 						{
 							cnt = 16 + (pti[1] - 'a') * 36 + (pti[2] - 'a') * 6 + (pti[3] - 'a');
 							cnt = 16 + (pti[1] - 'a') * 36 + (pti[2] - 'a') * 6 + (pti[3] - 'a');
-							
+
 							if (ses->color >= 256)
 							if (ses->color >= 256)
 							{
 							{
 								pto += sprintf(pto, "\e[22;38;5;%dm", cnt);
 								pto += sprintf(pto, "\e[22;38;5;%dm", cnt);
@@ -2234,7 +2234,7 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 				{
 				{
 					*pto++ = *pti++;
 					*pto++ = *pti++;
 				}
 				}
-				break;	
+				break;
 
 
 			default:
 			default:
 				*pto++ = *pti++;
 				*pto++ = *pti++;
@@ -2516,7 +2516,7 @@ int get_color_names(struct session *ses, char *string, char *result)
 				result += substitute(ses, result, result, SUB_COL);
 				result += substitute(ses, result, result, SUB_COL);
 
 
 				continue;
 				continue;
-			
+
 			case '\\':
 			case '\\':
 				skip = find_escaped_color_code(string);
 				skip = find_escaped_color_code(string);
 
 

+ 12 - 6
src/system.c

@@ -33,7 +33,7 @@
 #include <util.h>
 #include <util.h>
 #endif
 #endif
 #endif
 #endif
-#include <fcntl.h>  
+#include <fcntl.h>
 #include <dirent.h>
 #include <dirent.h>
 #include <termios.h>
 #include <termios.h>
 #include <sys/un.h>
 #include <sys/un.h>
@@ -55,7 +55,7 @@ DO_COMMAND(do_run)
 	if (*arg1 == 0 || *arg2 == 0)
 	if (*arg1 == 0 || *arg2 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #RUN <NAME> <SHELL COMMAND>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #RUN <NAME> <SHELL COMMAND>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -121,7 +121,7 @@ DO_COMMAND(do_script)
 					*cptr = 0;
 					*cptr = 0;
 				}
 				}
 
 
-				ses = script_driver(ses, LIST_COMMAND, buf);
+				ses = script_driver(ses, LIST_COMMAND, NULL, buf);
 			}
 			}
 
 
 			pclose(script);
 			pclose(script);
@@ -170,6 +170,12 @@ DO_COMMAND(do_script)
 
 
 DO_COMMAND(do_suspend)
 DO_COMMAND(do_suspend)
 {
 {
+	if (!strcmp(gtd->system->os, "WINTIN++"))
+	{
+		show_error(gtd->ses, LIST_COMMAND, "#ERROR: #SUSPEND / ctrl-z is not supported for WinTin++.");
+
+		return ses;
+	}
 	print_stdout(0, 0, "\e[?1049l\e[r\e[%d;%dH", gtd->screen->rows, 1);
 	print_stdout(0, 0, "\e[?1049l\e[r\e[%d;%dH", gtd->screen->rows, 1);
 
 
 	fflush(NULL);
 	fflush(NULL);
@@ -203,7 +209,7 @@ DO_COMMAND(do_system)
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #SYSTEM {SHELL COMMAND}");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #SYSTEM {SHELL COMMAND}");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -281,7 +287,7 @@ DO_COMMAND(do_system)
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #SYSTEM <COMMAND>");
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #SYSTEM <COMMAND>");
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 
@@ -321,7 +327,7 @@ DO_COMMAND(do_textin)
 	if ((fp = fopen(arg1, "r")) == NULL)
 	if ((fp = fopen(arg1, "r")) == NULL)
 	{
 	{
 		show_error(ses, LIST_COMMAND, "#ERROR: #TEXTIN {%s}: FILE NOT FOUND.", arg1);
 		show_error(ses, LIST_COMMAND, "#ERROR: #TEXTIN {%s}: FILE NOT FOUND.", arg1);
-		
+
 		return ses;
 		return ses;
 	}
 	}
 
 

+ 33 - 30
src/tables.c

@@ -213,7 +213,7 @@ char character_table[256] =
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
 
 
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA, // 104 h
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA, // 104 h
-	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA, 
+	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
 	CHAR_FLAG_PRINT|CHAR_FLAG_VAR|CHAR_FLAG_CSI|CHAR_FLAG_ALPHA,
@@ -384,7 +384,7 @@ char character_table[256] =
 	CHAR_FLAG_PRINT
 	CHAR_FLAG_PRINT
 };
 };
 
 
-	
+
 struct color_type color_table[] =
 struct color_type color_table[] =
 {
 {
 	{    "azure",         "<abd>",  5 },
 	{    "azure",         "<abd>",  5 },
@@ -693,8 +693,8 @@ struct cursor_type cursor_table[] =
 	{     "ESCAPE ENTER",       "Process multi-line input.",                      "\e[13;5u",    CURSOR_FLAG_GET_ALL,     cursor_escape_enter,          ""          },
 	{     "ESCAPE ENTER",       "Process multi-line input.",                      "\e[13;5u",    CURSOR_FLAG_GET_ALL,     cursor_escape_enter,          ""          },
 	{     "SUSPEND",            "Suspend program, return with fg",                "",           CURSOR_FLAG_GET_ALL,     cursor_suspend,               ""          },
 	{     "SUSPEND",            "Suspend program, return with fg",                "",           CURSOR_FLAG_GET_ALL,     cursor_suspend,               ""          },
 	{     "TAB",                "<LIST|SCROLLBACK> <BACKWARD|FORWARD>",           "",            CURSOR_FLAG_GET_ONE,     cursor_tab,                   ""          },
 	{     "TAB",                "<LIST|SCROLLBACK> <BACKWARD|FORWARD>",           "",            CURSOR_FLAG_GET_ONE,     cursor_tab,                   ""          },
-	{     "TAB L S BACKWARD",   "",                                               "\e[Z",        CURSOR_FLAG_GET_ALL,     cursor_tab,                   "L S B"     }, // shift tab
-	{     "TAB L S FORWARD",    "",                                               "\t",          CURSOR_FLAG_GET_ALL,     cursor_tab,                   "L S F"     },
+	{     "TAB L S BACKWARD",   "",                                               "\e[Z",        CURSOR_FLAG_GET_ALL,     cursor_tab,                   "L I S B"   }, // shift tab
+	{     "TAB L S FORWARD",    "",                                               "\t",          CURSOR_FLAG_GET_ALL,     cursor_tab,                   "L I S F"   },
 	{     "UP",                 "Move cursor up",                                 "\e[A",        CURSOR_FLAG_GET_ALL,     cursor_move_up,               ""          },
 	{     "UP",                 "Move cursor up",                                 "\e[A",        CURSOR_FLAG_GET_ALL,     cursor_move_up,               ""          },
 	{     "",                   "",                                               "\e[6~",                          0,    cursor_buffer_down,           ""          },
 	{     "",                   "",                                               "\e[6~",                          0,    cursor_buffer_down,           ""          },
 	{     "",                   "",                                               "\e[1;5F",                        0,    cursor_buffer_end,            ""          },
 	{     "",                   "",                                               "\e[1;5F",                        0,    cursor_buffer_end,            ""          },
@@ -770,7 +770,7 @@ struct timer_type timer_table[] =
 
 
 struct event_type event_table[] =
 struct event_type event_table[] =
 {
 {
-	{    "BUFFER UPDATE",                          0, EVENT_FLAG_UPDATE,   "UPDATE",    "scrollback buffer update"   },	
+	{    "BUFFER UPDATE",                          0, EVENT_FLAG_UPDATE,   "UPDATE",    "scrollback buffer update"   },
 	{    "CATCH ",                                 0, EVENT_FLAG_CATCH,    "CATCH",     "prefix for catch events"    },
 	{    "CATCH ",                                 0, EVENT_FLAG_CATCH,    "CATCH",     "prefix for catch events"    },
 	{    "CHAT MESSAGE",                           0, EVENT_FLAG_PORT,     "PORT",      "any chat related message"   },
 	{    "CHAT MESSAGE",                           0, EVENT_FLAG_PORT,     "PORT",      "any chat related message"   },
 	{    "CLASS ACTIVATED",                        0, EVENT_FLAG_CLASS,    "CLASS",     "class activations"          },
 	{    "CLASS ACTIVATED",                        0, EVENT_FLAG_CLASS,    "CLASS",     "class activations"          },
@@ -786,7 +786,9 @@ struct event_type event_table[] =
 	{    "DISPLAY UPDATE",                         0, EVENT_FLAG_UPDATE,   "UPDATE",    "when display is updated"    },
 	{    "DISPLAY UPDATE",                         0, EVENT_FLAG_UPDATE,   "UPDATE",    "when display is updated"    },
 	{    "DOUBLE-CLICKED ",                        0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is double-clicked"    },
 	{    "DOUBLE-CLICKED ",                        0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is double-clicked"    },
 	{    "EDIT FINISHED",                          0, EVENT_FLAG_INPUT,    "INPUT",     "when editing is finished"   },
 	{    "EDIT FINISHED",                          0, EVENT_FLAG_INPUT,    "INPUT",     "when editing is finished"   },
+	{    "EDIT RESUMED",                           0, EVENT_FLAG_INPUT,    "INPUT",     "when editing is resumed"    },
 	{    "EDIT STARTED",                           0, EVENT_FLAG_INPUT,    "INPUT",     "when editing is started"    },
 	{    "EDIT STARTED",                           0, EVENT_FLAG_INPUT,    "INPUT",     "when editing is started"    },
+	{    "EDIT SUSPENDED",                         0, EVENT_FLAG_INPUT,    "INPUT",     "when editing is suspended"  },
 	{    "END OF PATH",                            0, EVENT_FLAG_MAP,      "MAP",       "walking the last room"      },
 	{    "END OF PATH",                            0, EVENT_FLAG_MAP,      "MAP",       "walking the last room"      },
 	{    "END OF RUN",                             0, EVENT_FLAG_MAP,      "MAP",       "running the last room"      },
 	{    "END OF RUN",                             0, EVENT_FLAG_MAP,      "MAP",       "running the last room"      },
 	{    "GAG ",                                   0, EVENT_FLAG_GAG,      "GAG",       "prefix for gag events"      },
 	{    "GAG ",                                   0, EVENT_FLAG_GAG,      "GAG",       "prefix for gag events"      },
@@ -806,7 +808,7 @@ struct event_type event_table[] =
 	{    "MAP FOLLOW MAP",                         0, EVENT_FLAG_MAP,      "MAP",       "moving to a map room"       },
 	{    "MAP FOLLOW MAP",                         0, EVENT_FLAG_MAP,      "MAP",       "moving to a map room"       },
 	{    "MAP LOCATION",                           0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map click"               },
 	{    "MAP LOCATION",                           0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map click"               },
 	{    "MAP LONG-CLICKED ",                      0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map click"               },
 	{    "MAP LONG-CLICKED ",                      0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map click"               },
-	{    "MAP MOUSE LOCATION",                     0, EVENT_FLAG_MOUSE,    "MOUSE",     "called by #screen raise"    }, 
+	{    "MAP MOUSE LOCATION",                     0, EVENT_FLAG_MOUSE,    "MOUSE",     "called by #screen raise"    },
 	{    "MAP MOVED ",                             0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map mouse move"          },
 	{    "MAP MOVED ",                             0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map mouse move"          },
 	{    "MAP PRESSED ",                           0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map click"               },
 	{    "MAP PRESSED ",                           0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map click"               },
 	{    "MAP REGION ",                            0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map mouse events"        },
 	{    "MAP REGION ",                            0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map mouse events"        },
@@ -817,6 +819,7 @@ struct event_type event_table[] =
 	{    "MAP TRIPLE-CLICKED ",                    0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map click"               },
 	{    "MAP TRIPLE-CLICKED ",                    0, EVENT_FLAG_MOUSE,    "MOUSE",     "vt map click"               },
 	{    "MAP UPDATED VTMAP",                      0, EVENT_FLAG_MAP,      "MAP",       "vt map update"              },
 	{    "MAP UPDATED VTMAP",                      0, EVENT_FLAG_MAP,      "MAP",       "vt map update"              },
 	{    "MINUTE",                                 0, EVENT_FLAG_TIME,     "TIME",      "minute or given minute"     },
 	{    "MINUTE",                                 0, EVENT_FLAG_TIME,     "TIME",      "minute or given minute"     },
+	{    "MODIFIED INPUT",                         0, EVENT_FLAG_INPUT,    "INPUT",     "input line was modified"    },
 	{    "MONTH",                                  0, EVENT_FLAG_TIME,     "TIME",      "month or given month"       },
 	{    "MONTH",                                  0, EVENT_FLAG_TIME,     "TIME",      "month or given month"       },
 	{    "MOVED ",                                 0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is moved"             },
 	{    "MOVED ",                                 0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is moved"             },
 	{    "NO SESSION ACTIVE",                      0, EVENT_FLAG_INPUT,    "INPUT",     "input on startup session"   },
 	{    "NO SESSION ACTIVE",                      0, EVENT_FLAG_INPUT,    "INPUT",     "input on startup session"   },
@@ -1439,31 +1442,31 @@ struct map_legend_type map_legend_table[] =
 
 
         { "NO DIAGONAL",        "UNICODE GRAPHICS",     "2x5",  "2x5"   },
         { "NO DIAGONAL",        "UNICODE GRAPHICS",     "2x5",  "2x5"   },
 	{ "SE",                 "UNICODE GRAPHICS",     "⸌",    "2x5"   },
 	{ "SE",                 "UNICODE GRAPHICS",     "⸌",    "2x5"   },
-	{ "NE",                 "UNICODE GRAPHICS",     "⸝",    "2x5"   }, 
-	{ "SE NE",              "UNICODE GRAPHICS",     ">",    "2x5"   }, 
-	{ "SW",                 "UNICODE GRAPHICS",     "⸍",    "2x5"   }, 
-	{ "SE SW",              "UNICODE GRAPHICS",     "⸌⸍",   "2x5"   }, 
-	{ "NE SW",              "UNICODE GRAPHICS",     "/",   "2x5"   }, 
-	{ "SE NE SW",           "UNICODE GRAPHICS",     ">⸍",   "2x5"   }, 
-	{ "NW",                 "UNICODE GRAPHICS",     "⸜",    "2x5"   }, 
-	{ "SE NW",              "UNICODE GRAPHICS",     "\",   "2x5"   }, 
-	{ "NE NW",              "UNICODE GRAPHICS",     "⸝⸜",   "2x5"   }, 
-	{ "SE NE NW",           "UNICODE GRAPHICS",     ">⸜",   "2x5"   }, 
+	{ "NE",                 "UNICODE GRAPHICS",     "⸝",    "2x5"   },
+	{ "SE NE",              "UNICODE GRAPHICS",     ">",    "2x5"   },
+	{ "SW",                 "UNICODE GRAPHICS",     "⸍",    "2x5"   },
+	{ "SE SW",              "UNICODE GRAPHICS",     "⸌⸍",   "2x5"   },
+	{ "NE SW",              "UNICODE GRAPHICS",     "/",   "2x5"   },
+	{ "SE NE SW",           "UNICODE GRAPHICS",     ">⸍",   "2x5"   },
+	{ "NW",                 "UNICODE GRAPHICS",     "⸜",    "2x5"   },
+	{ "SE NW",              "UNICODE GRAPHICS",     "\",   "2x5"   },
+	{ "NE NW",              "UNICODE GRAPHICS",     "⸝⸜",   "2x5"   },
+	{ "SE NE NW",           "UNICODE GRAPHICS",     ">⸜",   "2x5"   },
 	{ "SW NW",              "UNICODE GRAPHICS",     "<",    "2x5"   },
 	{ "SW NW",              "UNICODE GRAPHICS",     "<",    "2x5"   },
-	{ "SE SW NW",           "UNICODE GRAPHICS",     "⸌<",   "2x5"   }, 
-	{ "NE SW NW",           "UNICODE GRAPHICS",     "⸝<",   "2x5"   }, 
-	{ "SE NE SW NW",        "UNICODE GRAPHICS",     "><",   "2x5"   }, 
-	{ "D",                  "UNICODE GRAPHICS",     "-",    "2x5"   }, 
-	{ "N",                  "UNICODE GRAPHICS",     "↑",    "2x5"   }, 
-	{ "S",                  "UNICODE GRAPHICS",     "↓",    "2x5"   }, 
-	{ "N S",                "UNICODE GRAPHICS",     "│",    "2x5"   }, 
-	{ "U",                  "UNICODE GRAPHICS",     "+",    "2x5"   }, 
-	{ "E",                  "UNICODE GRAPHICS",     "🠆",    "2x5"   }, 
-	{ "W",                  "UNICODE GRAPHICS",     "🠄",    "2x5"   }, 
-	{ "E W",                "UNICODE GRAPHICS",     "─",    "2x5"   }, 
-	{ "ROOM L",             "UNICODE GRAPHICS",     "[",    "2x5"   }, 
-	{ "ROOM L CURVED",      "UNICODE GRAPHICS",     "(",    "2x5"   }, 
-	{ "ROOM R",             "UNICODE GRAPHICS",     "]",    "2x5"   }, 
+	{ "SE SW NW",           "UNICODE GRAPHICS",     "⸌<",   "2x5"   },
+	{ "NE SW NW",           "UNICODE GRAPHICS",     "⸝<",   "2x5"   },
+	{ "SE NE SW NW",        "UNICODE GRAPHICS",     "><",   "2x5"   },
+	{ "D",                  "UNICODE GRAPHICS",     "-",    "2x5"   },
+	{ "N",                  "UNICODE GRAPHICS",     "↑",    "2x5"   },
+	{ "S",                  "UNICODE GRAPHICS",     "↓",    "2x5"   },
+	{ "N S",                "UNICODE GRAPHICS",     "│",    "2x5"   },
+	{ "U",                  "UNICODE GRAPHICS",     "+",    "2x5"   },
+	{ "E",                  "UNICODE GRAPHICS",     "🠆",    "2x5"   },
+	{ "W",                  "UNICODE GRAPHICS",     "🠄",    "2x5"   },
+	{ "E W",                "UNICODE GRAPHICS",     "─",    "2x5"   },
+	{ "ROOM L",             "UNICODE GRAPHICS",     "[",    "2x5"   },
+	{ "ROOM L CURVED",      "UNICODE GRAPHICS",     "(",    "2x5"   },
+	{ "ROOM R",             "UNICODE GRAPHICS",     "]",    "2x5"   },
 	{ "ROOM R CURVED",      "UNICODE GRAPHICS",     ")",    "2x5"   },
 	{ "ROOM R CURVED",      "UNICODE GRAPHICS",     ")",    "2x5"   },
 
 
 	{ NULL,			NULL,			NULL,	NULL	}
 	{ NULL,			NULL,			NULL,	NULL	}

+ 7 - 7
src/telopt_client.c

@@ -125,7 +125,7 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 
 
 	if (cplen == 0)
 	if (cplen == 0)
 	{
 	{
-		gtd->mud_output_buf[gtd->mud_output_len] = 0;	
+		gtd->mud_output_buf[gtd->mud_output_len] = 0;
 
 
 		pop_call();
 		pop_call();
 		return 0;
 		return 0;
@@ -251,13 +251,13 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 			{
 			{
 				switch(cpsrc[1])
 				switch(cpsrc[1])
 				{
 				{
-					case NOP:   
+					case NOP:
 					case DM:
 					case DM:
-					case BREAK: 
-					case IP:    
-					case AO:    
-					case AYT:   
-					case EC:    
+					case BREAK:
+					case IP:
+					case AO:
+					case AYT:
+					case EC:
 					case EL:
 					case EL:
 					case IAC:
 					case IAC:
 					case GA:
 					case GA:

+ 1 - 1
src/telopt_server.c

@@ -560,7 +560,7 @@ int process_sb_ttype_is(struct session *ses, struct port_data *buddy, unsigned c
 	{
 	{
 		switch (src[i])
 		switch (src[i])
 		{
 		{
-			default:			
+			default:
 				*pto++ = src[i];
 				*pto++ = src[i];
 				break;
 				break;
 
 

+ 1 - 1
src/terminal.c

@@ -94,7 +94,7 @@ void reset_terminal(struct session *ses)
 	{
 	{
 		return;
 		return;
 	}
 	}
-	
+
 	if (gtd->detach_port == 0)
 	if (gtd->detach_port == 0)
 	{
 	{
 		if (tcsetattr(0, TCSANOW, &gtd->old_terminal))
 		if (tcsetattr(0, TCSANOW, &gtd->old_terminal))

+ 9 - 6
src/tintin.h

@@ -26,7 +26,7 @@
 *                       modified by Bill Reiss 1993                           *
 *                       modified by Bill Reiss 1993                           *
 *                    recoded by Igor van den Hoven 2004                       *
 *                    recoded by Igor van den Hoven 2004                       *
 ******************************************************************************/
 ******************************************************************************/
-	
+
 #include <stdio.h>
 #include <stdio.h>
 #include <zlib.h>
 #include <zlib.h>
 #include <ctype.h>
 #include <ctype.h>
@@ -212,7 +212,7 @@
 
 
 
 
 #define CLIENT_NAME              "TinTin++"
 #define CLIENT_NAME              "TinTin++"
-#define CLIENT_VERSION           "2.02.50b"
+#define CLIENT_VERSION           "2.02.51 "
 
 
 
 
 #define XT_E                            0x27
 #define XT_E                            0x27
@@ -253,7 +253,7 @@
 #define COLOR_TEXT          "\e[0m"        // "<088>" // reset
 #define COLOR_TEXT          "\e[0m"        // "<088>" // reset
 #define COLOR_TINTIN        "\e[38;5;184m" // "<eea>" // yellow
 #define COLOR_TINTIN        "\e[38;5;184m" // "<eea>" // yellow
 #define COLOR_REPEAT        "\e[38;5;33m"  // "<acf>" // azure
 #define COLOR_REPEAT        "\e[38;5;33m"  // "<acf>" // azure
-#define COLOR_HELP_DIM      "\e[22;37m" 
+#define COLOR_HELP_DIM      "\e[22;37m"
 #define COLOR_HELP_BOLD     "\e[1;37m"
 #define COLOR_HELP_BOLD     "\e[1;37m"
 #define COLOR_HELP_TITLE    "\e[1;32m"
 #define COLOR_HELP_TITLE    "\e[1;32m"
 #define COLOR_HELP_TABLE    "\e[22;36m"
 #define COLOR_HELP_TABLE    "\e[22;36m"
@@ -603,6 +603,7 @@ enum operators
 #define TAB_FLAG_DICTIONARY           BV05
 #define TAB_FLAG_DICTIONARY           BV05
 #define TAB_FLAG_LIST                 BV06
 #define TAB_FLAG_LIST                 BV06
 #define TAB_FLAG_SCROLLBACK           BV07
 #define TAB_FLAG_SCROLLBACK           BV07
+#define TAB_FLAG_INPUT                BV08
 
 
 #define REGEX_FLAG_NONE                  0
 #define REGEX_FLAG_NONE                  0
 #define REGEX_FLAG_FIX                BV01
 #define REGEX_FLAG_FIX                BV01
@@ -698,6 +699,7 @@ enum operators
 
 
 #define NODE_FLAG_COLOR               BV01
 #define NODE_FLAG_COLOR               BV01
 #define NODE_FLAG_MULTI               BV02
 #define NODE_FLAG_MULTI               BV02
+#define NODE_FLAG_DEBUG               BV03
 
 
 #define LOG_FLAG_NONE                    0
 #define LOG_FLAG_NONE                    0
 #define LOG_FLAG_LINEFEED             BV01
 #define LOG_FLAG_LINEFEED             BV01
@@ -2713,7 +2715,7 @@ extern void dispose_session(struct session *ses);
 
 
 extern void show_message(struct session *ses, int index, char *format, ...);
 extern void show_message(struct session *ses, int index, char *format, ...);
 extern void show_error(struct session *ses, int index, char *format, ...);
 extern void show_error(struct session *ses, int index, char *format, ...);
-extern void show_debug(struct session *ses, int index, char *format, ...);
+extern void show_debug(struct session *ses, int index, struct listnode *node, char *format, ...);
 extern void show_info(struct session *ses, int index, char *format, ...);
 extern void show_info(struct session *ses, int index, char *format, ...);
 extern void tintin_header(struct session *ses, int width, char *format, ...);
 extern void tintin_header(struct session *ses, int width, char *format, ...);
 extern void socket_printf(struct session *ses, size_t length, char *format, ...);
 extern void socket_printf(struct session *ses, size_t length, char *format, ...);
@@ -2924,7 +2926,7 @@ extern void init_local(struct session *ses);
 extern struct scriptroot *push_script_stack(struct session *ses, int list);
 extern struct scriptroot *push_script_stack(struct session *ses, int list);
 extern void pop_script_stack();
 extern void pop_script_stack();
 extern struct listroot *local_list(struct session *ses);
 extern struct listroot *local_list(struct session *ses);
-extern struct session *script_driver(struct session *ses, int list, char *str);
+extern struct session *script_driver(struct session *ses, int list, struct listnode *node, char *str);
 extern char *view_script(struct session *ses, struct scriptroot *root);
 extern char *view_script(struct session *ses, struct scriptroot *root);
 extern char *script_writer(struct session *ses, char *str);
 extern char *script_writer(struct session *ses, char *str);
 extern char *script_viewer(struct session *ses, char *str);
 extern char *script_viewer(struct session *ses, char *str);
@@ -2939,7 +2941,7 @@ extern DO_COMMAND(do_function);
 
 
 extern void check_all_actions(struct session *ses, char *original, char *line, char *buf);
 extern void check_all_actions(struct session *ses, char *original, char *line, char *buf);
 extern void check_all_actions_multi(struct session *ses, char *original, char *line, char *buf);
 extern void check_all_actions_multi(struct session *ses, char *original, char *line, char *buf);
-extern  int check_all_aliases(struct session *ses, char *input);
+extern struct listnode *check_all_aliases(struct session *ses, char *input);
 extern void check_all_buttons(struct session *ses, short row, short col, char *arg1, char *arg2, char *word, char *line);
 extern void check_all_buttons(struct session *ses, short row, short col, char *arg1, char *arg2, char *word, char *line);
 extern void check_all_gags(struct session *ses, char *original, char *line);
 extern void check_all_gags(struct session *ses, char *original, char *line);
 extern void check_all_highlights(struct session *ses, char *original, char *line);
 extern void check_all_highlights(struct session *ses, char *original, char *line);
@@ -2977,6 +2979,7 @@ extern char *str_time(struct session *ses, char *format, time_t time);
 extern unsigned long long generate_rand(struct session *ses);
 extern unsigned long long generate_rand(struct session *ses);
 extern void seed_rand(struct session *ses, unsigned long long seed);
 extern void seed_rand(struct session *ses, unsigned long long seed);
 extern char *capitalize(char *str);
 extern char *capitalize(char *str);
+extern char *decapitalize(char *str);
 extern char *ftos(double number);
 extern char *ftos(double number);
 extern char *ntos(long long number);
 extern char *ntos(long long number);
 extern char *indent_one(int len);
 extern char *indent_one(int len);

+ 29 - 17
src/tokenize.c

@@ -73,65 +73,65 @@ void debugtoken(struct session *ses, struct scriptroot *root, struct scriptnode
 		switch (token->type)
 		switch (token->type)
 		{
 		{
 			case TOKEN_TYPE_REPEAT:
 			case TOKEN_TYPE_REPEAT:
-				show_debug(ses, root->list, "%s" COLOR_REPEAT "!\e[0m%s", indent(token->lvl + 1), token->str);
+				show_debug(ses, root->list, NULL, "%s" COLOR_REPEAT "!\e[0m%s", indent(token->lvl + 1), token->str);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_STRING:
 			case TOKEN_TYPE_STRING:
-				show_debug(ses, root->list, "%s%s", indent(token->lvl + 1), token->str);
+				show_debug(ses, root->list, NULL, "%s%s", indent(token->lvl + 1), token->str);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_SESSION:
 			case TOKEN_TYPE_SESSION:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_SESSION "%s", indent(token->lvl + 1), gtd->tintin_char, token->str);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_SESSION "%s", indent(token->lvl + 1), gtd->tintin_char, token->str);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_ELSE:
 			case TOKEN_TYPE_ELSE:
 			case TOKEN_TYPE_END:
 			case TOKEN_TYPE_END:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, token->str);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, token->str);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_DEFAULT:
 			case TOKEN_TYPE_DEFAULT:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_BREAK:
 			case TOKEN_TYPE_BREAK:
 			case TOKEN_TYPE_CONTINUE:
 			case TOKEN_TYPE_CONTINUE:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_COMMAND:
 			case TOKEN_TYPE_COMMAND:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_COMMAND   "%s " COLOR_STRING "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->str);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_COMMAND   "%s " COLOR_STRING "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->str);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_RETURN:
 			case TOKEN_TYPE_RETURN:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_STRING "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->str);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_STRING "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->str);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_CASE:
 			case TOKEN_TYPE_CASE:
 			case TOKEN_TYPE_ELSEIF:
 			case TOKEN_TYPE_ELSEIF:
 			case TOKEN_TYPE_IF:
 			case TOKEN_TYPE_IF:
 			case TOKEN_TYPE_WHILE:
 			case TOKEN_TYPE_WHILE:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->str);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->str);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_FOREACH:
 			case TOKEN_TYPE_FOREACH:
 			case TOKEN_TYPE_LOOP:
 			case TOKEN_TYPE_LOOP:
 			case TOKEN_TYPE_PARSE:
 			case TOKEN_TYPE_PARSE:
 			case TOKEN_TYPE_SWITCH:
 			case TOKEN_TYPE_SWITCH:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_STRING "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->data->hlt);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_STRING "%s\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->data->hlt);
 				break;
 				break;
 
 
 			case TOKEN_TYPE_REGEX:
 			case TOKEN_TYPE_REGEX:
-				show_debug(ses, root->list, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->str, token->regex->str);
+				show_debug(ses, root->list, NULL, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}\e[0m", indent(token->lvl + 1), gtd->tintin_char, command_table[token->cmd].name, token->str, token->regex->str);
 				break;
 				break;
 
 
 			default:
 			default:
 				if (token == (struct scriptnode *) ses)
 				if (token == (struct scriptnode *) ses)
 				{
 				{
-					show_debug(ses, root->list, "[--] (error) token == ses");
+					show_debug(ses, root->list, NULL, "[--] (error) token == ses");
 				}
 				}
 				else
 				else
 				{
 				{
-					show_debug(ses, root->list, "[%02d] %s\e[1;33m%d {\e[0m%s\e[1;32m}\e[0m", token->type, indent(token->lvl + 1), token->cmd, token->str);
+					show_debug(ses, root->list, NULL, "[%02d] %s\e[1;33m%d {\e[0m%s\e[1;32m}\e[0m", token->type, indent(token->lvl + 1), token->cmd, token->str);
 				}
 				}
 				break;
 				break;
 		}
 		}
@@ -297,7 +297,7 @@ void handlereturntoken(struct session *ses, struct scriptnode *token)
 
 
 		SET_BIT(gtd->flags, TINTIN_FLAG_LOCAL);
 		SET_BIT(gtd->flags, TINTIN_FLAG_LOCAL);
 	}
 	}
-//	show_debug(ses, LIST_FUNCTION, COLOR_DEBUG "#DEBUG RETURN " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", arg);
+//	show_debug(ses, LIST_FUNCTION, NULL, COLOR_DEBUG "#DEBUG RETURN " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", arg);
 }
 }
 
 
 void handleswitchtoken(struct session *ses, struct scriptnode *token)
 void handleswitchtoken(struct session *ses, struct scriptnode *token)
@@ -1052,7 +1052,7 @@ struct scriptnode *parse_script(struct scriptroot *root, int lvl, struct scriptn
 				{
 				{
 					substitute(root->ses, token->regex->bod, token->regex->buf, SUB_CMD);
 					substitute(root->ses, token->regex->bod, token->regex->buf, SUB_CMD);
 
 
-					root->ses = script_driver(root->ses, LIST_COMMAND, token->regex->buf);
+					root->ses = script_driver(root->ses, LIST_COMMAND, NULL, token->regex->buf);
 				}
 				}
 				else
 				else
 				{
 				{
@@ -1269,6 +1269,9 @@ char *view_script(struct session *ses, struct scriptroot *root)
 			case TOKEN_TYPE_LOOP:
 			case TOKEN_TYPE_LOOP:
 			case TOKEN_TYPE_PARSE:
 			case TOKEN_TYPE_PARSE:
 			case TOKEN_TYPE_SWITCH:
 			case TOKEN_TYPE_SWITCH:
+			case TOKEN_TYPE_BROKEN_FOREACH:
+			case TOKEN_TYPE_BROKEN_LOOP:
+			case TOKEN_TYPE_BROKEN_PARSE:
 				cat_sprintf(buf, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_STRING "%s\n%s" COLOR_BRACE "{\n", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, token->data->hlt, indent(token->lvl));
 				cat_sprintf(buf, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_STRING "%s\n%s" COLOR_BRACE "{\n", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, token->data->hlt, indent(token->lvl));
 				break;
 				break;
 
 
@@ -1276,6 +1279,7 @@ char *view_script(struct session *ses, struct scriptroot *root)
 			case TOKEN_TYPE_ELSEIF:
 			case TOKEN_TYPE_ELSEIF:
 			case TOKEN_TYPE_IF:
 			case TOKEN_TYPE_IF:
 			case TOKEN_TYPE_WHILE:
 			case TOKEN_TYPE_WHILE:
+			case TOKEN_TYPE_BROKEN_WHILE:
 				cat_sprintf(buf, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}" COLOR_STRING "\n%s" COLOR_BRACE "{\n", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, token->str, indent(token->lvl));
 				cat_sprintf(buf, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}" COLOR_STRING "\n%s" COLOR_BRACE "{\n", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, token->str, indent(token->lvl));
 				break;
 				break;
 
 
@@ -1308,9 +1312,10 @@ char *view_script(struct session *ses, struct scriptroot *root)
 	return buf;
 	return buf;
 }
 }
 
 
-struct session *script_driver(struct session *ses, int list, char *str)
+struct session *script_driver(struct session *ses, int list, struct listnode *node, char *str)
 {
 {
 	struct scriptroot *root;
 	struct scriptroot *root;
+	int debug;
 
 
 	push_call("script_driver(%p,%d,%p)",ses,list,str);
 	push_call("script_driver(%p,%d,%p)",ses,list,str);
 
 
@@ -1318,14 +1323,21 @@ struct session *script_driver(struct session *ses, int list, char *str)
 
 
 	gtd->level->input += list != LIST_COMMAND;
 	gtd->level->input += list != LIST_COMMAND;
 
 
+	debug = node ? HAS_BIT(node->flags, NODE_FLAG_DEBUG) : 0;
+
+	gtd->level->debug += debug;
+
 	tokenize_script(root, 0, str);
 	tokenize_script(root, 0, str);
 
 
 	ses = (struct session *) parse_script(root, 0, root->next, root->prev);
 	ses = (struct session *) parse_script(root, 0, root->next, root->prev);
 
 
 	if (list != LIST_COMMAND)
 	if (list != LIST_COMMAND)
 	{
 	{
-		show_debug(ses, list, COLOR_DEBUG "#END%s", list_table[list].name);
+		show_debug(ses, list, NULL, COLOR_DEBUG "#END%s", list_table[list].name);
 	}
 	}
+
+	gtd->level->debug -= debug;
+
 	gtd->level->input -= list != LIST_COMMAND;
 	gtd->level->input -= list != LIST_COMMAND;
 
 
 	while (root->prev)
 	while (root->prev)

+ 19 - 18
src/trigger.c

@@ -83,7 +83,7 @@ void check_all_actions(struct session *ses, char *original, char *line, char *bu
 
 
 		if (check_one_regexp(ses, node, line, original, 0))
 		if (check_one_regexp(ses, node, line, original, 0))
 		{
 		{
-			show_debug(ses, LIST_ACTION, COLOR_DEBUG "#DEBUG ACTION " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+			show_debug(ses, LIST_ACTION, node, COLOR_DEBUG "#DEBUG ACTION " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
 
 
 			substitute(ses, node->arg2, buf, SUB_ARG|SUB_SEC);
 			substitute(ses, node->arg2, buf, SUB_ARG|SUB_SEC);
 
 
@@ -92,7 +92,7 @@ void check_all_actions(struct session *ses, char *original, char *line, char *bu
 				delete_node_list(ses, LIST_ACTION, node);
 				delete_node_list(ses, LIST_ACTION, node);
 			}
 			}
 
 
-			script_driver(ses, LIST_ACTION, buf);
+			script_driver(ses, LIST_ACTION, node, buf);
 
 
 			return;
 			return;
 		}
 		}
@@ -123,7 +123,7 @@ void check_all_actions_multi(struct session *ses, char *original, char *stripped
 			{
 			{
 				break;
 				break;
 			}
 			}
-			show_debug(ses, LIST_ACTION, COLOR_DEBUG "#DEBUG MULTI ACTION " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+			show_debug(ses, LIST_ACTION, node, COLOR_DEBUG "#DEBUG MULTI ACTION " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
 
 
 			substitute(ses, node->arg2, buf, SUB_ARG|SUB_SEC);
 			substitute(ses, node->arg2, buf, SUB_ARG|SUB_SEC);
 
 
@@ -151,7 +151,7 @@ void check_all_actions_multi(struct session *ses, char *original, char *stripped
 					pto = pts = NULL;
 					pto = pts = NULL;
 				}
 				}
 			}
 			}
-			script_driver(ses, LIST_ACTION, buf);
+			script_driver(ses, LIST_ACTION, node, buf);
 
 
 			ptm = node->arg1 + (*node->arg1 == '~');
 			ptm = node->arg1 + (*node->arg1 == '~');
 
 
@@ -205,7 +205,7 @@ DO_COMMAND(do_unalias)
 	return ses;
 	return ses;
 }
 }
 
 
-int check_all_aliases(struct session *ses, char *input)
+struct listnode *check_all_aliases(struct session *ses, char *input)
 {
 {
 	struct listnode *node;
 	struct listnode *node;
 	struct listroot *root;
 	struct listroot *root;
@@ -278,6 +278,8 @@ int check_all_aliases(struct session *ses, char *input)
 
 
 			if (!strncmp(node->arg1, line, strlen(node->arg1)) && !strcmp(node->arg2, buf) && *gtd->vars[0])
 			if (!strncmp(node->arg1, line, strlen(node->arg1)) && !strcmp(node->arg2, buf) && *gtd->vars[0])
 			{
 			{
+				show_error(ses, LIST_ACTION, "#WARNING: #ALIAS {%s} CONTAINS NO %%0-%%99 BUT IS CALLED WITH ARGUMENT {%s}.", node->arg1, gtd->vars[0]);
+
 				sprintf(input, "%s %s", buf, gtd->vars[0]);
 				sprintf(input, "%s %s", buf, gtd->vars[0]);
 			}
 			}
 			else
 			else
@@ -285,18 +287,18 @@ int check_all_aliases(struct session *ses, char *input)
 				sprintf(input, "%s", buf);
 				sprintf(input, "%s", buf);
 			}
 			}
 
 
-			show_debug(ses, LIST_ALIAS, COLOR_DEBUG "#DEBUG ALIAS " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1, gtd->vars[0]);
+			show_debug(ses, LIST_ALIAS, node, COLOR_DEBUG "#DEBUG ALIAS " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1, gtd->vars[0]);
 
 
 			if (node->shots && --node->shots == 0)
 			if (node->shots && --node->shots == 0)
 			{
 			{
 				delete_node_list(ses, LIST_ALIAS, node);
 				delete_node_list(ses, LIST_ALIAS, node);
 			}
 			}
 			pop_call();
 			pop_call();
-			return TRUE;
+			return node;
 		}
 		}
 	}
 	}
 	pop_call();
 	pop_call();
-	return FALSE;
+	return NULL;
 }
 }
 
 
 
 
@@ -426,7 +428,7 @@ void check_all_buttons(struct session *ses, short row, short col, char *arg1, ch
 
 
 		if (!strcmp(arg4, node->arg4))
 		if (!strcmp(arg4, node->arg4))
 		{
 		{
-			show_debug(ses, LIST_BUTTON, COLOR_DEBUG "#DEBUG BUTTON " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+			show_debug(ses, LIST_BUTTON, node, COLOR_DEBUG "#DEBUG BUTTON " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
 
 
 			RESTRING(gtd->vars[0], ntos(row));
 			RESTRING(gtd->vars[0], ntos(row));
 			RESTRING(gtd->vars[1], ntos(col));
 			RESTRING(gtd->vars[1], ntos(col));
@@ -441,7 +443,7 @@ void check_all_buttons(struct session *ses, short row, short col, char *arg1, ch
 			{
 			{
 				delete_node_list(ses, LIST_BUTTON, node);
 				delete_node_list(ses, LIST_BUTTON, node);
 			}
 			}
-			script_driver(ses, LIST_BUTTON, buf);
+			script_driver(ses, LIST_BUTTON, node, buf);
 
 
 			break;
 			break;
 		}
 		}
@@ -490,7 +492,6 @@ DO_COMMAND(do_delay)
 			create_node_list(ses->list[LIST_DELAY], time, arg2, arg1, arg3);
 			create_node_list(ses->list[LIST_DELAY], time, arg2, arg1, arg3);
 
 
 			show_message(ses, LIST_DELAY, "#DELAY: IN {%s} SECONDS {%s} IS EXECUTED.", arg1, arg2);
 			show_message(ses, LIST_DELAY, "#DELAY: IN {%s} SECONDS {%s} IS EXECUTED.", arg1, arg2);
-
 		}
 		}
 		else
 		else
 		{
 		{
@@ -615,7 +616,7 @@ void check_all_gags(struct session *ses, char *original, char *line)
 
 
 		if (check_one_regexp(ses, node, line, original, 0))
 		if (check_one_regexp(ses, node, line, original, 0))
 		{
 		{
-//			show_debug(ses, LIST_GAG, "#DEBUG GAG {%s}", node->arg1);
+//			show_debug(ses, LIST_GAG, node, "#DEBUG GAG {%s}", node->arg1);
 
 
 			if (node->shots && --node->shots == 0)
 			if (node->shots && --node->shots == 0)
 			{
 			{
@@ -741,7 +742,7 @@ void check_all_highlights(struct session *ses, char *original, char *line)
 
 
 				pto = ptm + len;
 				pto = ptm + len;
 
 
-				show_debug(ses, LIST_HIGHLIGHT, COLOR_DEBUG "#DEBUG HIGHLIGHT " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+				show_debug(ses, LIST_HIGHLIGHT, node, COLOR_DEBUG "#DEBUG HIGHLIGHT " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
 			}
 			}
 			while (check_one_regexp(ses, node, ptl, pto, 0));
 			while (check_one_regexp(ses, node, ptl, pto, 0));
 
 
@@ -875,7 +876,7 @@ int check_all_prompts(struct session *ses, char *original, char *line)
 				strip_vt102_codes(original, line);
 				strip_vt102_codes(original, line);
 			}
 			}
 
 
-			show_debug(ses, LIST_PROMPT, COLOR_DEBUG "#DEBUG PROMPT " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+			show_debug(ses, LIST_PROMPT, node, COLOR_DEBUG "#DEBUG PROMPT " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
 
 
 			if (strcmp(node->arg3, "0"))
 			if (strcmp(node->arg3, "0"))
 			{
 			{
@@ -954,7 +955,7 @@ void check_all_substitutions(struct session *ses, char *original, char *line)
 	subst  = str_alloc_stack(0);
 	subst  = str_alloc_stack(0);
 	result = str_alloc_stack(0);
 	result = str_alloc_stack(0);
 	temp   = str_alloc_stack(0);
 	temp   = str_alloc_stack(0);
-	
+
 	for (root->update = 0 ; root->update < root->used ; root->update++)
 	for (root->update = 0 ; root->update < root->used ; root->update++)
 	{
 	{
 		node = root->list[root->update];
 		node = root->list[root->update];
@@ -1006,7 +1007,7 @@ void check_all_substitutions(struct session *ses, char *original, char *line)
 
 
 				pto = ptm + len;
 				pto = ptm + len;
 
 
-				show_debug(ses, LIST_SUBSTITUTE, COLOR_DEBUG "#DEBUG SUBSTITUTE " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1, match);
+				show_debug(ses, LIST_SUBSTITUTE, node, COLOR_DEBUG "#DEBUG SUBSTITUTE " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1, match);
 
 
 				ptm = node->arg1 + (*node->arg1 == '~');
 				ptm = node->arg1 + (*node->arg1 == '~');
 
 
@@ -1097,7 +1098,7 @@ void check_all_substitutions_multi(struct session *ses, char *original, char *li
 
 
 				pto = ptm + len;
 				pto = ptm + len;
 
 
-				show_debug(ses, LIST_SUBSTITUTE, COLOR_DEBUG "#DEBUG SUBSTITUTE " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1, match);
+				show_debug(ses, LIST_SUBSTITUTE, node, COLOR_DEBUG "#DEBUG SUBSTITUTE " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "} {" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1, match);
 
 
 				ptm = node->arg1 + (*node->arg1 == '~');
 				ptm = node->arg1 + (*node->arg1 == '~');
 
 
@@ -1194,7 +1195,7 @@ DO_COMMAND(do_tick)
 	}
 	}
 	else if (*arg1 && *arg2 == 0)
 	else if (*arg1 && *arg2 == 0)
 	{
 	{
-		if (show_node_with_wild(ses, arg1, ses->list[LIST_TICKER]) == FALSE) 
+		if (show_node_with_wild(ses, arg1, ses->list[LIST_TICKER]) == FALSE)
 		{
 		{
 			show_message(ses, LIST_TICKER, "#TICKER: NO MATCHES FOUND FOR {%s}.", arg1);
 			show_message(ses, LIST_TICKER, "#TICKER: NO MATCHES FOUND FOR {%s}.", arg1);
 		}
 		}

+ 19 - 14
src/update.c

@@ -177,7 +177,7 @@ void mainloop(void)
 			pulse.update_daemon = PULSE_UPDATE_DAEMON;
 			pulse.update_daemon = PULSE_UPDATE_DAEMON;
 
 
 			update_daemon();
 			update_daemon();
-			
+
 			close_timer(TIMER_UPDATE_DAEMON);
 			close_timer(TIMER_UPDATE_DAEMON);
 		}
 		}
 
 
@@ -201,7 +201,7 @@ void mainloop(void)
 			update_port();
 			update_port();
 
 
 			close_timer(TIMER_UPDATE_PORT);
 			close_timer(TIMER_UPDATE_PORT);
-		}	
+		}
 
 
 		if (--pulse.update_ticks == 0)
 		if (--pulse.update_ticks == 0)
 		{
 		{
@@ -560,9 +560,9 @@ void update_daemon(void)
 					if (gtd->detach_sock < 0)
 					if (gtd->detach_sock < 0)
 					{
 					{
 						syserr_printf(gtd->ses, "update_daemon: detach_port: accept");
 						syserr_printf(gtd->ses, "update_daemon: detach_port: accept");
-						
+
 						gtd->detach_sock = close(gtd->detach_sock);
 						gtd->detach_sock = close(gtd->detach_sock);
-						
+
 						goto attach;
 						goto attach;
 					}
 					}
 
 
@@ -571,7 +571,7 @@ void update_daemon(void)
 						syserr_printf(gtd->ses, "update_daemon: detach_port: fcntl O_NDELAY|O_NONBLOCK");
 						syserr_printf(gtd->ses, "update_daemon: detach_port: fcntl O_NDELAY|O_NONBLOCK");
 
 
 						gtd->detach_sock = close(gtd->detach_sock);
 						gtd->detach_sock = close(gtd->detach_sock);
-						
+
 						goto attach;
 						goto attach;
 					}
 					}
 
 
@@ -698,7 +698,7 @@ void update_daemon(void)
 		if (rv < 0)
 		if (rv < 0)
 		{
 		{
 			gtd->attach_sock = close(gtd->attach_sock);
 			gtd->attach_sock = close(gtd->attach_sock);
-	
+
 			show_message(gtd->ses, LIST_COMMAND, "#DAEMON UPDATE: UNATTACHING {%s} DUE TO SELECT ERROR.", gtd->attach_file);
 			show_message(gtd->ses, LIST_COMMAND, "#DAEMON UPDATE: UNATTACHING {%s} DUE TO SELECT ERROR.", gtd->attach_file);
 		}
 		}
 		else if (rv > 0)
 		else if (rv > 0)
@@ -876,7 +876,7 @@ void tick_update(void)
 
 
 	gtd->utime_next_tick = gtd->utime + 1000000000;
 	gtd->utime_next_tick = gtd->utime + 1000000000;
 
 
-	for (ses = gts->next ; ses ; ses = gtd->update)
+	for (ses = gts ; ses ; ses = gtd->update)
 	{
 	{
 		gtd->update = ses->next;
 		gtd->update = ses->next;
 
 
@@ -891,6 +891,11 @@ void tick_update(void)
 				tintin_printf2(gtd->ses, "error: tick_update: node->val64 == 0");
 				tintin_printf2(gtd->ses, "error: tick_update: node->val64 == 0");
 			}
 			}
 
 
+			if (ses == gts && node->shots == 0)
+			{
+				continue;
+			}
+
 			if (node->val64 <= gtd->utime)
 			if (node->val64 <= gtd->utime)
 			{
 			{
 				node->val64 += (long long) (get_number(ses, node->arg3) * 1000000LL);
 				node->val64 += (long long) (get_number(ses, node->arg3) * 1000000LL);
@@ -904,13 +909,13 @@ void tick_update(void)
 
 
 				if (!HAS_BIT(root->flags, LIST_FLAG_IGNORE))
 				if (!HAS_BIT(root->flags, LIST_FLAG_IGNORE))
 				{
 				{
-					show_debug(ses, LIST_TICKER, COLOR_DEBUG "#DEBUG TICKER " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg2);
+					show_debug(ses, LIST_TICKER, node, COLOR_DEBUG "#DEBUG TICKER " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg2);
 
 
 					if (node->shots && --node->shots == 0)
 					if (node->shots && --node->shots == 0)
 					{
 					{
 						delete_node_list(ses, LIST_TICKER, node);
 						delete_node_list(ses, LIST_TICKER, node);
 					}
 					}
-					script_driver(ses, LIST_TICKER, node->arg2);
+					script_driver(ses, LIST_TICKER, node, node->arg2);
 				}
 				}
 			}
 			}
 			else
 			else
@@ -949,11 +954,11 @@ void delay_update(void)
 
 
 			if (node->val64 <= gtd->utime)
 			if (node->val64 <= gtd->utime)
 			{
 			{
-				show_debug(ses, LIST_DELAY, COLOR_DEBUG "#DEBUG DELAY " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg2);
+				show_debug(ses, LIST_DELAY, node, COLOR_DEBUG "#DEBUG DELAY " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg2);
 
 
 				delete_index_list(root, root->update);
 				delete_index_list(root, root->update);
 
 
-				script_driver(ses, LIST_DELAY, node->arg2);
+				script_driver(ses, LIST_DELAY, node, node->arg2);
 			}
 			}
 			else
 			else
 			{
 			{
@@ -993,9 +998,9 @@ void path_update(void)
 
 
 				node->val64 = 0;
 				node->val64 = 0;
 
 
-				show_debug(ses, LIST_PATH, COLOR_DEBUG "#DEBUG PATH " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
+				show_debug(ses, LIST_PATH, node, COLOR_DEBUG "#DEBUG PATH " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", node->arg1);
 
 
-				script_driver(ses, LIST_PATH, node->arg1);
+				script_driver(ses, LIST_PATH, NULL, node->arg1);
 
 
 				if (root->update == root->used)
 				if (root->update == root->used)
 				{
 				{
@@ -1022,7 +1027,7 @@ void packet_update(void)
 		if (HAS_BIT(ses->telopts, TELOPT_FLAG_UPDATENAWS))
 		if (HAS_BIT(ses->telopts, TELOPT_FLAG_UPDATENAWS))
 		{
 		{
 			client_send_sb_naws(ses, 0, NULL);
 			client_send_sb_naws(ses, 0, NULL);
-					
+
 			DEL_BIT(ses->telopts, TELOPT_FLAG_UPDATENAWS);
 			DEL_BIT(ses->telopts, TELOPT_FLAG_UPDATENAWS);
 		}
 		}
 	}
 	}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
src/utf8.c


+ 15 - 1
src/utils.c

@@ -338,7 +338,7 @@ char *str_time(struct session *ses, char *format, time_t time)
 
 
 	return buf[cnt];
 	return buf[cnt];
 }
 }
-	
+
 void seed_rand(struct session *ses, unsigned long long seed)
 void seed_rand(struct session *ses, unsigned long long seed)
 {
 {
 	ses->rand = seed % 4294967291ULL;
 	ses->rand = seed % 4294967291ULL;
@@ -393,6 +393,20 @@ char *capitalize(char *str)
 	return outbuf;
 	return outbuf;
 }
 }
 
 
+char *decapitalize(char *str)
+{
+	char *outbuf = str_alloc_stack(0);
+	int cnt;
+
+	for (cnt = 0 ; str[cnt] != 0 ; cnt++)
+	{
+		outbuf[cnt] = tolower((int) str[cnt]);
+	}
+	outbuf[cnt] = 0;
+
+	return outbuf;
+}
+
 char *ftos(double number)
 char *ftos(double number)
 {
 {
 	static char outbuf[10][NUMBER_SIZE];
 	static char outbuf[10][NUMBER_SIZE];

+ 6 - 6
src/variable.c

@@ -298,7 +298,7 @@ DO_COMMAND(do_replace)
 	}
 	}
 	else
 	else
 	{
 	{
-//		show_debug(ses, LIST_VARIABLE, "#REPLACE {%s} {%s} {%s}", node->arg2, arg2, arg3);
+//		show_debug(ses, LIST_VARIABLE, node, "#REPLACE {%s} {%s} {%s}", node->arg2, arg2, arg3);
 
 
 		pti = node->arg2;
 		pti = node->arg2;
 		str = str_alloc_stack(0);
 		str = str_alloc_stack(0);
@@ -833,7 +833,7 @@ void metricgroupingstring(struct session *ses, char *str)
 		else
 		else
 		{
 		{
 			snprintf(tmp, NUMBER_SIZE, "%Lf", val);
 			snprintf(tmp, NUMBER_SIZE, "%Lf", val);
-		} 
+		}
 		sprintf(str, "%.5s%c", tmp, small[index]);
 		sprintf(str, "%.5s%c", tmp, small[index]);
 	}
 	}
 	else if (val <= -1000)
 	else if (val <= -1000)
@@ -1027,7 +1027,7 @@ int string_str_raw_len(struct session *ses, char *str, int start, int end)
 		{
 		{
 			ret_cnt += (str_cnt >= start) ? 1 : 0;
 			ret_cnt += (str_cnt >= start) ? 1 : 0;
 			raw_cnt++;
 			raw_cnt++;
-			
+
 			if (str[raw_cnt] == '\\')
 			if (str[raw_cnt] == '\\')
 			{
 			{
 				ret_cnt += (str_cnt >= start) ? 1 : 0;
 				ret_cnt += (str_cnt >= start) ? 1 : 0;
@@ -1107,7 +1107,7 @@ int string_str_str_len(struct session *ses, char *str, int start, int end)
 		if (str[raw_cnt] == '\\')
 		if (str[raw_cnt] == '\\')
 		{
 		{
 			raw_cnt++;
 			raw_cnt++;
-			
+
 			if (str[raw_cnt] == '\\')
 			if (str[raw_cnt] == '\\')
 			{
 			{
 				ret_cnt += (str_cnt >= start) ? 1 : 0;
 				ret_cnt += (str_cnt >= start) ? 1 : 0;
@@ -1411,7 +1411,7 @@ void format_string(struct session *ses, char *format, char *arg, char *out)
 							{
 							{
 								ptt = arg2;
 								ptt = arg2;
 								ptn = ptn + 1;
 								ptn = ptn + 1;
-		
+
 								while (*ptn)
 								while (*ptn)
 								{
 								{
 									*ptt++ = *ptn++;
 									*ptt++ = *ptn++;
@@ -1459,7 +1459,7 @@ void format_string(struct session *ses, char *format, char *arg, char *out)
 
 
 							ptt = argformat;
 							ptt = argformat;
 							ptn = pts;
 							ptn = pts;
-		
+
 							while (*ptt)
 							while (*ptt)
 							{
 							{
 								*ptn++ = *ptt++;
 								*ptn++ = *ptt++;

+ 26 - 26
src/vt102.c

@@ -284,22 +284,22 @@ int skip_vt102_codes_non_graph(char *str)
 	switch (str[skip])
 	switch (str[skip])
 	{
 	{
 		case   7:   // BEL
 		case   7:   // BEL
-//		case   8:   // BS  
-//		case   9:   // HT  
-//		case  10:   // LF  
-		case  11:   // VT  
-		case  12:   // FF  
-		case  13:   // CR  
-		case  14:   // SO  
-		case  15:   // SI  
-		case  17:   // DC1 
-		case  19:   // DC3 
-		case  24:   // CAN 
-		case  26:   // SUB 
-		case 127:   // DEL 
+//		case   8:   // BS
+//		case   9:   // HT
+//		case  10:   // LF
+		case  11:   // VT
+		case  12:   // FF
+		case  13:   // CR
+		case  14:   // SO
+		case  15:   // SI
+		case  17:   // DC1
+		case  19:   // DC3
+		case  24:   // CAN
+		case  26:   // SUB
+		case 127:   // DEL
 			return 1;
 			return 1;
 
 
-		case  27:   // ESC 
+		case  27:   // ESC
 			break;
 			break;
 
 
 		default:
 		default:
@@ -656,7 +656,7 @@ void strip_non_vt102_codes(char *str, char *buf)
 }
 }
 
 
 char *strip_vt102_strstr(char *str, char *buf, int *len)
 char *strip_vt102_strstr(char *str, char *buf, int *len)
-{ 
+{
 	char *pti, *ptm, *pts;
 	char *pti, *ptm, *pts;
 
 
 	push_call("strip_vt102_strstr(%p,%p,%p)",str,buf,len);
 	push_call("strip_vt102_strstr(%p,%p,%p)",str,buf,len);
@@ -804,9 +804,9 @@ void get_color_codes(char *old, char *str, char *buf, int flags)
 					rgb[2] = URANGE(0, atoi(col), 255);
 					rgb[2] = URANGE(0, atoi(col), 255);
 
 
 					fgc = rgb[0] * 256 * 256 + rgb[1] * 256 + rgb[2];
 					fgc = rgb[0] * 256 * 256 + rgb[1] * 256 + rgb[2];
-					
+
 					DEL_BIT(vtc, COL_TCF_2|COL_TCF_R);
 					DEL_BIT(vtc, COL_TCF_2|COL_TCF_R);
-					SET_BIT(vtc, COL_TCB);
+					SET_BIT(vtc, COL_TCF);
 				}
 				}
 			}
 			}
 			else if (HAS_BIT(vtc, COL_TCB_R))
 			else if (HAS_BIT(vtc, COL_TCB_R))
@@ -824,7 +824,7 @@ void get_color_codes(char *old, char *str, char *buf, int flags)
 					rgb[5] = URANGE(0, atoi(col), 255);
 					rgb[5] = URANGE(0, atoi(col), 255);
 
 
 					fgc = rgb[3] * 256 * 256 + rgb[4] * 256 + rgb[5];
 					fgc = rgb[3] * 256 * 256 + rgb[4] * 256 + rgb[5];
-					
+
 					DEL_BIT(vtc, COL_TCB_2|COL_TCF_R);
 					DEL_BIT(vtc, COL_TCB_2|COL_TCF_R);
 					SET_BIT(vtc, COL_TCB);
 					SET_BIT(vtc, COL_TCB);
 				}
 				}
@@ -916,7 +916,7 @@ void get_color_codes(char *old, char *str, char *buf, int flags)
 								fgc = atoi(col);
 								fgc = atoi(col);
 								DEL_BIT(vtc, COL_XTF|COL_TCF);
 								DEL_BIT(vtc, COL_XTF|COL_TCF);
 								break;
 								break;
-							
+
 							case 4:
 							case 4:
 							case 9:
 							case 9:
 								bgc = atoi(col);
 								bgc = atoi(col);
@@ -1009,7 +1009,7 @@ int strip_vt102_strlen(struct session *ses, char *str)
 {
 {
 	char *pti;
 	char *pti;
 	int size, width, str_len;
 	int size, width, str_len;
-	
+
 	str_len = 0;
 	str_len = 0;
 
 
 	pti = str;
 	pti = str;
@@ -1232,7 +1232,7 @@ int interpret_vt102_codes(struct session *ses, char *str, int real)
 			ses->split->top_row = URANGE(1, ses->split->top_row, gtd->screen->rows);
 			ses->split->top_row = URANGE(1, ses->split->top_row, gtd->screen->rows);
 
 
 			ses->split->bot_row = ses->split->bot_row ? URANGE(1, ses->split->bot_row, gtd->screen->rows) : gtd->screen->rows;
 			ses->split->bot_row = ses->split->bot_row ? URANGE(1, ses->split->bot_row, gtd->screen->rows) : gtd->screen->rows;
-			
+
 			return TRUE;
 			return TRUE;
 		}
 		}
 	}
 	}
@@ -1255,7 +1255,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 			}
 			}
 			pop_call();
 			pop_call();
 			return 0;
 			return 0;
-			
+
 		case ASCII_ESC:
 		case ASCII_ESC:
 			break;
 			break;
 
 
@@ -1410,9 +1410,9 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 					if (cplen >= 10)
 					if (cplen >= 10)
 					{
 					{
 						sprintf(osc, "%.*s", 8, str + 3);
 						sprintf(osc, "%.*s", 8, str + 3);
-							
+
 						check_all_events(ses, EVENT_FLAG_VT100, 0, 1, "VT100 OSC COLOR PALETTE", osc);
 						check_all_events(ses, EVENT_FLAG_VT100, 0, 1, "VT100 OSC COLOR PALETTE", osc);
-							
+
 						if (check_all_events(ses, EVENT_FLAG_CATCH, 0, 1, "CATCH VT100 OSC", osc))
 						if (check_all_events(ses, EVENT_FLAG_CATCH, 0, 1, "CATCH VT100 OSC", osc))
 						{
 						{
 							pop_call();
 							pop_call();
@@ -1448,7 +1448,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 							return 1;
 							return 1;
 						}
 						}
 					}
 					}
-					
+
 					while (cplen >= skip && skip < BUFFER_SIZE)
 					while (cplen >= skip && skip < BUFFER_SIZE)
 					{
 					{
 						if (str[skip] == ASCII_BEL)
 						if (str[skip] == ASCII_BEL)
@@ -1457,7 +1457,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 						}
 						}
 						skip++;
 						skip++;
 					}
 					}
-	
+
 					snprintf(osc, BUFFER_SIZE, "%.*s", skip - 2, str + 2);
 					snprintf(osc, BUFFER_SIZE, "%.*s", skip - 2, str + 2);
 
 
 					check_all_events(ses, SUB_SEC|EVENT_FLAG_VT100, 0, 1, "VT100 OSC", osc);
 					check_all_events(ses, SUB_SEC|EVENT_FLAG_VT100, 0, 1, "VT100 OSC", osc);

Vissa filer visades inte eftersom för många filer har ändrats