Scandum 4 年 前
コミット
b0fa43339e
41 ファイル変更1530 行追加974 行削除
  1. 4 0
      NEWS
  2. 110 94
      SCRIPTS
  3. 34 30
      TODO
  4. 76 19
      docs/help.html
  5. 58 1
      mods/igr.mods
  6. 11 0
      src/banner.c
  7. 11 11
      src/buffer.c
  8. 13 13
      src/config.c
  9. 246 150
      src/cursor.c
  10. 56 29
      src/data.c
  11. 80 1
      src/dict.c
  12. 5 3
      src/draw.c
  13. 2 2
      src/event.c
  14. 32 32
      src/gui.h
  15. 77 20
      src/help.c
  16. 15 11
      src/input.c
  17. 58 58
      src/line.c
  18. 135 28
      src/log.c
  19. 5 22
      src/main.c
  20. 169 75
      src/mapper.c
  21. 0 4
      src/math.c
  22. 0 81
      src/misc.c
  23. 1 8
      src/nest.c
  24. 1 0
      src/net.c
  25. 11 10
      src/parse.c
  26. 16 62
      src/path.c
  27. 1 1
      src/regex.c
  28. 1 0
      src/scan.c
  29. 18 25
      src/session.c
  30. 48 36
      src/show.c
  31. 4 5
      src/split.c
  32. 2 0
      src/ssl.c
  33. 5 5
      src/string.c
  34. 68 23
      src/substitute.c
  35. 13 15
      src/tables.c
  36. 2 2
      src/telopt_client.c
  37. 75 64
      src/tintin.h
  38. 11 7
      src/tokenize.c
  39. 15 8
      src/utf8.c
  40. 39 17
      src/variable.c
  41. 2 2
      src/vt102.c

+ 4 - 0
NEWS

@@ -1,6 +1,10 @@
 Due to continuous improvements old tintin scripts aren't always compatible
 Due to continuous improvements old tintin scripts aren't always compatible
 with new versions. This document tries to list most compatibility conflicts.
 with new versions. This document tries to list most compatibility conflicts.
 
 
+TinTin++ 2.02.12
+----------------
+01) The behavior of $variable[] is now identical to $variable[%*].
+
 TinTin++ 2.02.11
 TinTin++ 2.02.11
 ----------------
 ----------------
 
 

+ 110 - 94
SCRIPTS

@@ -661,33 +661,33 @@
 
 
 #event {PROGRAM START}
 #event {PROGRAM START}
 {
 {
-    #split 3 1;
-    #config mouse on;
-    #var active gts;
-    session_activated gts;
+	#split 3 1;
+	#config mouse on;
+	#var active gts;
+	session_activated gts;
 }
 }
 
 
 #event {SESSION CREATED}
 #event {SESSION CREATED}
 {
 {
-    #gts session_activated %0
+	#gts session_activated %0
 }
 }
 
 
 #event {SESSION ACTIVATED}
 #event {SESSION ACTIVATED}
 {
 {
-    #gts session_activated %0
+	#gts session_activated %0
 }
 }
 
 
 #alias {session_activated}
 #alias {session_activated}
 {
 {
-    #line sub esc #var sessions[$active] {<138>\e]68;2;TABS;#$active\a\e[4;24m$active\e[24m};
-    #var active {%0};
-    #line sub esc #var sessions[%0] {<128>\e]68;2;TABS;#nop\a\e[4;24m%0\e[24m};
-    #draw foreground Azure table 1 1 3 -1 {$sessions[%*]}
+	#line sub esc #var sessions[$active] {<138>\e]68;2;TABS;#$active\a\e[4;24m$active\e[24m};
+	#var active {%0};
+	#line sub esc #var sessions[%0] {<128>\e]68;2;TABS;#nop\a\e[4;24m%0\e[24m};
+	#draw foreground Azure table 1 1 3 -1 {$sessions[%*]}
 }
 }
 
 
 #event {PRESSED SECURE LINK TABS MOUSE BUTTON ONE}
 #event {PRESSED SECURE LINK TABS MOUSE BUTTON ONE}
 {
 {
-    %4
+	%4
 }
 }
 
 
 
 
@@ -699,12 +699,12 @@
 
 
 #event {IAC DO MXP}
 #event {IAC DO MXP}
 {
 {
-    #send {\xFF\xFB\x5B\}
+	#send {\xFF\xFB\x5B\}
 }
 }
 
 
 #function {mxp_link}
 #function {mxp_link}
 {
 {
-    #line sub esc #var result {\e]68;1;%1;%2\a\e[4m%3\e[24m}
+	#line sub esc #var result {\e]68;1;%1;%2\a\e[4m%3\e[24m}
 }
 }
 
 
 #act {~\e[1z<VERSION>} {#send {\e[4z<VERSION MXP=1.0 CLIENT=TINTIN++ VERSION=2.02.04>}}
 #act {~\e[1z<VERSION>} {#send {\e[4z<VERSION MXP=1.0 CLIENT=TINTIN++ VERSION=2.02.04>}}
@@ -716,7 +716,7 @@
 
 
 #event {PRESSED LINK MXP MOUSE BUTTON ONE}
 #event {PRESSED LINK MXP MOUSE BUTTON ONE}
 {
 {
-    #send {%4}
+	#send {%4}
 }
 }
 
 
 #sub {~\e[4z{<RExits>|</RExits>|<RDesc>|</RDesc>|<PROMPT>|</PROMPT>|<RName>|</RName>}} {}
 #sub {~\e[4z{<RExits>|</RExits>|<RDesc>|</RDesc>|<PROMPT>|</PROMPT>|<RName>|</RName>}} {}
@@ -742,33 +742,33 @@
 
 
 	#loop 1 &players[] cnt
 	#loop 1 &players[] cnt
 	{
 	{
-	    #var out[$cnt] {$cnt;$players[+$cnt][name];$players[+$cnt][age];$players[+$cnt][level]};
+		#var out[$cnt] {$cnt;$players[+$cnt][name];$players[+$cnt][age];$players[+$cnt][level]};
 	};
 	};
 	#draw scroll grid table 1 1 2+&players[]*2 80 $out[%*]
 	#draw scroll grid table 1 1 2+&players[]*2 80 $out[%*]
 }
 }
 
 
 #alias {test1}
 #alias {test1}
 {
 {
-    #list players index name;
-    #list players order;
-    display
+	#list players index name;
+	#list players order;
+	display
 }
 }
 
 
 #alias {test2}
 #alias {test2}
 {
 {
-    #list players index name;
-    #list players order;
-    #list players reverse;
-    display;
+	#list players index name;
+	#list players order;
+	#list players reverse;
+	display;
 }
 }
 
 
 #alias {test3}
 #alias {test3}
 {
 {
-    #list players index name;
-    #list players order;
-    #list players index level;
-    #list players order;
-    display
+	#list players index name;
+	#list players order;
+	#list players index level;
+	#list players order;
+	display
 }
 }
 
 
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
@@ -784,12 +784,12 @@
 
 
 #alias {inputswitch}
 #alias {inputswitch}
 {
 {
-    #cursor get {input[current]};
-    #cursor clear;
-    #cursor set {$input[buffer2]};
-    #cursor end;
-    #var input[buffer2] {$input[current]};
-    #draw Ebony tile {-1-$input[width]} 1 -2 -1 {$input[buffer2]}
+	#cursor get {input[current]};
+	#cursor clear;
+	#cursor set {$input[buffer2]};
+	#cursor end;
+	#var input[buffer2] {$input[current]};
+	#draw Ebony tile {-1-$input[width]} 1 -2 -1 {$input[buffer2]}
 }
 }
 
 
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
@@ -799,79 +799,79 @@
 
 
 #event {PROGRAM START}
 #event {PROGRAM START}
 {
 {
-    #config mouse on;
-    #var SCROLL[MODE] 0;
-    #split 0 1;
-    #screen raise SCREEN RESIZE;
+	#config mouse on;
+	#var SCROLL[MODE] 0;
+	#split 0 1;
+	#screen raise SCREEN RESIZE;
 }
 }
 
 
 #event {SCREEN RESIZE}
 #event {SCREEN RESIZE}
 {
 {
-    #var ROWS %0;
-    #var COLS %1;
-    #screen get SCROLL_TOP_ROW SCROLL[TOP_ROW];
-    #screen get SCROLL_TOP_COL SCROLL[TOP_COL];
-    #screen get SCROLL_BOT_ROW SCROLL[BOT_ROW];
-    #screen get SCROLL_BOT_COL SCROLL[BOT_COL];
+	#var ROWS %0;
+	#var COLS %1;
+	#screen get SCROLL_TOP_ROW SCROLL[TOP_ROW];
+	#screen get SCROLL_TOP_COL SCROLL[TOP_COL];
+	#screen get SCROLL_BOT_ROW SCROLL[BOT_ROW];
+	#screen get SCROLL_BOT_COL SCROLL[BOT_COL];
 }
 }
 
 
 #EVENT {SCROLLED MOUSE WHEEL UP}
 #EVENT {SCROLLED MOUSE WHEEL UP}
 {
 {
-    #if {$SCROLL[MODE] == 0}
-    {
-	#if {%0 < $ROWS / 2}
+	#if {$SCROLL[MODE] == 0}
 	{
 	{
-	    #var SCROLL[MODE] 1;
-	    #var SCROLL[OLD_ROW] $SCROLL[BOT_ROW];
-	    #math SCROLL[BOT_ROW] $SCROLL[OLD_ROW] / 2;
-	    #var BUFFER {};
-	    #screen scroll $SCROLL[TOP_ROW] $SCROLL[TOP_COL] $SCROLL[BOT_ROW] $SCROLL[BOT_COL];
+		#if {%0 < $ROWS / 2}
+		{
+			#var SCROLL[MODE] 1;
+			#var SCROLL[OLD_ROW] $SCROLL[BOT_ROW];
+			#math SCROLL[BOT_ROW] $SCROLL[OLD_ROW] / 2;
+			#var BUFFER {};
+			#screen scroll $SCROLL[TOP_ROW] $SCROLL[TOP_COL] $SCROLL[BOT_ROW] $SCROLL[BOT_COL];
 
 
-	    #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];
+			#screen clear square $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL];
+		};
 	};
 	};
-    };
-    #if {$SCROLL[MODE] == 1}
-    {
-	#buffer up 1
-    }
+	#if {$SCROLL[MODE] == 1}
+	{
+		#buffer up 1
+	}
 }
 }
 
 
 #EVENT {SCROLLED MOUSE WHEEL DOWN}
 #EVENT {SCROLLED MOUSE WHEEL DOWN}
 {
 {
-    #if {$SCROLL[MODE] == 1}
-    {
-	#if {%0 < $ROWS / 2}
+	#if {$SCROLL[MODE] == 1}
 	{
 	{
-	    #buffer down 1;
+		#if {%0 < $ROWS / 2}
+		{
+			#buffer down 1;
 
 
-	    #buffer info save SCROLL[INFO];
+			#buffer info save SCROLL[INFO];
 
 
-	    #if {$SCROLL[INFO][LINE] == -1}
-	    {
-		#var SCROLL[MODE] 0;
-		#var SCROLL[BOT_ROW] $SCROLL[OLD_ROW];
+			#if {$SCROLL[INFO][LINE] == -1}
+			{
+				#var SCROLL[MODE] 0;
+				#var SCROLL[BOT_ROW] $SCROLL[OLD_ROW];
 
 
-		#split 0 1;
-		#buffer end;
-	    }
+				#split 0 1;
+				#buffer end;
+			}
+		}
 	}
 	}
-    }
 }
 }
 
 
 #event {RECEIVED LINE}
 #event {RECEIVED LINE}
 {
 {
-    #if {$SCROLL[MODE] == 1}
-    {
-	#if {&BUFFER[] > $ROWS}
+	#if {$SCROLL[MODE] == 1}
 	{
 	{
-	    #list BUFFER del 1
-	};
-	#list BUFFER add {%0};
+		#if {&BUFFER[] > $ROWS}
+		{
+			#list BUFFER del 1
+		};
+		#list BUFFER add {%0};
 
 
-	#draw tile $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL] $BUFFER[%*];
-    }
+		#draw tile $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL] $BUFFER[%*];
+	}
 }
 }
 
 
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
@@ -884,32 +884,48 @@
 
 
 #alias {gemstone}
 #alias {gemstone}
 {
 {
-    #var gemstone {};
+	#var gemstone {};
 
 
-    #line oneshot #action {^GAMEHOST=%*} {#var gemstone[host] %%1};
-    #line oneshot #action {^GAMEPORT=%*} {#var gemstone[port] %%1};
-    #line oneshot #action {^KEY=%*} {#var gemstone[key] %%1};
+	#line oneshot #action {^GAMEHOST=%*} {#var gemstone[host] %%1};
+	#line oneshot #action {^GAMEPORT=%*} {#var gemstone[port] %%1};
+	#line oneshot #action {^KEY=%*} {#var gemstone[key] %%1};
 
 
-    #scan txt gemstone.sal;
+	#scan txt gemstone.sal;
 
 
-    #if {&gemstone[] != 3}
-    {
-        #showme Failed to load gemstone.sal file.;
-        #return
-    };
-    #ses gemstone $gemstone[host] $gemstone[port];
-    #send {$gemstone[key]};
-    #send {>/FE:JAVA}
+	#if {&gemstone[] != 3}
+	{
+		#showme Failed to load gemstone.sal file.;
+		#return
+	};
+	#ses gemstone $gemstone[host] $gemstone[port];
+	#send {$gemstone[key]};
+	#send {>/FE:JAVA}
 }
 }
 
 
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
-#nop 
+#nop Start a dated log file in the logs directory when a session connects. See
+#nop #help time for the available date options for #format %t.
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
 
 
+#event {SESSION CONNECTED}
+{
+	#format date %t %Y-%m-%d-%H-%M;
+
+	#log append logs/%0_$date.log
+}
+
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
-#nop 
+#nop Sometimes an error doesn't give enough information and it's useful to
+#nop see the calling script.
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
 
 
+#event {RECEIVED ERROR}
+{
+	#echo <118>%h { TOKENIZER };
+	#info tokenizer -1;
+	#echo <118>%h
+}
+
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------
 #nop 
 #nop 
 #nop -------------------------------------------------------------------------
 #nop -------------------------------------------------------------------------

+ 34 - 30
TODO

@@ -1,20 +1,34 @@
   - look into large variable handling, foreach, once again
   - look into large variable handling, foreach, once again
 
 
-  - tab window, add tab ordering and garbage collection
-
 ----------------
 ----------------
-  - ãã is messing up
+  - GMCP: MG.room.info { "exits": [ ] } gets parsed into {exits} {{1}{}}
 
 
-  - Add RECEIVED INPUT CHARACTER event / filter mouse input sequences.
+  - #map info save option
+
+  - check: #var bla { x};#draw scroll box 1 1 3 40 $bla
+
+  - set_line_screen stack call triggered on android
+
+  - input spell checking, #cursor display ?
+
+  - cp949toutf8 is missing some characters
 
 
-  - handle signals in the mainloop.
+  - look into named actions as a 4th argument
+
+  - look into adding #line quiet support to #buffer
+
+  - pruned tile handling
+
+  - Get discworld / aardwolf mxp to work for @sentix
+
+  - look into default input color
+
+  - Add RECEIVED INPUT CHARACTER event / filter mouse input sequences.
 
 
   - add ctrl-r support for scrollback
   - add ctrl-r support for scrollback
 
 
   - Add #event {SESSION CONNECTED} {5.1} option.
   - Add #event {SESSION CONNECTED} {5.1} option.
 
 
-  - Add the option to use + ? . and * as variable exit fields. 
-
   - TT++ HANDBOOK for meticulous organized details.
   - TT++ HANDBOOK for meticulous organized details.
 
 
   - vertical bar drawing
   - vertical bar drawing
@@ -25,6 +39,8 @@
 
 
   - finish BUFFER_SIZE replacement.
   - finish BUFFER_SIZE replacement.
 
 
+  - WSL sound, double check soundpack scripts for lag/stutter
+
   - WSL faq: #system cmd.exe /c start notepad
   - WSL faq: #system cmd.exe /c start notepad
 
 
   - update msdp scripts with #line msdp feature
   - update msdp scripts with #line msdp feature
@@ -35,6 +51,10 @@
 
 
 * 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
@@ -44,42 +64,26 @@
   - Work on VT2020 protocol (mouse click)
   - Work on VT2020 protocol (mouse click)
 
 
   - $var[%*][%*] support.
   - $var[%*][%*] support.
-  - make list sorting move nests as well
 
 
   - better #draw font support
   - better #draw font support
 
 
-  - case insensitive tabbing (partial start with rewrite)
-  - tabbing on directory structure.
-  - tabbing on dictionary
-
-#0  0x00005555555a5418 in tunnel_void (ses=0x555558a97b00, from=8004, room=1931506785, dir=1684955508) at mapper.c:4220
-#1  0x00005555555a599d in searchgrid_find (ses=0x555558a97b00, from=153, search=0x555558d8f850) at mapper.c:4336
-#2  0x00005555555afb44 in map_list (ses=0x555558a97b00, arg=0x5555572e1b95 "{} {} {} {$roomarea} {variable} {area_mapped}",
+  - tab completion on directory structure.
 
 
+  - pancake mode to display rooms at all levels and annotations
+  - Store the map filename to differentiate between maps.
   - #map list {<exits>} breaks on rooms that have e mapped to eu.
   - #map list {<exits>} breaks on rooms that have e mapped to eu.
   - finish landmarks
   - finish landmarks
   - map sandbox mode support (flags to disable saving?)
   - map sandbox mode support (flags to disable saving?)
   - add ghosting to fix #map flag nofollow exit cmd issues?
   - add ghosting to fix #map flag nofollow exit cmd issues?
-  ! #map legend support for unicode graphics.
-  - multi-line room symbols
-  - pancake mode to display rooms at all levels and annotations
-  - there might be a terrain density bug
-  - provide the coordinate of the X on the vtmap.
-  - add maze flag for maze handling.
   - Request: aura around the character position. Something similar to terrain dense narrow. Could improve visibility of the character position on big resolutions. Furthermor config to allow modification of the character terrain. 
   - Request: aura around the character position. Something similar to terrain dense narrow. Could improve visibility of the character position on big resolutions. Furthermor config to allow modification of the character terrain. 
   - vt map doesn't utilize all available space.
   - vt map doesn't utilize all available space.
   - Request: 'stop' #map center command, so i could see how the 'user' moves, rather map moves around him? 
   - Request: 'stop' #map center command, so i could see how the 'user' moves, rather map moves around him? 
   - #map uninsert <vnum>
   - #map uninsert <vnum>
   - make map spacing easier
   - make map spacing easier
-  - add configurable default symbol
-  - exit symbol?
-  - more data to #map list saving, and maybe easier sorting of tables.
   - event for failed #map move.
   - event for failed #map move.
   - look into #send triggering follow map.
   - look into #send triggering follow map.
   - add {roomdata} search to #map list
   - add {roomdata} search to #map list
 
 
-  - truncate prompt longer than split.
-
   - Make actions with a priority of 0. trigger always
   - Make actions with a priority of 0. trigger always
 
 
   - #draw table {1;2;3;4} {a;b;c;d}
   - #draw table {1;2;3;4} {a;b;c;d}
@@ -105,8 +109,6 @@
 
 
   - better color syntax highlighting configuration.
   - better color syntax highlighting configuration.
 
 
-  - Add #log delete/remove option.
-
   - See about adding SESSIONS to the list table.
   - See about adding SESSIONS to the list table.
 
 
   - Add debugger to syntax highlighter, substitution highlighing, 256 color support, and variable expansion.
   - Add debugger to syntax highlighter, substitution highlighing, 256 color support, and variable expansion.
@@ -131,14 +133,16 @@
 
 
   - http://tintin.sourceforge.net/board/viewtopic.php?p=8766#8766 (global verbose toggle?)
   - http://tintin.sourceforge.net/board/viewtopic.php?p=8766#8766 (global verbose toggle?)
 
 
-  - http://tintin.sourceforge.net/board/viewtopic.php?p=8745#8745 (verbose logging?)
-
   - See about adding ~/ handling for file names.
   - See about adding ~/ handling for file names.
 
 
+  - Look into adding basic EUC-KR support.
+
 --------------------------------------------------------------------------------
 --------------------------------------------------------------------------------
 
 
 * LOW PRIORITY
 * LOW PRIORITY
 
 
+  - ./configure might error on /dev/ptmx
+
   - Add a file handler.
   - Add a file handler.
 
 
   - multi-line buffer searches / captures / deletes
   - multi-line buffer searches / captures / deletes

+ 76 - 19
docs/help.html

@@ -616,8 +616,30 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          with macros. Subsequently many cursor commands only work properly when
          with macros. Subsequently many cursor commands only work properly when
          used within a macro or event.
          used within a macro or event.
 
 
-         </span><span style='color:#FFF'>#cursor tab &lt;list;scrollback&gt; &lt;backward|forward&gt;
-         </span><span style='color:#AAA'>  Tab through the given option(s) going forward or backward.
+         </span><span style='color:#FFF'>#cursor flag
+
+         </span><span style='color:#AAA'>EOL         end of line character(s)
+         ECHO        local echo
+         OVERTYPE    overtype mode
+
+         </span><span style='color:#FFF'>#cursor macro
+
+         </span><span style='color:#AAA'>PRESERVE    do not erase the macro from the macro input buffer
+         RESET       erase the macro input buffer
+
+         </span><span style='color:#FFF'>#cursor tab
+
+         </span><span style='color:#AAA'>CASELESS    makes tab completion caseless
+         COMPLETE    makes tab completion work while editing
+
+         DICTIONARY  performs tab completion on the dictionary
+         LIST        performs tab completion on the tab completion list
+         SCROLLBACK  performs tab completion on the scrollback buffer
+
+         BACKWARD    specifies tab completion to go backward
+         FORWARD     specifies tab completion to go forward
+
+         Multiple options can/must be specified at once.
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#ALIAS'>alias</a>, <a href='#HISTORY'>history</a>, <a href='#KEYPAD'>keypad</a>, <a href='#MACRO'>macro</a>, <a href='#SPEEDWALK'>speedwalk</a> and <a href='#TAB'>tab</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#ALIAS'>alias</a>, <a href='#HISTORY'>history</a>, <a href='#KEYPAD'>keypad</a>, <a href='#MACRO'>macro</a>, <a href='#SPEEDWALK'>speedwalk</a> and <a href='#TAB'>tab</a>.
 <a name='DAEMON'></a>
 <a name='DAEMON'></a>
@@ -687,6 +709,8 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          Nanosecond floating point precision is allowed. Delays will fire in
          Nanosecond floating point precision is allowed. Delays will fire in
          0.01 second intervals.
          0.01 second intervals.
 
 
+         Named delays are treated as one-shot tickers, see #help tick.
+
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #delay {1} {#show last};#show first
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #delay {1} {#show last};#show first
          This will print 'first', and 'last' around one second later.
          This will print 'first', and 'last' around one second later.
 
 
@@ -1071,6 +1095,9 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          </span><span style='color:#FFF'>RECEIVED INPUT [NAME]
          </span><span style='color:#FFF'>RECEIVED INPUT [NAME]
          </span><span style='color:#AAA'>  %0 raw text
          </span><span style='color:#AAA'>  %0 raw text
 
 
+         </span><span style='color:#FFF'>RECEIVED INPUT CHARACTER
+         </span><span style='color:#AAA'>  %0 character  %1 unicode index  %2 size  %3 width
+
          SEND OUTPUT            %0 raw text %1 size
          SEND OUTPUT            %0 raw text %1 size
          SENT OUTPUT            %0 raw text %1 size
          SENT OUTPUT            %0 raw text %1 size
 
 
@@ -1343,7 +1370,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
 
 </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.11b                    </span><span style='color:#0AA'>#
+      #</span><span style='color:#AAA'>                    T I N T I N + +   2.02.12                     </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'>#
@@ -1523,9 +1550,9 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
 
 </span><span style='color:#5F5'>         INDEX
 </span><span style='color:#5F5'>         INDEX
 
 
-         On this page you'll find an introduction to using TinTin++. Additional
+</span><span style='color:#AAA'>         On this page you'll find an introduction to using TinTin++. Additional
          information can be found in the individual help sections.
          information can be found in the individual help sections.
-
+</span><span style='color:#5F5'>
          Starting and Ending
          Starting and Ending
 </span><span style='color:#AAA'>
 </span><span style='color:#AAA'>
          The syntax for starting TinTin++ is: ./tt++ [command file]
          The syntax for starting TinTin++ is: ./tt++ [command file]
@@ -1804,6 +1831,7 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
          #info session will show information on the session.
          #info session will show information on the session.
          #info sessions will show information on all sessions.
          #info sessions will show information on all sessions.
          #info system will show some system information.
          #info system will show some system information.
+         #info tokenizer will show information about the script stack.
          #info unicode will show information on the provided character.
          #info unicode will show information on the provided character.
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CLASS'>class</a>, <a href='#DEBUG'>debug</a>, <a href='#IGNORE'>ignore</a>, <a href='#KILL'>kill</a> and <a href='#MESSAGE'>message</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CLASS'>class</a>, <a href='#DEBUG'>debug</a>, <a href='#IGNORE'>ignore</a>, <a href='#KILL'>kill</a> and <a href='#MESSAGE'>message</a>.
@@ -1871,19 +1899,19 @@ Terminal -&gt; Window Settings -&gt; Emulation.
 </span><span style='color:#5F5'>         LINE
 </span><span style='color:#5F5'>         LINE
 
 
 </span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #line </span><span style='color:#FFF'>{</span><span style='color:#AAA'>option</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>argument</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
 </span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #line </span><span style='color:#FFF'>{</span><span style='color:#AAA'>option</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>argument</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
-</span><span style='color:#5F5'>
-         Line sub commands that alter the argument.
-</span><span style='color:#AAA'>
+
+         </span><span style='color:#5F5'>Line options that alter the argument.
+
          </span><span style='color:#FFF'>#line strip &lt;argument&gt;
          </span><span style='color:#FFF'>#line strip &lt;argument&gt;
          </span><span style='color:#AAA'>  Argument is executed with all color codes stripped.
          </span><span style='color:#AAA'>  Argument is executed with all color codes stripped.
 
 
          </span><span style='color:#FFF'>#line substitute &lt;options&gt; &lt;argument&gt;
          </span><span style='color:#FFF'>#line substitute &lt;options&gt; &lt;argument&gt;
          </span><span style='color:#AAA'>  Argument is executed using the provided substitutions, available
          </span><span style='color:#AAA'>  Argument is executed using the provided substitutions, available
-           options are: arguments, colors, escapes, functions, secure, and
-           variables.
-</span><span style='color:#5F5'>
-         Line sub commands that alter how the line is executed.
-</span><span style='color:#AAA'>
+           options are: arguments, braces, colors, escapes, functions, secure,
+           and variables.
+
+         </span><span style='color:#5F5'>Line options that alter how the line is executed.
+
          </span><span style='color:#FFF'>#line background &lt;argument&gt;
          </span><span style='color:#FFF'>#line background &lt;argument&gt;
          </span><span style='color:#AAA'>  Prevent new session activation.
          </span><span style='color:#AAA'>  Prevent new session activation.
 
 
@@ -2282,12 +2310,36 @@ Terminal -&gt; Window Settings -&gt; Emulation.
 
 
 </span><span style='color:#5F5'>         LOG
 </span><span style='color:#5F5'>         LOG
 
 
-</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #log </span><span style='color:#FFF'>{</span><span style='color:#AAA'>append</span><span style='color:#FFF'>|</span><span style='color:#AAA'>overwrite</span><span style='color:#FFF'>|</span><span style='color:#AAA'>off</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>[filename]</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
+</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #log </span><span style='color:#FFF'>{</span><span style='color:#AAA'>option</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>argument</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
+
+         The log command allows logging session output to file. You can set the
+         data type to either plain, raw, or html with the config command.
 
 
-         Logs session output to a file, you can set the data type to either
-         plain, raw, or html with the config command.
+         </span><span style='color:#FFF'>#log append &lt;filename&gt;
+         </span><span style='color:#AAA'>  Start logging to the given file, if the file already exists it won't
+           be overwritten and data will be appended to the end.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#READ'>read</a>, <a href='#SCAN'>scan</a>, <a href='#TEXTIN'>textin</a> and <a href='#WRITE'>write</a>.
+         </span><span style='color:#FFF'>#log move &lt;filename_1&gt; &lt;filename_2&gt;
+         </span><span style='color:#AAA'>  Move filename_1 to filename_2. This can be any file and doesn't need
+           to be a log file.
+
+         </span><span style='color:#FFF'>#log overwrite &lt;filename&gt;
+         </span><span style='color:#AAA'>  Start logging to the given file, if the file already exists it will
+           be overwritten.
+
+         </span><span style='color:#FFF'>#log off
+         </span><span style='color:#AAA'>  Stop logging.
+
+         </span><span style='color:#FFF'>#log remove &lt;filename&gt;
+         </span><span style='color:#AAA'>  Remove the file. This can be any file and doesn't need to be a log
+           file.
+
+         </span><span style='color:#FFF'>#log timestamp &lt;format&gt;
+         </span><span style='color:#AAA'>  When set the timestamp will be prepended to each line logged to file.
+           The format will be formatted as a date using the strftime format
+           specifiers as described in #help time.
+
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#READ'>read</a>, <a href='#SCAN'>scan</a>, <a href='#TEXTIN'>textin</a>, <a href='#TIME'>time</a> and <a href='#WRITE'>write</a>.
 <a name='LOOP'></a>
 <a name='LOOP'></a>
 
 
 </span><span style='color:#5F5'>         LOOP
 </span><span style='color:#5F5'>         LOOP
@@ -2493,9 +2545,11 @@ Terminal -&gt; Window Settings -&gt; Emulation.
          </span><span style='color:#AAA'>  Lists all matching rooms and their distance. The following
          </span><span style='color:#AAA'>  Lists all matching rooms and their distance. The following
            search keywords are supported.
            search keywords are supported.
 
 
+           {distance}    &lt;arg&gt; will list rooms within given distance.
            {roomarea}    &lt;arg&gt; will list rooms with matching area name.
            {roomarea}    &lt;arg&gt; will list rooms with matching area name.
            {roomdesc}    &lt;arg&gt; will list rooms with matching room desc.
            {roomdesc}    &lt;arg&gt; will list rooms with matching room desc.
            {roomexits}   &lt;arg&gt; will list rooms with identical room exits.
            {roomexits}   &lt;arg&gt; will list rooms with identical room exits.
+                               Use * as an exit to ignore non pathdir exits.
            {roomflag}    &lt;arg&gt; will list rooms with matching room flags.
            {roomflag}    &lt;arg&gt; will list rooms with matching room flags.
            {roomid}      &lt;arg&gt; will list rooms with identical id name.
            {roomid}      &lt;arg&gt; will list rooms with identical id name.
            {roomname}    &lt;arg&gt; will list rooms with matching room name.
            {roomname}    &lt;arg&gt; will list rooms with matching room name.
@@ -3988,8 +4042,11 @@ Related</span><span style='color:#AAA'>: <a href='#ALL'>all</a>, <a href='#PORT'
 
 
          Adds a word to the tab completion list, alphabetically sorted.
          Adds a word to the tab completion list, alphabetically sorted.
 
 
-         If no tabs are defined tintin will use the scrollback buffer
-         for auto tab completion.
+         If no tabs are defined tintin will use the scrollback buffer for auto
+         tab completion.
+
+         Tabbing behavior can be modified with the #cursor tab command which
+         by default is bound to the tab key.
 
 
 </span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: You can remove a tab with the #untab command.
 </span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: You can remove a tab with the #untab command.
 
 

+ 58 - 1
mods/igr.mods

@@ -1,3 +1,60 @@
+May 2022        2.02.12
+------------------------------------------------------------------------------
+input.c         Added RECEIVED INPUT CHARACTER event that triggers on each
+                character added to the input buffer. %0 holds the character,
+                %1 the unicode index, %2 the byte size, %3 the character's
+                display width.
+
+cursor.c        Added #cursor tab caseless option to make tab completion case
+                incensitive.
+
+dict.c          Added #cursor tab dictionary option to tab through the
+                dictionary.
+
+log.c           Added #log timestamp <format>. The format follows strftime as
+                described in #help time. Timestamps will be prepended to each
+                line of log output.
+
+log.c           Added #log move <filename> <filename> to move files.
+
+log.c           Added #log remove <filename> to remove files.
+
+variable.c      #format %r now ignores color and escape codes.
+
+data.c          Added the #info tokenizer option to have a peek at the stack
+                of the scripting engine. Use case example:
+
+                #event {RECEIVED ERROR}
+                {
+                    #echo <118>%h { TOKENIZER };
+                    #info tokenizer -1;
+                    #echo <118>%h
+                }
+
+path.c          #path load now automatically adds reverse directions.
+
+map.c           Added support for #map list {roomflag} {!void} etc.
+
+line.c          Added #line substitute braces which will turn { and } into
+                \x7B and \x7D.
+
+map.c           Added #map list {{distance}{5}} to list all rooms within a
+                weighted distance of 5. Keep in mind this goes by weight,
+                which starts at 1.0 and increases by 2.0 per room by default.
+
+cursor.c        Added #cursor flag eol {cr|lf|crlf|crnul|off} to change the
+                default end of line character between \r \n \r\n and \r\0.
+
+log.c           Changed logging to where it logs data before it's wrapped by
+                the client.
+
+map.c           Added support for roomsymbol lengths up to 5 characters in
+                unicode, and 6 characters in ascii graphics mode.
+
+map.c           Added the option to #map list/find to use * as a roomexit.
+                This will make the search ignore non-pathdir exits without
+                an exit direction.
+
 Mar 2021        2.02.11
 Mar 2021        2.02.11
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 draw.c          #draw BALIGN will push text to the bottom if there aren't
 draw.c          #draw BALIGN will push text to the bottom if there aren't
@@ -37,7 +94,7 @@ math.c          Made #math / #if about 3x faster.
 
 
 math.c          Updated // to support powers other than 2 and 3.
 math.c          Updated // to support powers other than 2 and 3.
 
 
-regex.c         Changed %w to match any letter, number, or undescore instead
+regex.c         Changed %w to match any letter, number, or underscore instead
                 of just letters, to make it match \w. Same for %W.
                 of just letters, to make it match \w. Same for %W.
 
 
 Nov 2020        2.02.10
 Nov 2020        2.02.10

+ 11 - 0
src/banner.c

@@ -194,6 +194,17 @@ void banner_init(struct session *ses, char *arg1)
 	banner_website(ses, "Carrion Fields", "http://carrionfields.net", arg1);
 	banner_website(ses, "Carrion Fields", "http://carrionfields.net", arg1);
 	banner_address(ses, "Carrion Fields", "cf carrionfields.net 4449", arg1);
 	banner_address(ses, "Carrion Fields", "cf carrionfields.net 4449", arg1);
 	banner_expires(ses, "Carrion Fields", "2026", arg1);
 	banner_expires(ses, "Carrion Fields", "2026", arg1);
+
+	banner_create(ses, "RetroMUD", arg1);
+
+	banner_desc(ses, "RetroMUD",
+		"RetroMUD features over 100 levels of play, a huge array of character advancement\n"
+		"options, and dozens of quests across six different worlds. It's like six games\n"
+		"in one.", arg1);
+
+	banner_website(ses, "RetroMUD", "http://www.retromud.org", arg1);
+	banner_address(ses, "RetroMUD", "rm 96.126.116.118 3000", arg1);
+	banner_expires(ses, "RetroMUD", "2027", arg1);
 }
 }
 
 
 int total_banners()
 int total_banners()

+ 11 - 11
src/buffer.c

@@ -280,6 +280,14 @@ void add_line_buffer(struct session *ses, char *line, int prompt)
 		port_socket_printf(ses, ses->proxy, "%s%s", ses->scroll->input, prompt ? "" : "\n");
 		port_socket_printf(ses, ses->proxy, "%s%s", ses->scroll->input, prompt ? "" : "\n");
 	}
 	}
 
 
+	if (!HAS_BIT(ses->log->mode, LOG_FLAG_LOW))
+	{
+		if (ses->log->file)
+		{
+			logit(ses, ses->scroll->input, ses->log->file, LOG_FLAG_LINEFEED);
+		}
+	}
+
 	ses->scroll->buffer[ses->scroll->used] = calloc(1, sizeof(struct buffer_data));
 	ses->scroll->buffer[ses->scroll->used] = calloc(1, sizeof(struct buffer_data));
 
 
 	buffer = ses->scroll->buffer[ses->scroll->used];
 	buffer = ses->scroll->buffer[ses->scroll->used];
@@ -302,14 +310,6 @@ void add_line_buffer(struct session *ses, char *line, int prompt)
 
 
 	str_cpy(&ses->scroll->input, "");
 	str_cpy(&ses->scroll->input, "");
 
 
-	if (!HAS_BIT(ses->logmode, LOG_FLAG_LOW))
-	{
-		if (ses->logfile)
-		{
-			logit(ses, temp, ses->logfile, LOG_FLAG_LINEFEED);
-		}
-	}
-
 	if (gtd->chat)
 	if (gtd->chat)
 	{
 	{
 		chat_forward_session(ses, temp);
 		chat_forward_session(ses, temp);
@@ -1067,15 +1067,15 @@ DO_BUFFER(buffer_write)
 		{
 		{
 			show_message(ses, LIST_COMMAND, "#OK: WRITING BUFFER TO '%s'.", arg1);
 			show_message(ses, LIST_COMMAND, "#OK: WRITING BUFFER TO '%s'.", arg1);
 
 
-			loginit(ses, fp, ses->logmode + LOG_FLAG_OVERWRITE);
+			logheader(ses, fp, ses->log->mode + LOG_FLAG_OVERWRITE);
 
 
 			for (cnt = 0 ; cnt < ses->scroll->used ; cnt++)
 			for (cnt = 0 ; cnt < ses->scroll->used ; cnt++)
 			{
 			{
-				if (HAS_BIT(ses->logmode, LOG_FLAG_PLAIN))
+				if (HAS_BIT(ses->log->mode, LOG_FLAG_PLAIN))
 				{
 				{
 					strip_vt102_codes(ses->scroll->buffer[cnt]->str, arg2);
 					strip_vt102_codes(ses->scroll->buffer[cnt]->str, arg2);
 				}
 				}
-				else if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
+				else if (HAS_BIT(ses->log->mode, LOG_FLAG_HTML))
 				{
 				{
 					vt102_to_html(ses, ses->scroll->buffer[cnt]->str, arg2);
 					vt102_to_html(ses, ses->scroll->buffer[cnt]->str, arg2);
 				}
 				}

+ 13 - 13
src/config.c

@@ -477,11 +477,11 @@ DO_CONFIG(config_loglevel)
 	{
 	{
 		if (is_abbrev(arg2, "LOW"))
 		if (is_abbrev(arg2, "LOW"))
 		{
 		{
-			SET_BIT(ses->logmode, LOG_FLAG_LOW);
+			SET_BIT(ses->log->mode, LOG_FLAG_LOW);
 		}
 		}
 		else if (is_abbrev(arg2, "HIGH"))
 		else if (is_abbrev(arg2, "HIGH"))
 		{
 		{
-			DEL_BIT(ses->logmode, LOG_FLAG_LOW);
+			DEL_BIT(ses->log->mode, LOG_FLAG_LOW);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -490,7 +490,7 @@ DO_CONFIG(config_loglevel)
 			return NULL;
 			return NULL;
 		}
 		}
 	}
 	}
-	strcpy(arg2, HAS_BIT(ses->logmode, LOG_FLAG_LOW) ? "LOW" : "HIGH");
+	strcpy(arg2, HAS_BIT(ses->log->mode, LOG_FLAG_LOW) ? "LOW" : "HIGH");
 
 
 	return ses;
 	return ses;
 }
 }
@@ -502,21 +502,21 @@ DO_CONFIG(config_logmode)
 	{
 	{
 		if (is_abbrev(arg2, "HTML"))
 		if (is_abbrev(arg2, "HTML"))
 		{
 		{
-			SET_BIT(ses->logmode, LOG_FLAG_HTML);
-			DEL_BIT(ses->logmode, LOG_FLAG_PLAIN);
-			DEL_BIT(ses->logmode, LOG_FLAG_RAW);
+			SET_BIT(ses->log->mode, LOG_FLAG_HTML);
+			DEL_BIT(ses->log->mode, LOG_FLAG_PLAIN);
+			DEL_BIT(ses->log->mode, LOG_FLAG_RAW);
 		}
 		}
 		else if (is_abbrev(arg2, "PLAIN"))
 		else if (is_abbrev(arg2, "PLAIN"))
 		{
 		{
-			DEL_BIT(ses->logmode, LOG_FLAG_HTML);
-			SET_BIT(ses->logmode, LOG_FLAG_PLAIN);
-			DEL_BIT(ses->logmode, LOG_FLAG_RAW);
+			DEL_BIT(ses->log->mode, LOG_FLAG_HTML);
+			SET_BIT(ses->log->mode, LOG_FLAG_PLAIN);
+			DEL_BIT(ses->log->mode, LOG_FLAG_RAW);
 		}
 		}
 		else if (is_abbrev(arg2, "RAW"))
 		else if (is_abbrev(arg2, "RAW"))
 		{
 		{
-			DEL_BIT(ses->logmode, LOG_FLAG_HTML);
-			DEL_BIT(ses->logmode, LOG_FLAG_PLAIN);
-			SET_BIT(ses->logmode, LOG_FLAG_RAW);
+			DEL_BIT(ses->log->mode, LOG_FLAG_HTML);
+			DEL_BIT(ses->log->mode, LOG_FLAG_PLAIN);
+			SET_BIT(ses->log->mode, LOG_FLAG_RAW);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -525,7 +525,7 @@ DO_CONFIG(config_logmode)
 			return NULL;
 			return NULL;
 		}
 		}
 	}
 	}
-	strcpy(arg2, HAS_BIT(ses->logmode, LOG_FLAG_HTML) ? "HTML" : HAS_BIT(ses->logmode, LOG_FLAG_PLAIN) ? "PLAIN" : "RAW");
+	strcpy(arg2, HAS_BIT(ses->log->mode, LOG_FLAG_HTML) ? "HTML" : HAS_BIT(ses->log->mode, LOG_FLAG_PLAIN) ? "PLAIN" : "RAW");
 
 
 	return ses;
 	return ses;
 }
 }

+ 246 - 150
src/cursor.c

@@ -896,7 +896,7 @@ DO_CURSOR(cursor_delete)
 			{
 			{
 				break;
 				break;
 			}
 			}
-			size = get_utf8_width(&gtd->ses->input->buf[gtd->ses->input->raw_pos], &width);
+			size = get_utf8_width(&gtd->ses->input->buf[gtd->ses->input->raw_pos], &width, NULL);
 
 
 			if (width)
 			if (width)
 			{
 			{
@@ -950,7 +950,7 @@ DO_CURSOR(cursor_delete_word_left)
 
 
 	while (span_raw < index_raw)
 	while (span_raw < index_raw)
 	{
 	{
-		span_raw += get_vt102_width(gtd->ses, &gtd->ses->input->buf[gtd->ses->input->raw_pos], &width);
+		span_raw += get_vt102_width(gtd->ses, &gtd->ses->input->buf[span_raw], &width);
 
 
 		gtd->ses->input->str_pos -= width;
 		gtd->ses->input->str_pos -= width;
 	}
 	}
@@ -1180,10 +1180,18 @@ DO_CURSOR(cursor_enter_finish)
 	ses->input->raw_pos = 0;
 	ses->input->raw_pos = 0;
 	ses->input->str_pos = 0;
 	ses->input->str_pos = 0;
 
 
+	ses->input->str_off = 1;
 	ses->input->str_hid = 0;
 	ses->input->str_hid = 0;
 
 
 	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_EDIT);
 	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_EDIT);
 
 
+	if (ses == gtd->ses && gtd->ses->scroll->line != -1)
+	{
+		cursor_check_line(gtd->ses, "");
+
+		buffer_end(gtd->ses, "", "", "");
+	}
+
 	if (ses == gtd->ses && HAS_BIT(gtd->ses->flags, SES_FLAG_SPLIT))
 	if (ses == gtd->ses && HAS_BIT(gtd->ses->flags, SES_FLAG_SPLIT))
 	{
 	{
 		cursor_redraw_line(gtd->ses, "");
 		cursor_redraw_line(gtd->ses, "");
@@ -1197,6 +1205,57 @@ DO_CURSOR(cursor_flag)
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
 
 
+	if (is_abbrev(arg1, "EOL"))
+	{
+		if (*arg2 == 0)
+		{
+			TOG_BIT(ses->telopts, TELOPT_FLAG_CR|TELOPT_FLAG_LF);
+		}
+		else if (!strcasecmp(arg2, "CR"))
+		{
+			SET_BIT(ses->telopts, TELOPT_FLAG_CR);
+			DEL_BIT(ses->telopts, TELOPT_FLAG_LF);
+			DEL_BIT(ses->telopts, TELOPT_FLAG_NUL);
+		}
+		else if (!strcasecmp(arg2, "LF"))
+		{
+			DEL_BIT(ses->telopts, TELOPT_FLAG_CR);
+			SET_BIT(ses->telopts, TELOPT_FLAG_LF);
+			DEL_BIT(ses->telopts, TELOPT_FLAG_NUL);
+		}
+		else if (!strcasecmp(arg2, "CRLF") || !strcasecmp(arg2, "ON"))
+		{
+			SET_BIT(ses->telopts, TELOPT_FLAG_CR);
+			SET_BIT(ses->telopts, TELOPT_FLAG_LF);
+			DEL_BIT(ses->telopts, TELOPT_FLAG_NUL);
+		}
+		else if (!strcasecmp(arg2, "CRNUL"))
+		{
+			SET_BIT(ses->telopts, TELOPT_FLAG_CR);
+			DEL_BIT(ses->telopts, TELOPT_FLAG_LF);
+			SET_BIT(ses->telopts, TELOPT_FLAG_NUL);
+		}
+		else if (!strcasecmp(arg2, "OFF"))
+		{
+			DEL_BIT(ses->telopts, TELOPT_FLAG_CR);
+			DEL_BIT(ses->telopts, TELOPT_FLAG_LF);
+			DEL_BIT(ses->telopts, TELOPT_FLAG_NUL);
+		}
+		else
+		{
+			show_error(gtd->ses, LIST_COMMAND, "#SYNTAX: #CURSOR {FLAG} {EOL} {CR|LF|CRLF|CRNUL|OFF}.");
+			return;
+		}
+
+		show_message(gtd->ses, LIST_COMMAND, "#CURSOR FLAG EOL HAS BEEN SET TO: %s",
+			HAS_BIT(ses->telopts, TELOPT_FLAG_CR|TELOPT_FLAG_LF) == 0 ? "OFF" :
+			HAS_BIT(ses->telopts, TELOPT_FLAG_CR|TELOPT_FLAG_NUL) == (TELOPT_FLAG_CR|TELOPT_FLAG_NUL) ? "CRNUL" :
+			HAS_BIT(ses->telopts, TELOPT_FLAG_CR|TELOPT_FLAG_LF) == TELOPT_FLAG_CR ? "CR" :
+			HAS_BIT(ses->telopts, TELOPT_FLAG_CR|TELOPT_FLAG_LF) == TELOPT_FLAG_LF ? "LF" : "CRLF");
+
+		return;
+	}
+
 	if (is_abbrev(arg1, "ECHO"))
 	if (is_abbrev(arg1, "ECHO"))
 	{
 	{
 		if (*arg2 == 0)
 		if (*arg2 == 0)
@@ -1218,7 +1277,7 @@ DO_CURSOR(cursor_flag)
 		return;
 		return;
 	}
 	}
 
 
-	if (is_abbrev(arg1, "INSERT"))
+	if (is_abbrev(arg1, "INSERT") || is_abbrev(arg1, "OVERTYPE"))
 	{
 	{
 		if (*arg2 == 0)
 		if (*arg2 == 0)
 		{
 		{
@@ -1239,7 +1298,7 @@ DO_CURSOR(cursor_flag)
 		return;
 		return;
 	}
 	}
 
 
-	show_error(gtd->ses, LIST_COMMAND, "#SYNTAX: #CURSOR {FLAG} {ECHO|INSERT} {ON|OFF}.");
+	show_error(gtd->ses, LIST_COMMAND, "#SYNTAX: #CURSOR {FLAG} {ECHO|EOL|INSERT} {ON|OFF}.");
 }
 }
 
 
 DO_CURSOR(cursor_get)
 DO_CURSOR(cursor_get)
@@ -1765,7 +1824,7 @@ DO_CURSOR(cursor_move_left_word)
 
 
 	while (span_raw < index_raw)
 	while (span_raw < index_raw)
 	{
 	{
-		span_raw += get_vt102_width(gtd->ses, &gtd->ses->input->buf[gtd->ses->input->raw_pos], &width);
+		span_raw += get_vt102_width(gtd->ses, &gtd->ses->input->buf[span_raw], &width);
 
 
 		gtd->ses->input->str_pos -= width;
 		gtd->ses->input->str_pos -= width;
 	}
 	}
@@ -1805,7 +1864,7 @@ DO_CURSOR(cursor_move_right)
 				{
 				{
 					break;
 					break;
 				}
 				}
-				size = get_utf8_width(&gtd->ses->input->buf[gtd->ses->input->raw_pos], &width);
+				size = get_utf8_width(&gtd->ses->input->buf[gtd->ses->input->raw_pos], &width, NULL);
 
 
 				if (width)
 				if (width)
 				{
 				{
@@ -2336,86 +2395,7 @@ DO_CURSOR(cursor_info)
 	original tab cycling by Ben Love
 	original tab cycling by Ben Love
 */
 */
 
 
-
-DO_CURSOR(cursor_tab)
-{
-	char arg1[BUFFER_SIZE];
-	int flags = 0;
-
-	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
-
-	while (*arg)
-	{
-		if (is_abbrev(arg1, "LIST"))
-		{
-			SET_BIT(flags, TAB_FLAG_LIST);
-		}
-		else if (is_abbrev(arg1, "SCROLLBACK"))
-		{
-			SET_BIT(flags, TAB_FLAG_SCROLLBACK);
-		}
-		else if (is_abbrev(arg1, "COMPLETE"))
-		{
-			SET_BIT(flags, TAB_FLAG_COMPLETE);
-		}
-
-		arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
-
-		if (*arg == COMMAND_SEPARATOR)
-		{
-			arg++;
-		}
-	}
-
-	if (is_abbrev(arg1, "FORWARD"))
-	{
-		if (!HAS_BIT(flags, TAB_FLAG_COMPLETE) && inputline_editor())
-		{
-			sprintf(arg1, "%*s", gtd->ses->tab_width, "");
-
-			inputline_insert(arg1, -1);
-
-			return cursor_redraw_line(ses, arg);
-		}
-
-		if (!HAS_BIT(flags, TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
-		{
-			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {LIST|SCROLLBACK} FORWARD");
-		}
-		else
-		{
-			cursor_tab_forward(ses, ntos(flags));
-		}
-		SET_BIT(flags, TAB_FLAG_FORWARD);
-	}
-	else if (is_abbrev(arg1, "BACKWARD"))
-	{
-		if (!HAS_BIT(flags, TAB_FLAG_COMPLETE) && inputline_editor())
-		{
-			sprintf(arg1, "%*s", gtd->ses->tab_width, "");
-			
-			inputline_insert(arg1, 0);
-
-			return cursor_redraw_line(ses, arg);
-		}
-
-		if (!HAS_BIT(flags, TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
-		{
-			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {LIST|SCROLLBACK} BACKWARD");
-		}
-		else
-		{
-			cursor_tab_backward(ses, ntos(flags));
-		}
-		SET_BIT(flags, TAB_FLAG_BACKWARD);
-	}
-	else
-	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {LIST;SCROLLBACK} <BACKWARD|FORWARD>");
-	}
-}
-
-int cursor_tab_add(int stop_after_first)
+int cursor_tab_add(int flag)
 {
 {
 	struct listroot *tab_root = gtd->ses->list[LIST_TAB];
 	struct listroot *tab_root = gtd->ses->list[LIST_TAB];
 	struct listroot *cmd_root = gtd->ses->list[LIST_COMMAND];
 	struct listroot *cmd_root = gtd->ses->list[LIST_COMMAND];
@@ -2432,31 +2412,42 @@ int cursor_tab_add(int stop_after_first)
 		{
 		{
 			node = tab_root->list[tab_root->update];
 			node = tab_root->list[tab_root->update];
 
 
-			if (*node->arg1 == *tail && !strncmp(node->arg1, tail, tail_len))
+			if (HAS_BIT(flag, TAB_FLAG_CASELESS))
 			{
 			{
-				if (search_node_list(cmd_root, node->arg1))
+				if (strncasecmp(node->arg1, tail, tail_len) != 0)
 				{
 				{
 					continue;
 					continue;
 				}
 				}
-				create_node_list(cmd_root, node->arg1, "", "", "");
-
-				if (node->shots && --node->shots == 0)
+			}
+			else
+			{
+				if (*node->arg1 != *tail || strncmp(node->arg1, tail, tail_len) != 0)
 				{
 				{
-					delete_node_list(gtd->ses, LIST_TAB, node);
+					continue;
 				}
 				}
+			}
 
 
-				if (stop_after_first)
-				{
-					return TRUE;
-				}
+			if (search_node_list(cmd_root, node->arg1))
+			{
+				continue;
+			}
+			create_node_list(cmd_root, node->arg1, "", "", "");
+
+			if (node->shots && --node->shots == 0)
+			{
+				delete_node_list(gtd->ses, LIST_TAB, node);
+			}
+
+			if (HAS_BIT(flag, TAB_FLAG_FORWARD))
+			{
+				return TRUE;
 			}
 			}
 		}
 		}
 	}
 	}
 	return FALSE;
 	return FALSE;
 }
 }
 
 
-
-int cursor_scrollback_tab_add(int stop_after_first)
+int cursor_scrollback_tab_add(int flag)
 {
 {
 	char tab[BUFFER_SIZE], buf[BUFFER_SIZE];
 	char tab[BUFFER_SIZE], buf[BUFFER_SIZE];
 	struct listroot *root = gtd->ses->list[LIST_COMMAND];
 	struct listroot *root = gtd->ses->list[LIST_COMMAND];
@@ -2494,71 +2485,83 @@ int cursor_scrollback_tab_add(int stop_after_first)
 				ptb++;
 				ptb++;
 			}
 			}
 
 
-			if (*ptb == *tail && !strncmp(ptb, tail, tail_len))
+			if (HAS_BIT(flag, TAB_FLAG_CASELESS))
 			{
 			{
-				ptt = tab;
-
-				for (tab_len = 0 ; tab_len < tail_len ; tab_len++)
+				if (strncasecmp(ptb, tail, tail_len) != 0)
 				{
 				{
-					*ptt++ = *ptb++;
+					goto end;
 				}
 				}
-
-				while (*ptb && *ptb != ' ')
+			}
+			else
+			{
+				if (*ptb != *tail || strncmp(ptb, tail, tail_len) != 0)
 				{
 				{
-					switch (*ptb)
-					{
-						case ';':
-						case '.':
-						case ',':
-						case '!':
-						case '?':
-						case ':':
-						case '"':
-							*ptt++ = 0;
-							ptb++;
-							break;
-
-						default:
-							*ptt++ = *ptb++;
-							break;
-					}
+					goto end;
 				}
 				}
-				*ptt = 0;
+			}
+			ptt = tab;
+
+			for (tab_len = 0 ; tab_len < tail_len ; tab_len++)
+			{
+				*ptt++ = *ptb++;
+			}
 
 
-				if (search_node_list(gtd->ses->list[LIST_COMMAND], tab))
+			while (*ptb && *ptb != ' ')
+			{
+				switch (*ptb)
 				{
 				{
-					continue;
+					case ';':
+					case '.':
+					case ',':
+					case '!':
+					case '?':
+					case ':':
+					case '"':
+						*ptt++ = 0;
+						ptb++;
+						break;
+
+					default:
+						*ptt++ = *ptb++;
+						break;
 				}
 				}
+			}
+			*ptt = 0;
 
 
-				node = create_node_list(gtd->ses->list[LIST_COMMAND], tab, "", "", "");
+			if (search_node_list(gtd->ses->list[LIST_COMMAND], tab))
+			{
+				goto end;
+			}
 
 
-				node->val32[0] = scroll_cnt;
+			node = create_node_list(gtd->ses->list[LIST_COMMAND], tab, "", "", "");
 
 
-				if (stop_after_first)
-				{
-					return TRUE;
-				}
+			node->val32[0] = scroll_cnt;
 
 
-				if (root->used > 100)
-				{
-					return FALSE;
-				}
+			if (HAS_BIT(flag, TAB_FLAG_FORWARD))
+			{
+				return TRUE;
 			}
 			}
 
 
+			if (root->used > 100)
+			{
+				return FALSE;
+			}
+
+			end:
+
 			while (*ptb && !is_space(*ptb))
 			while (*ptb && !is_space(*ptb))
 			{
 			{
 				ptb++;
 				ptb++;
 			}
 			}
 		}
 		}
 	}
 	}
-
 	return FALSE;
 	return FALSE;
 }
 }
 
 
-DO_CURSOR(cursor_tab_forward)
+void cursor_tab_forward(struct session *ses, int flag)
 {
 {
 	struct listroot *root = gtd->ses->list[LIST_COMMAND];
 	struct listroot *root = gtd->ses->list[LIST_COMMAND];
-	int tab_found, flags;
+	int tab_found;
 
 
 	if (inputline_tab_valid() == FALSE)
 	if (inputline_tab_valid() == FALSE)
 	{
 	{
@@ -2576,16 +2579,19 @@ DO_CURSOR(cursor_tab_forward)
 
 
 	tab_found = 0;
 	tab_found = 0;
 
 
-	flags = atoi(arg);
+	if (tab_found == 0 && HAS_BIT(flag, TAB_FLAG_LIST))
+	{
+		tab_found = cursor_tab_add(flag);
+	}
 
 
-	if (tab_found == 0 && HAS_BIT(flags, TAB_FLAG_LIST))
+	if (tab_found == 0 && HAS_BIT(flag, TAB_FLAG_SCROLLBACK))
 	{
 	{
-		tab_found = cursor_tab_add(TRUE);
+		tab_found = cursor_scrollback_tab_add(flag);
 	}
 	}
 
 
-	if (tab_found == 0 && HAS_BIT(flags, TAB_FLAG_SCROLLBACK))
+	if (tab_found == 0 && HAS_BIT(flag, TAB_FLAG_DICTIONARY))
 	{
 	{
-		tab_found = cursor_scrollback_tab_add(TRUE);
+		tab_found = cursor_dictionary_tab_add(flag);
 	}
 	}
 
 
 	if (tab_found == 0)
 	if (tab_found == 0)
@@ -2601,10 +2607,9 @@ DO_CURSOR(cursor_tab_forward)
 	cursor_end(ses, "");
 	cursor_end(ses, "");
 }
 }
 
 
-DO_CURSOR(cursor_tab_backward)
+void cursor_tab_backward(struct session *ses, int flag)
 {
 {
 	struct listroot *root = ses->list[LIST_COMMAND];
 	struct listroot *root = ses->list[LIST_COMMAND];
-	int flags;
 
 
 	if (inputline_tab_valid() == FALSE)
 	if (inputline_tab_valid() == FALSE)
 	{
 	{
@@ -2624,16 +2629,19 @@ DO_CURSOR(cursor_tab_backward)
 
 
 		inputline_cap("");
 		inputline_cap("");
 
 
-		flags = atoi(arg);
+		if (HAS_BIT(flag, TAB_FLAG_LIST))
+		{
+			cursor_tab_add(flag);
+		}
 
 
-		if (HAS_BIT(flags, TAB_FLAG_LIST))
+		if (HAS_BIT(flag, TAB_FLAG_SCROLLBACK))
 		{
 		{
-			cursor_tab_add(FALSE);
+			cursor_scrollback_tab_add(flag);
 		}
 		}
 
 
-		if (HAS_BIT(flags, TAB_FLAG_SCROLLBACK))
+		if (HAS_BIT(flag, TAB_FLAG_DICTIONARY))
 		{
 		{
-			cursor_scrollback_tab_add(FALSE);
+			cursor_dictionary_tab_add(flag);
 		}
 		}
 	}
 	}
 	else
 	else
@@ -2645,3 +2653,91 @@ DO_CURSOR(cursor_tab_backward)
 
 
 	cursor_end(ses, "");
 	cursor_end(ses, "");
 }
 }
+
+DO_CURSOR(cursor_tab)
+{
+	char arg1[BUFFER_SIZE];
+	int flag = 0;
+
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
+
+	while (*arg)
+	{
+		if (is_abbrev(arg1, "CASELESS"))
+		{
+			SET_BIT(flag, TAB_FLAG_CASELESS);
+		}
+		else if (is_abbrev(arg1, "COMPLETE"))
+		{
+			SET_BIT(flag, TAB_FLAG_COMPLETE);
+		}
+		else if (is_abbrev(arg1, "DICTIONARY"))
+		{
+			SET_BIT(flag, TAB_FLAG_DICTIONARY);
+		}
+		else if (is_abbrev(arg1, "LIST"))
+		{
+			SET_BIT(flag, TAB_FLAG_LIST);
+		}
+		else if (is_abbrev(arg1, "SCROLLBACK"))
+		{
+			SET_BIT(flag, TAB_FLAG_SCROLLBACK);
+		}
+
+		arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
+
+		if (*arg == COMMAND_SEPARATOR)
+		{
+			arg++;
+		}
+	}
+
+	if (is_abbrev(arg1, "FORWARD"))
+	{
+		SET_BIT(flag, TAB_FLAG_FORWARD);
+
+		if (!HAS_BIT(flag, TAB_FLAG_COMPLETE) && inputline_editor())
+		{
+			sprintf(arg1, "%*s", gtd->ses->tab_width, "");
+
+			inputline_insert(arg1, -1);
+
+			return cursor_redraw_line(ses, arg);
+		}
+
+		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
+		{
+			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {DICTIONARY|LIST|SCROLLBACK} FORWARD");
+		}
+		else
+		{
+			cursor_tab_forward(ses, flag);
+		}
+	}
+	else if (is_abbrev(arg1, "BACKWARD"))
+	{
+		SET_BIT(flag, TAB_FLAG_BACKWARD);
+
+		if (!HAS_BIT(flag, TAB_FLAG_COMPLETE) && inputline_editor())
+		{
+			sprintf(arg1, "%*s", gtd->ses->tab_width, "");
+			
+			inputline_insert(arg1, 0);
+
+			return cursor_redraw_line(ses, arg);
+		}
+
+		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
+		{
+			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {DICTIONARY|LIST|SCROLLBACK} BACKWARD");
+		}
+		else
+		{
+			cursor_tab_backward(ses, flag);
+		}
+	}
+	else
+	{
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {DICTIONARY;LIST;SCROLLBACK} <BACKWARD|FORWARD>");
+	}
+}

+ 56 - 29
src/data.c

@@ -27,6 +27,8 @@
 
 
 #include <limits.h>
 #include <limits.h>
 
 
+extern char **environ;
+
 struct listroot *init_list(struct session *ses, int type, int size)
 struct listroot *init_list(struct session *ses, int type, int size)
 {
 {
 	struct listroot *listhead;
 	struct listroot *listhead;
@@ -102,23 +104,25 @@ struct listroot *copy_list(struct session *ses, struct listroot *sourcelist, int
 					break;
 					break;
 
 
 				case LIST_BUTTON:
 				case LIST_BUTTON:
-				case LIST_DELAY:
 				case LIST_EVENT:
 				case LIST_EVENT:
-				case LIST_TICKER:
+//				case LIST_TICKER:
 				case LIST_PATHDIR:
 				case LIST_PATHDIR:
 					node->val64 = sourcelist->list[i]->val64;
 					node->val64 = sourcelist->list[i]->val64;
-/*
-					node->val16[0] = sourcelist->list[i]->val16[0];
-					node->val16[1] = sourcelist->list[i]->val16[1];
-					node->val16[2] = sourcelist->list[i]->val16[2];
-					node->val16[3] = sourcelist->list[i]->val16[3];
-*/
 					break;
 					break;
 
 
 				case LIST_VARIABLE:
 				case LIST_VARIABLE:
 					copy_nest_node(ses->list[type], node, sourcelist->list[i]);
 					copy_nest_node(ses->list[type], node, sourcelist->list[i]);
 					break;
 					break;
 
 
+				case LIST_TICKER:
+					node->val64 = gtd->utime + (long long) (tintoi(node->arg3) * 1000000.0);
+
+					if (node->val64 < gtd->utime_next_tick)
+					{
+						gtd->utime_next_tick = node->val64;
+					}
+					break;
+
 				default:
 				default:
 					if (sourcelist->list[i]->val64)
 					if (sourcelist->list[i]->val64)
 					{
 					{
@@ -161,26 +165,6 @@ struct listnode *create_node_list(struct listroot *root, char *arg1, char *arg2,
 
 
 //	printf("debug: %p [%p] (%d) (%s) (%s)\n", root, root->ses, root->type, node->arg1, node->arg3);
 //	printf("debug: %p [%p] (%d) (%s) (%s)\n", root, root->ses, root->type, node->arg1, node->arg3);
 
 
-	switch (root->type)
-	{
-		case LIST_DELAY:
-			node->val64 = (long long) tintoi(node->arg1);
-
-			if (node->val64 < gtd->utime_next_delay)
-			{
-				gtd->utime_next_delay = node->val64;
-			}
-			break;
-
-		case LIST_TICKER:
-			node->val64 = gtd->utime + (long long) tintoi(arg3) * 1000000.0;
-
-			if (node->val64 < gtd->utime_next_tick)
-			{
-				gtd->utime_next_tick = node->val64;
-			}
-			break;
-	}
 
 
 	if (gtd->level->shots)
 	if (gtd->level->shots)
 	{
 	{
@@ -202,6 +186,25 @@ struct listnode *create_node_list(struct listroot *root, char *arg1, char *arg2,
 		case LIST_SUBSTITUTE:
 		case LIST_SUBSTITUTE:
 			node->regex = tintin_regexp_compile(root->ses, node, node->arg1, 0);
 			node->regex = tintin_regexp_compile(root->ses, node, node->arg1, 0);
 			break;
 			break;
+
+		case LIST_DELAY:
+			node->val64 = (long long) tintoi(node->arg1);
+
+			if (node->val64 < gtd->utime_next_delay)
+			{
+				gtd->utime_next_delay = node->val64;
+			}
+			break;
+
+		case LIST_TICKER:
+			node->val64 = gtd->utime + (long long) (tintoi(arg3) * 1000000.0);
+
+			if (node->val64 < gtd->utime_next_tick)
+			{
+				gtd->utime_next_tick = node->val64;
+			}
+			break;
+
 	}
 	}
 
 
 	return insert_node_list(root, node);
 	return insert_node_list(root, node);
@@ -1327,6 +1330,13 @@ DO_COMMAND(do_info)
 
 
 		switch (*arg1 % 32)
 		switch (*arg1 % 32)
 		{
 		{
+			case CTRL_B:
+				if (is_abbrev(arg1, "BIG5TOUTF8"))
+				{
+					big5toutf8_info(ses);
+				}
+				break;
+
 			case CTRL_C:
 			case CTRL_C:
 				if (is_abbrev(arg1, "CPU"))
 				if (is_abbrev(arg1, "CPU"))
 				{
 				{
@@ -1607,13 +1617,26 @@ DO_COMMAND(do_info)
 				}
 				}
 				break;
 				break;
 
 
+			case CTRL_T:
+				if (is_abbrev(arg1, "TOKENIZER"))
+				{
+					int index = URANGE(0, gtd->script_index + atoi(arg2), gtd->script_index);
+					struct scriptroot *root = gtd->script_stack[index];
+
+					tintin_printf2(ses, "#INFO TOKENIZER: SCRIPT_INDEX = %d", index);
+					tintin_printf2(ses, "#INFO TOKENIZER: SESSION_NAME = %s", root->ses->name);
+					tintin_printf2(ses, "#INFO TOKENIZER: LIST_TYPE    = %s", list_table[root->list].name);
+					tintin_printf2(ses, "#INFO TOKENIZER: LOCAL_VARS   = %d", root->local->used);
+					tintin_printf2(ses, "#INFO TOKENIZER: SCRIPT       =\n%s", view_script(ses, root));
+				}
+				break;
 			case CTRL_U:
 			case CTRL_U:
 				if (is_abbrev(arg1, "UNICODE"))
 				if (is_abbrev(arg1, "UNICODE"))
 				{
 				{
 					int size, width, index;
 					int size, width, index;
 
 
 					size = get_utf8_size(arg2);
 					size = get_utf8_size(arg2);
-					get_utf8_width(arg2, &width);
+					get_utf8_width(arg2, &width, NULL);
 					get_utf8_index(arg2, &index);
 					get_utf8_index(arg2, &index);
 
 
 					tintin_printf2(ses, "#INFO UNICODE: %s:  is_utf8_head  = %d (%s)", arg2, is_utf8_head(arg2), is_utf8_head(arg2) ? "true" : "false");
 					tintin_printf2(ses, "#INFO UNICODE: %s:  is_utf8_head  = %d (%s)", arg2, is_utf8_head(arg2), is_utf8_head(arg2) ? "true" : "false");
@@ -1622,6 +1645,10 @@ DO_COMMAND(do_info)
 					tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_index = %d (decimal)", arg2, index);
 					tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_index = %d (decimal)", arg2, index);
 					tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_index = %x (hexadecimal)", arg2, index);
 					tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_index = %x (hexadecimal)", arg2, index);
 				}
 				}
+				else if (is_abbrev(arg1, "UTF8TOBIG5"))
+				{
+					utf8tobig5_info(ses);
+				}
 				break;
 				break;
 		}
 		}
 		if (*gtd->is_result == 0)
 		if (*gtd->is_result == 0)

+ 80 - 1
src/dict.c

@@ -176,6 +176,82 @@ int spellcheck_count(struct session *ses, char *in)
 	return cnt;
 	return cnt;
 }
 }
 
 
+int cursor_dictionary_tab_add(int flag)
+{
+	struct listroot *cmd_root = gtd->ses->list[LIST_COMMAND];
+	struct listnode *node;
+	char *tail, *word, buf[50];
+	int tail_len, i, hash, val;
+
+	if (dictionary == NULL)
+	{
+		dictionary_init();
+	}
+
+	tail     = cmd_root->list[0]->arg1;
+	tail_len = str_len(tail);
+
+	if (!is_alpha(*tail))
+	{
+		return FALSE;
+	}
+
+	hash = tolower((int) *tail) - 'a';
+
+	i = URANGE(0, cmd_root->list[cmd_root->used - 1]->val32[1], cmd_root->used - 1);
+
+	for ( ; i < dictionary->listsize[hash] ; i++)
+	{
+		word = wordlist[hash] + dictionary->wordindex[hash][i];
+
+		if (HAS_BIT(flag, TAB_FLAG_CASELESS))
+		{
+			val = strncasecmp(word, tail + 1, tail_len - 1);
+		}
+		else
+		{
+			if (*word < tail[1])
+			{
+				continue;
+			}
+			val = strncmp(word, tail + 1, tail_len - 1);
+		}
+
+		if (val < 0)
+		{
+			continue;
+		}
+
+		if (val > 0)
+		{
+			return FALSE;
+		}
+
+		buf[0] = tail[0];
+		strcpy(buf + 1, word);
+
+		if (search_node_list(cmd_root, buf))
+		{
+			continue;
+		}
+
+		node = create_node_list(cmd_root, buf, "", "", "");
+
+		node->val32[1] = i;
+
+		if (HAS_BIT(flag, TAB_FLAG_FORWARD))
+		{
+			return TRUE;
+		}
+
+		if (cmd_root->used > 100)
+		{
+			return FALSE;
+		}
+	}
+	return FALSE;
+}
+
 DO_COMMAND(do_dictionary)
 DO_COMMAND(do_dictionary)
 {
 {
 	int hash, index;
 	int hash, index;
@@ -191,7 +267,10 @@ DO_COMMAND(do_dictionary)
 	{
 	{
 		show_message(ses, LIST_COMMAND, "#SYNTAX: #DICTIONARY {WORD}");
 		show_message(ses, LIST_COMMAND, "#SYNTAX: #DICTIONARY {WORD}");
 
 
-		wordlist[0][0] = 0;
+		for (hash = 0 ; hash < 26 ; hash++)
+		{
+			printf("hash %c = %d\n", 'A' + hash, dictionary->listsize[hash]);
+		}
 
 
 		return ses;
 		return ses;
 	}
 	}

+ 5 - 3
src/draw.c

@@ -117,7 +117,7 @@ struct draw_type draw_table[] =
 	{       "LINE",      "Draw a line.",                      DRAW_FLAG_NONE, draw_line },
 	{       "LINE",      "Draw a line.",                      DRAW_FLAG_NONE, draw_line },
 	{       "MAP",       "Draw the map.",                     DRAW_FLAG_NONE, draw_map },
 	{       "MAP",       "Draw the map.",                     DRAW_FLAG_NONE, draw_map },
 	{       "RAIN",      "Draw digital rain.",                DRAW_FLAG_NONE, draw_rain },
 	{       "RAIN",      "Draw digital rain.",                DRAW_FLAG_NONE, draw_rain },
-	{       "SIDE",      "Draw a line with corners.",         DRAW_FLAG_BOXED, draw_side },
+	{       "SIDE",      "Draw a line with corners.",         DRAW_FLAG_CORNERED, draw_side },
 	{       "TABLE",     "Draw a table.",                     DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT|DRAW_FLAG_TOP|DRAW_FLAG_BOT, draw_table_grid },
 	{       "TABLE",     "Draw a table.",                     DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT|DRAW_FLAG_TOP|DRAW_FLAG_BOT, draw_table_grid },
 	{       "TILE",      "Draw a tile.",                      DRAW_FLAG_NONE, draw_square },
 	{       "TILE",      "Draw a tile.",                      DRAW_FLAG_NONE, draw_square },
 	{       "",          "",                                  DRAW_FLAG_NONE, NULL }
 	{       "",          "",                                  DRAW_FLAG_NONE, NULL }
@@ -444,8 +444,10 @@ DO_COMMAND(do_draw)
 	{
 	{
 		if (is_abbrev(arg1, draw_table[index].name))
 		if (is_abbrev(arg1, draw_table[index].name))
 		{
 		{
-			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 = get_arg_in_braces(ses, arg, arg1, GET_ONE);
+			arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
+//			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);
 
 
 			top_row = get_row_index_arg(ses, arg1);
 			top_row = get_row_index_arg(ses, arg1);
 			top_col = get_col_index_arg(ses, arg2);
 			top_col = get_col_index_arg(ses, arg2);

+ 2 - 2
src/event.c

@@ -182,9 +182,9 @@ int check_all_events(struct session *ses, int flags, int args, int vars, char *f
 		return 0;
 		return 0;
 	}
 	}
 
 
-	sub = HAS_BIT(flags, SUB_SEC) ? SUB_ARG|SUB_SEC : SUB_ARG;
+	sub = HAS_BIT(flags, SUB_SEC) ? SUB_ARG|SUB_SEC : HAS_BIT(flags, SUB_BRA) ? SUB_ARG|SUB_BRA : SUB_ARG;
 
 
-	DEL_BIT(flags, SUB_ARG|SUB_SEC);
+	DEL_BIT(flags, SUB_ARG|SUB_SEC|SUB_BRA);
 
 
 	if (flags == 0)
 	if (flags == 0)
 	{
 	{

+ 32 - 32
src/gui.h

@@ -132,7 +132,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#class world_tab kill;\n"
 "	#class world_tab kill;\n"
 "	#class profile_tab kill;\n"
 "	#class profile_tab kill;\n"
 "\n"
 "\n"
-"	#draw tile 4 1 -4 26 {\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n};\n"
+"	#draw tile 4 1 -4 26 { };\n"
 "\n"
 "\n"
 "	#if {&worldlist[] == 0}\n"
 "	#if {&worldlist[] == 0}\n"
 "	{\n"
 "	{\n"
@@ -160,7 +160,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#class world_tab kill;\n"
 "	#class world_tab kill;\n"
 "	#class profile_tab kill;\n"
 "	#class profile_tab kill;\n"
 "\n"
 "\n"
-"	#draw tile 4 1 -4 26 {\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n};\n"
+"	#draw tile 4 1 -4 26 { };\n"
 "\n"
 "\n"
 "	#if {&info[BANNERS][] == 0}\n"
 "	#if {&info[BANNERS][] == 0}\n"
 "	{\n"
 "	{\n"
@@ -431,6 +431,8 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "\n"
 "\n"
 "	#line ignore #showme {<acf>Connecting to <ffa>$gui[new][NAME]<acf>..};\n"
 "	#line ignore #showme {<acf>Connecting to <ffa>$gui[new][NAME]<acf>..};\n"
 "\n"
 "\n"
+"	#config mouse off;\n"
+"\n"
 "	#buffer refresh;\n"
 "	#buffer refresh;\n"
 "\n"
 "\n"
 "	#if {{$gui[new][SSL]} == {off}}\n"
 "	#if {{$gui[new][SSL]} == {off}}\n"
@@ -563,6 +565,8 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "#alias {gui_reload}\n"
 "#alias {gui_reload}\n"
 "{\n"
 "{\n"
 "	#split 1 3 27 27;\n"
 "	#split 1 3 27 27;\n"
+"	#config mouse on;\n"
+"\n"
 "	#screen clear split;\n"
 "	#screen clear split;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "\n"
 "\n"
@@ -592,7 +596,6 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "\n"
 "\n"
 "#alias {gui_init}\n"
 "#alias {gui_init}\n"
 "{\n"
 "{\n"
-"	#config mouse on;\n"
 "	#config scroll_lock off;\n"
 "	#config scroll_lock off;\n"
 "\n"
 "\n"
 "	#class WORLDS assign #variable {worldlist} {};\n"
 "	#class WORLDS assign #variable {worldlist} {};\n"
@@ -613,36 +616,33 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "\n"
 "\n"
 "	gui_reload;\n"
 "	gui_reload;\n"
 "\n"
 "\n"
-"	#line verbose\n"
+"	#if {$gui[cols] > 75}\n"
 "	{\n"
 "	{\n"
-"		#if {$gui[cols] > 75}\n"
-"		{\n"
-"			#draw Silver huge traced scroll tile 1 1 6 73 { TINTIN++};\n"
-"			#draw Silver calign scroll tile 1 1 2 75 {}{$info[SYSTEM][CLIENT_VERSION]};\n"
-"			#draw Silver calign scroll tile 1 1 3 75 {}{Code by Peter Unold, Bill Reiss, and Igor van den Hoven}\n"
-"		};\n"
-"		#elseif {$gui[cols] > 40}\n"
-"		{\n"
-"			#draw Silver huge traced scroll tile 1 1 6 40 { TT++};\n"
-"			#draw Silver calign scroll tile 1 1 2 40 {}{$info[SYSTEM][CLIENT_VERSION]};\n"
-"			#draw Silver calign scroll tile 1 1 4 40 {}{Code by Peter Unold, Bill Reiss,}{}{and Igor van den Hoven}\n"
-"		};\n"
-"		#elseif {$gui[cols] > 18}\n"
-"		{\n"
-"			#draw Silver calign scroll tile 1 1 14 $gui[cols] {T I N T I N + +}{}{$info[SYSTEM][CLIENT_VERSION]}{}{Code by}{}{Peter Unold}{}{Bill Reiss}{}{and}{}{Igor van den Hoven};\n"
-"		};\n"
-"		#elseif {$gui[cols] > 8}\n"
-"		{\n"
-"			#draw Silver huge traced scroll tile 1 1 6 9 {T};\n"
-"			#draw Silver huge traced scroll tile 1 1 6 9 {T};\n"
-"			#draw Silver huge traced scroll tile 1 1 6 9 {+};\n"
-"			#draw Silver huge traced scroll tile 1 1 6 9 {+};\n"
-"			#draw Silver calign scroll tile 1 1 1 9 {$info[SYSTEM][CLIENT_VERSION]}\n"
-"		};\n"
-"		#elseif {$gui[cols] > 1}\n"
-"		{\n"
-"			#draw Silver calign scroll tile 1 1 8 $gui[cols] {T}{i}{n}{T}{i}{n}{+}{+}\n"
-"		}\n"
+"		#draw Silver huge traced scroll tile 1 1 6 73 { TINTIN++};\n"
+"		#draw Silver calign scroll tile 1 1 2 75 {}{$info[SYSTEM][CLIENT_VERSION]};\n"
+"		#draw Silver calign scroll tile 1 1 3 75 {}{Code by Peter Unold, Bill Reiss, and Igor van den Hoven}\n"
+"	};\n"
+"	#elseif {$gui[cols] > 40}\n"
+"	{\n"
+"		#draw Silver huge traced scroll tile 1 1 6 40 { TT++};\n"
+"		#draw Silver calign scroll tile 1 1 2 40 {}{$info[SYSTEM][CLIENT_VERSION]};\n"
+"		#draw Silver calign scroll tile 1 1 4 40 {}{Code by Peter Unold, Bill Reiss,}{}{and Igor van den Hoven}\n"
+"	};\n"
+"	#elseif {$gui[cols] > 18}\n"
+"	{\n"
+"		#draw Silver calign scroll tile 1 1 14 $gui[cols] {T I N T I N + +}{}{$info[SYSTEM][CLIENT_VERSION]}{}{Code by}{}{Peter Unold}{}{Bill Reiss}{}{and}{}{Igor van den Hoven};\n"
+"	};\n"
+"	#elseif {$gui[cols] > 8}\n"
+"	{\n"
+"		#draw Silver huge traced scroll tile 1 1 6 9 {T};\n"
+"		#draw Silver huge traced scroll tile 1 1 6 9 {T};\n"
+"		#draw Silver huge traced scroll tile 1 1 6 9 {+};\n"
+"		#draw Silver huge traced scroll tile 1 1 6 9 {+};\n"
+"		#draw Silver calign scroll tile 1 1 1 9 {$info[SYSTEM][CLIENT_VERSION]}\n"
+"	};\n"
+"	#elseif {$gui[cols] > 1}\n"
+"	{\n"
+"		#draw Silver calign scroll tile 1 1 8 $gui[cols] {T}{i}{n}{T}{i}{n}{+}{+}\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
 "\n"
 "\n"

+ 77 - 20
src/help.c

@@ -155,7 +155,7 @@ DO_COMMAND(do_help)
 
 
 		script_driver(ses, LIST_COMMAND, "#config {log} {html}");
 		script_driver(ses, LIST_COMMAND, "#config {log} {html}");
 
 
-		if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
+		if (HAS_BIT(ses->log->mode, LOG_FLAG_HTML))
 		{
 		{
 			write_html_header(ses, logfile);
 			write_html_header(ses, logfile);
 		}
 		}
@@ -874,9 +874,31 @@ struct help_type help_table[] =
 		"         with macros. Subsequently many cursor commands only work properly when\n"
 		"         with macros. Subsequently many cursor commands only work properly when\n"
 		"         used within a macro or event.\n"
 		"         used within a macro or event.\n"
 		"\n"
 		"\n"
-		"         <178>#cursor tab <list;scrollback> <backward|forward>\n"
-		"         <278>  Tab through the given option(s) going forward or backward.\n"
-		,
+		"         <178>#cursor flag\n"
+		"\n"
+		"         <278>EOL         end of line character(s)\n"
+		"         <278>ECHO        local echo\n"
+		"         <278>OVERTYPE    overtype mode\n"
+		"\n"
+		"         <178>#cursor macro\n"
+		"\n"
+		"         <278>PRESERVE    do not erase the macro from the macro input buffer\n"
+		"         <278>RESET       erase the macro input buffer\n"
+		"\n"
+		"         <178>#cursor tab\n"
+		"\n"
+		"         <278>CASELESS    makes tab completion caseless\n"
+		"         <278>COMPLETE    makes tab completion work while editing\n"
+		"\n"
+		"         <278>DICTIONARY  performs tab completion on the dictionary\n"
+		"         <278>LIST        performs tab completion on the tab completion list\n"
+		"         <278>SCROLLBACK  performs tab completion on the scrollback buffer\n"
+		"\n"
+		"         <278>BACKWARD    specifies tab completion to go backward\n"
+		"         <278>FORWARD     specifies tab completion to go forward\n"
+		"\n"
+		"         <278>Multiple options can/must be specified at once.\n",
+
 		"alias history keypad macro speedwalk tab"
 		"alias history keypad macro speedwalk tab"
 	},
 	},
 	{
 	{
@@ -945,6 +967,8 @@ struct help_type help_table[] =
 		"         Nanosecond floating point precision is allowed. Delays will fire in\n"
 		"         Nanosecond floating point precision is allowed. Delays will fire in\n"
 		"         0.01 second intervals.\n"
 		"         0.01 second intervals.\n"
 		"\n"
 		"\n"
+		"         Named delays are treated as one-shot tickers, see #help tick.\n"
+		"\n"
 		"<178>Example<278>: #delay {1} {#show last};#show first\n"
 		"<178>Example<278>: #delay {1} {#show last};#show first\n"
 		"         This will print 'first', and 'last' around one second later.\n"
 		"         This will print 'first', and 'last' around one second later.\n"
 		"\n"
 		"\n"
@@ -1343,6 +1367,9 @@ struct help_type help_table[] =
 		"         <178>RECEIVED INPUT [NAME]\n"
 		"         <178>RECEIVED INPUT [NAME]\n"
 		"         <278>  %0 raw text\n"
 		"         <278>  %0 raw text\n"
 		"\n"
 		"\n"
+		"         <178>RECEIVED INPUT CHARACTER\n"
+		"         <278>  %0 character  %1 unicode index  %2 size  %3 width\n"
+		"\n"
 		"         SEND OUTPUT            %0 raw text %1 size\n"
 		"         SEND OUTPUT            %0 raw text %1 size\n"
 		"         SENT OUTPUT            %0 raw text %1 size\n"
 		"         SENT OUTPUT            %0 raw text %1 size\n"
 		"\n"
 		"\n"
@@ -1801,7 +1828,7 @@ struct help_type help_table[] =
 	{
 	{
 		"INDEX",
 		"INDEX",
 		TOKEN_TYPE_STRING,
 		TOKEN_TYPE_STRING,
-		"         On this page you'll find an introduction to using TinTin++. Additional\n"
+		"<278>         On this page you'll find an introduction to using TinTin++. Additional\n"
 		"         information can be found in the individual help sections.\n"
 		"         information can be found in the individual help sections.\n"
 		"<128>\n"
 		"<128>\n"
 		"         Starting and Ending\n"
 		"         Starting and Ending\n"
@@ -2082,6 +2109,7 @@ struct help_type help_table[] =
 		"         #info session will show information on the session.\n"
 		"         #info session will show information on the session.\n"
 		"         #info sessions will show information on all sessions.\n"
 		"         #info sessions will show information on all sessions.\n"
 		"         #info system will show some system information.\n"
 		"         #info system will show some system information.\n"
+		"         #info tokenizer will show information about the script stack.\n"
 		"         #info unicode will show information on the provided character.\n",
 		"         #info unicode will show information on the provided character.\n",
 
 
 		"class debug ignore kill message"
 		"class debug ignore kill message"
@@ -2150,19 +2178,19 @@ struct help_type help_table[] =
 		"LINE",
 		"LINE",
 		TOKEN_TYPE_COMMAND,
 		TOKEN_TYPE_COMMAND,
 		"<178>Command<278>: #line <178>{<278>option<178>} {<278>argument<178>}<278>\n"
 		"<178>Command<278>: #line <178>{<278>option<178>} {<278>argument<178>}<278>\n"
-		"<128>\n"
-		"         Line sub commands that alter the argument.\n"
-		"<278>\n"
+		"\n"
+		"         <128>Line options that alter the argument.\n"
+		"\n"
 		"         <178>#line strip <argument>\n"
 		"         <178>#line strip <argument>\n"
 		"         <278>  Argument is executed with all color codes stripped.\n"
 		"         <278>  Argument is executed with all color codes stripped.\n"
 		"\n"
 		"\n"
 		"         <178>#line substitute <options> <argument>\n"
 		"         <178>#line substitute <options> <argument>\n"
 		"         <278>  Argument is executed using the provided substitutions, available\n"
 		"         <278>  Argument is executed using the provided substitutions, available\n"
-		"         <278>  options are: arguments, colors, escapes, functions, secure, and\n"
-		"         <278>  variables.\n"
-		"<128>\n"
-		"         Line sub commands that alter how the line is executed.\n"
-		"<278>\n"
+		"         <278>  options are: arguments, braces, colors, escapes, functions, secure,\n"
+		"         <278>  and variables.\n"
+		"\n"
+		"         <128>Line options that alter how the line is executed.\n"
+		"\n"
 		"         <178>#line background <argument>\n"
 		"         <178>#line background <argument>\n"
 		"         <278>  Prevent new session activation.\n"
 		"         <278>  Prevent new session activation.\n"
 		"\n"
 		"\n"
@@ -2564,12 +2592,36 @@ struct help_type help_table[] =
 	{
 	{
 		"LOG",
 		"LOG",
 		TOKEN_TYPE_COMMAND,
 		TOKEN_TYPE_COMMAND,
-		"<178>Command<278>: #log <178>{<278>append<178>|<278>overwrite<178>|<278>off<178>} {<278>[filename]<178>}<278>\n"
+		"<178>Command<278>: #log <178>{<278>option<178>} {<278>argument<178>}<278>\n"
+		"<278>\n"
+		"         The log command allows logging session output to file. You can set the\n"
+		"         data type to either plain, raw, or html with the config command.\n"
 		"\n"
 		"\n"
-		"         Logs session output to a file, you can set the data type to either\n"
-		"         plain, raw, or html with the config command.\n",
-		
-		"read scan textin write"
+		"         <178>#log append <filename>\n"
+		"         <278>  Start logging to the given file, if the file already exists it won't\n"
+		"         <278>  be overwritten and data will be appended to the end.\n"
+		"\n"
+		"         <178>#log move <filename_1> <filename_2>\n"
+		"         <278>  Move filename_1 to filename_2. This can be any file and doesn't need\n"
+		"         <278>  to be a log file.\n"
+		"\n"
+		"         <178>#log overwrite <filename>\n"
+		"         <278>  Start logging to the given file, if the file already exists it will\n"
+		"         <278>  be overwritten.\n"
+		"\n"
+		"         <178>#log off\n"
+		"         <278>  Stop logging.\n"
+		"\n"
+		"         <178>#log remove <filename>\n"
+		"         <278>  Remove the file. This can be any file and doesn't need to be a log\n"
+		"         <278>  file.\n"
+		"\n"
+		"         <178>#log timestamp <format>\n"
+		"         <278>  When set the timestamp will be prepended to each line logged to file.\n"
+		"         <278>  The format will be formatted as a date using the strftime format\n"
+		"         <278>  specifiers as described in #help time.\n",
+
+		"read scan textin time write"
 	},
 	},
 
 
 	{
 	{
@@ -2776,9 +2828,11 @@ struct help_type help_table[] =
 		"         <278>  Lists all matching rooms and their distance. The following\n"
 		"         <278>  Lists all matching rooms and their distance. The following\n"
 		"         <278>  search keywords are supported.\n"
 		"         <278>  search keywords are supported.\n"
 		"\n"
 		"\n"
+		"         <278>  {distance}    <arg> will list rooms within given distance.\n"
 		"         <278>  {roomarea}    <arg> will list rooms with matching area name.\n"
 		"         <278>  {roomarea}    <arg> will list rooms with matching area name.\n"
 		"         <278>  {roomdesc}    <arg> will list rooms with matching room desc.\n"
 		"         <278>  {roomdesc}    <arg> will list rooms with matching room desc.\n"
 		"         <278>  {roomexits}   <arg> will list rooms with identical room exits.\n"
 		"         <278>  {roomexits}   <arg> will list rooms with identical room exits.\n"
+		"         <278>                      Use * as an exit to ignore non pathdir exits.\n"
 		"         <278>  {roomflag}    <arg> will list rooms with matching room flags.\n"
 		"         <278>  {roomflag}    <arg> will list rooms with matching room flags.\n"
 		"         <278>  {roomid}      <arg> will list rooms with identical id name.\n"
 		"         <278>  {roomid}      <arg> will list rooms with identical id name.\n"
 		"         <278>  {roomname}    <arg> will list rooms with matching room name.\n"
 		"         <278>  {roomname}    <arg> will list rooms with matching room name.\n"
@@ -4303,8 +4357,11 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"         Adds a word to the tab completion list, alphabetically sorted.\n"
 		"         Adds a word to the tab completion list, alphabetically sorted.\n"
 		"\n"
 		"\n"
-		"         If no tabs are defined tintin will use the scrollback buffer\n"
-		"         for auto tab completion.\n"
+		"         If no tabs are defined tintin will use the scrollback buffer for auto\n"
+		"         tab completion.\n"
+		"\n"
+		"         Tabbing behavior can be modified with the #cursor tab command which\n"
+		"         by default is bound to the tab key.\n"
 		"\n"
 		"\n"
 		"<178>Comment<278>: You can remove a tab with the #untab command.\n",
 		"<178>Comment<278>: You can remove a tab with the #untab command.\n",
 
 

+ 15 - 11
src/input.c

@@ -143,11 +143,6 @@ void process_input(void)
 		echo_command(gtd->ses, "");
 		echo_command(gtd->ses, "");
 	}
 	}
 
 
-	if (gtd->ses->scroll->line != -1)
-	{
-		buffer_end(gtd->ses, "", "", "");
-	}
-
 	input_ses = gtd->ses;
 	input_ses = gtd->ses;
 
 
 	check_all_events(gtd->ses, SUB_SEC|EVENT_FLAG_INPUT, 0, 1, "RECEIVED INPUT", gtd->ses->input->buf);
 	check_all_events(gtd->ses, SUB_SEC|EVENT_FLAG_INPUT, 0, 1, "RECEIVED INPUT", gtd->ses->input->buf);
@@ -233,11 +228,14 @@ void read_line(char *input, int len)
 
 
 	if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
 	if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
 	{
 	{
-		check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 2, "RECEIVED KEYPRESS", input, ntos(index));
+		check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 2, "RECEIVED KEYPRESS", input, ntos(index));
+	}
 
 
-		if (check_all_events(gtd->ses, EVENT_FLAG_CATCH, 0, 2, "CATCH RECEIVED KEYPRESS", input, ntos(index)) == 1)
+	if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_CATCH))
+	{
+		if (check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_CATCH, 0, 2, "CATCH RECEIVED KEYPRESS", input, ntos(index)) == 1)
 		{
 		{
-			check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
+			check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
 
 
 			return;
 			return;
 		}
 		}
@@ -247,7 +245,7 @@ void read_line(char *input, int len)
 	{
 	{
 		if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
 		if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
 		{
 		{
-			check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
+			check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
 		}
 		}
 		return;
 		return;
 	}
 	}
@@ -282,7 +280,7 @@ void read_line(char *input, int len)
 			default:
 			default:
 				if (HAS_BIT(gtd->ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(gtd->macro_buf) && gtd->macro_buf[1])
 				if (HAS_BIT(gtd->ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(gtd->macro_buf) && gtd->macro_buf[1])
 				{
 				{
-					size = get_utf8_width(gtd->macro_buf, &width);
+					size = get_utf8_width(gtd->macro_buf, &width, &index);
 				}
 				}
 				else if (HAS_BIT(gtd->ses->charset, CHARSET_FLAG_EUC) && is_euc_head(gtd->ses, gtd->macro_buf) && gtd->macro_buf[1])
 				else if (HAS_BIT(gtd->ses->charset, CHARSET_FLAG_EUC) && is_euc_head(gtd->ses, gtd->macro_buf) && gtd->macro_buf[1])
 				{
 				{
@@ -291,11 +289,17 @@ void read_line(char *input, int len)
 				else
 				else
 				{
 				{
 					size = get_ascii_width(gtd->macro_buf, &width);
 					size = get_ascii_width(gtd->macro_buf, &width);
+					index = (int) gtd->macro_buf[0];
 				}
 				}
 
 
 				sprintf(buf, "%.*s", size, gtd->macro_buf);
 				sprintf(buf, "%.*s", size, gtd->macro_buf);
 
 
 				inputline_insert(buf, -1);
 				inputline_insert(buf, -1);
+
+				if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
+				{
+					check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 4, "RECEIVED INPUT CHARACTER", buf, ntos(index), ntos(size), ntos(width));
+				}
 /*
 /*
 				if (width && HAS_BIT(gtd->flags, TINTIN_FLAG_INSERTINPUT) && gtd->ses->input->raw_len != gtd->ses->input->raw_pos)
 				if (width && HAS_BIT(gtd->flags, TINTIN_FLAG_INSERTINPUT) && gtd->ses->input->raw_len != gtd->ses->input->raw_pos)
 				{
 				{
@@ -337,7 +341,7 @@ void read_line(char *input, int len)
 	}
 	}
 	if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
 	if (HAS_BIT(gtd->ses->event_flags, EVENT_FLAG_INPUT))
 	{
 	{
-		check_all_events(gtd->ses, EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
+		check_all_events(gtd->ses, SUB_BRA|EVENT_FLAG_INPUT, 0, 4, "PROCESSED KEYPRESS", input, ntos(index), ntos(gtd->ses->input->edit->update + 1), ntos(gtd->ses->input->str_pos + 1));
 	}
 	}
 }
 }
 
 

+ 58 - 58
src/line.c

@@ -267,31 +267,31 @@ DO_LINE(line_log)
 	{
 	{
 		substitute(ses, arg2, arg2, SUB_ESC|SUB_COL|SUB_LNF);
 		substitute(ses, arg2, arg2, SUB_ESC|SUB_COL|SUB_LNF);
 
 
-		if (ses->logfile && !strcmp(ses->logname, arg1))
+		if (ses->log->file && !strcmp(ses->log->name, arg1))
 		{
 		{
-			logit(ses, arg2, ses->logfile, LOG_FLAG_NONE);
+			logit(ses, arg2, ses->log->file, LOG_FLAG_NONE);
 		}
 		}
-		else if (ses->logline_time == gtd->time && !strcmp(ses->logline_name, arg1))
+		else if (ses->log->line_time == gtd->time && !strcmp(ses->log->line_name, arg1))
 		{
 		{
-			logit(ses, arg2, ses->logline_file, LOG_FLAG_NONE);
+			logit(ses, arg2, ses->log->line_file, LOG_FLAG_NONE);
 		}
 		}
 		else
 		else
 		{
 		{
 			if ((logfile = fopen(arg1, "a")))
 			if ((logfile = fopen(arg1, "a")))
 			{
 			{
-				if (ses->logline_file)
+				if (ses->log->line_file)
 				{
 				{
-					fclose(ses->logline_file);
+					fclose(ses->log->line_file);
 				}
 				}
-				free(ses->logline_name);
+				free(ses->log->line_name);
 
 
-				ses->logline_name = strdup(arg1);
-				ses->logline_file = logfile;
-				ses->logline_time = gtd->time;
+				ses->log->line_name = strdup(arg1);
+				ses->log->line_file = logfile;
+				ses->log->line_time = gtd->time;
 
 
-				loginit(ses, ses->logline_file, LOG_FLAG_APPEND | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
+				logheader(ses, ses->log->line_file, LOG_FLAG_APPEND | HAS_BIT(ses->log->mode, LOG_FLAG_HTML));
 
 
-				logit(ses, arg2, ses->logline_file, LOG_FLAG_NONE);
+				logit(ses, arg2, ses->log->line_file, LOG_FLAG_NONE);
 			}
 			}
 			else
 			else
 			{
 			{
@@ -301,23 +301,23 @@ DO_LINE(line_log)
 	}
 	}
 	else
 	else
 	{
 	{
-		if (ses->lognext_time == gtd->time && !strcmp(ses->lognext_name, arg1))
+		if (ses->log->next_time == gtd->time && !strcmp(ses->log->next_name, arg1))
 		{
 		{
-			SET_BIT(ses->logmode, LOG_FLAG_NEXT);
+			SET_BIT(ses->log->mode, LOG_FLAG_NEXT);
 		}
 		}
 		else if ((logfile = fopen(arg1, "a")))
 		else if ((logfile = fopen(arg1, "a")))
 		{
 		{
-			if (ses->lognext_file)
+			if (ses->log->next_file)
 			{
 			{
-				fclose(ses->lognext_file);
+				fclose(ses->log->next_file);
 			}
 			}
-			free(ses->lognext_name);
+			free(ses->log->next_name);
 
 
-			ses->lognext_name = strdup(arg1);
-			ses->lognext_file = logfile;
-			ses->lognext_time = gtd->time;
+			ses->log->next_name = strdup(arg1);
+			ses->log->next_file = logfile;
+			ses->log->next_time = gtd->time;
 
 
-			SET_BIT(ses->logmode, LOG_FLAG_NEXT);
+			SET_BIT(ses->log->mode, LOG_FLAG_NEXT);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -333,38 +333,38 @@ DO_LINE(line_logmode)
 
 
 	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);
 
 
-	DEL_BIT(ses->logmode, LOG_FLAG_OLD_HTML|LOG_FLAG_OLD_PLAIN|LOG_FLAG_OLD_RAW);
+	DEL_BIT(ses->log->mode, LOG_FLAG_OLD_HTML|LOG_FLAG_OLD_PLAIN|LOG_FLAG_OLD_RAW);
 
 
-	switch (HAS_BIT(ses->logmode, LOG_FLAG_HTML|LOG_FLAG_PLAIN|LOG_FLAG_RAW))
+	switch (HAS_BIT(ses->log->mode, LOG_FLAG_HTML|LOG_FLAG_PLAIN|LOG_FLAG_RAW))
 	{
 	{
 		case LOG_FLAG_HTML:
 		case LOG_FLAG_HTML:
-			SET_BIT(ses->logmode, LOG_FLAG_OLD_HTML);
+			SET_BIT(ses->log->mode, LOG_FLAG_OLD_HTML);
 			break;
 			break;
 		case LOG_FLAG_PLAIN:
 		case LOG_FLAG_PLAIN:
-			SET_BIT(ses->logmode, LOG_FLAG_OLD_PLAIN);
+			SET_BIT(ses->log->mode, LOG_FLAG_OLD_PLAIN);
 			break;
 			break;
 		case LOG_FLAG_RAW:
 		case LOG_FLAG_RAW:
-			SET_BIT(ses->logmode, LOG_FLAG_OLD_RAW);
+			SET_BIT(ses->log->mode, LOG_FLAG_OLD_RAW);
 			break;
 			break;
 	}
 	}
 
 
 	if (is_abbrev(arg1, "HTML"))
 	if (is_abbrev(arg1, "HTML"))
 	{
 	{
-		SET_BIT(ses->logmode, LOG_FLAG_HTML);
-		DEL_BIT(ses->logmode, LOG_FLAG_PLAIN);
-		DEL_BIT(ses->logmode, LOG_FLAG_RAW);
+		SET_BIT(ses->log->mode, LOG_FLAG_HTML);
+		DEL_BIT(ses->log->mode, LOG_FLAG_PLAIN);
+		DEL_BIT(ses->log->mode, LOG_FLAG_RAW);
 	}
 	}
 	else if (is_abbrev(arg1, "PLAIN"))
 	else if (is_abbrev(arg1, "PLAIN"))
 	{
 	{
-		SET_BIT(ses->logmode, LOG_FLAG_PLAIN);
-		DEL_BIT(ses->logmode, LOG_FLAG_HTML);
-		DEL_BIT(ses->logmode, LOG_FLAG_RAW);
+		SET_BIT(ses->log->mode, LOG_FLAG_PLAIN);
+		DEL_BIT(ses->log->mode, LOG_FLAG_HTML);
+		DEL_BIT(ses->log->mode, LOG_FLAG_RAW);
 	}
 	}
 	else if (is_abbrev(arg1, "RAW"))
 	else if (is_abbrev(arg1, "RAW"))
 	{
 	{
-		SET_BIT(ses->logmode, LOG_FLAG_RAW);
-		DEL_BIT(ses->logmode, LOG_FLAG_HTML);
-		DEL_BIT(ses->logmode, LOG_FLAG_PLAIN);
+		SET_BIT(ses->log->mode, LOG_FLAG_RAW);
+		DEL_BIT(ses->log->mode, LOG_FLAG_HTML);
+		DEL_BIT(ses->log->mode, LOG_FLAG_PLAIN);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -377,18 +377,18 @@ DO_LINE(line_logmode)
 
 
 	active_ses = script_driver(ses, LIST_COMMAND, arg1);
 	active_ses = script_driver(ses, LIST_COMMAND, arg1);
 
 
-	DEL_BIT(ses->logmode, LOG_FLAG_HTML|LOG_FLAG_PLAIN|LOG_FLAG_RAW);
+	DEL_BIT(ses->log->mode, LOG_FLAG_HTML|LOG_FLAG_PLAIN|LOG_FLAG_RAW);
 
 
-	switch (HAS_BIT(ses->logmode, LOG_FLAG_OLD_HTML|LOG_FLAG_OLD_PLAIN|LOG_FLAG_OLD_RAW))
+	switch (HAS_BIT(ses->log->mode, LOG_FLAG_OLD_HTML|LOG_FLAG_OLD_PLAIN|LOG_FLAG_OLD_RAW))
 	{
 	{
 		case LOG_FLAG_OLD_HTML:
 		case LOG_FLAG_OLD_HTML:
-			SET_BIT(ses->logmode, LOG_FLAG_HTML);
+			SET_BIT(ses->log->mode, LOG_FLAG_HTML);
 			break;
 			break;
 		case LOG_FLAG_OLD_PLAIN:
 		case LOG_FLAG_OLD_PLAIN:
-			SET_BIT(ses->logmode, LOG_FLAG_PLAIN);
+			SET_BIT(ses->log->mode, LOG_FLAG_PLAIN);
 			break;
 			break;
 		case LOG_FLAG_OLD_RAW:
 		case LOG_FLAG_OLD_RAW:
-			SET_BIT(ses->logmode, LOG_FLAG_RAW);
+			SET_BIT(ses->log->mode, LOG_FLAG_RAW);
 			break;
 			break;
 	}
 	}
 
 
@@ -404,25 +404,25 @@ DO_LINE(line_logverbatim)
 
 
 	if (*arg1 && *arg2)
 	if (*arg1 && *arg2)
 	{
 	{
-		if (!strcmp(ses->logline_name, arg1))
+		if (!strcmp(ses->log->line_name, arg1))
 		{
 		{
-			logit(ses, arg2, ses->logline_file, LOG_FLAG_LINEFEED);
+			logit(ses, arg2, ses->log->line_file, LOG_FLAG_LINEFEED);
 		}
 		}
 		else
 		else
 		{
 		{
 			if ((logfile = fopen(arg1, "a")))
 			if ((logfile = fopen(arg1, "a")))
 			{
 			{
-				if (ses->logline_file)
+				if (ses->log->line_file)
 				{
 				{
-					fclose(ses->logline_file);
+					fclose(ses->log->line_file);
 				}
 				}
-				free(ses->logline_name);
-				ses->logline_name = strdup(arg1);
-				ses->logline_file = logfile;
+				free(ses->log->line_name);
+				ses->log->line_name = strdup(arg1);
+				ses->log->line_file = logfile;
 
 
-				loginit(ses, ses->logline_file, LOG_FLAG_APPEND | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
+				logheader(ses, ses->log->line_file, LOG_FLAG_APPEND | HAS_BIT(ses->log->mode, LOG_FLAG_HTML));
 
 
-				logit(ses, arg2, ses->logline_file, LOG_FLAG_LINEFEED);
+				logit(ses, arg2, ses->log->line_file, LOG_FLAG_LINEFEED);
 			}
 			}
 			else
 			else
 			{
 			{
@@ -432,21 +432,21 @@ DO_LINE(line_logverbatim)
 	}
 	}
 	else
 	else
 	{
 	{
-		if (!strcmp(ses->lognext_name, arg1))
+		if (!strcmp(ses->log->next_name, arg1))
 		{
 		{
-			SET_BIT(ses->logmode, LOG_FLAG_NEXT);
+			SET_BIT(ses->log->mode, LOG_FLAG_NEXT);
 		}
 		}
 		else if ((logfile = fopen(arg1, "a")))
 		else if ((logfile = fopen(arg1, "a")))
 		{
 		{
-			if (ses->lognext_file)
+			if (ses->log->next_file)
 			{
 			{
-				fclose(ses->lognext_file);
+				fclose(ses->log->next_file);
 			}
 			}
-			free(ses->lognext_name);
-			ses->lognext_name = strdup(arg1);
-			ses->lognext_file = logfile;
+			free(ses->log->next_name);
+			ses->log->next_name = strdup(arg1);
+			ses->log->next_file = logfile;
 
 
-			SET_BIT(ses->logmode, LOG_FLAG_NEXT);
+			SET_BIT(ses->log->mode, LOG_FLAG_NEXT);
 		}
 		}
 		else
 		else
 		{
 		{
@@ -478,7 +478,7 @@ DO_LINE(line_multishot)
 {
 {
 	unsigned int shots;
 	unsigned int shots;
 
 
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
 	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
 
 
 	shots = (unsigned int) get_number(ses, arg1);
 	shots = (unsigned int) get_number(ses, arg1);

+ 135 - 28
src/log.c

@@ -25,6 +25,37 @@
 
 
 #include "tintin.h"
 #include "tintin.h"
 
 
+#define DO_LOG(log) void log (struct session *ses, char *arg, char *arg1, char *arg2)
+
+DO_LOG(log_append);
+DO_LOG(log_info);
+DO_LOG(log_move);
+DO_LOG(log_overwrite);
+DO_LOG(log_off);
+DO_LOG(log_remove);
+DO_LOG(log_timestamp);
+
+typedef void LOG (struct session *ses, char *arg, char *arg1, char *arg2);
+
+struct log_type
+{
+	char                  * name;
+	LOG                   * fun;
+	char                  * desc;
+};
+
+struct log_type log_table[] =
+{
+	{    "APPEND",            log_append,          "Start logging, appending to given file."        },
+	{    "INFO",              log_info,            "Some logging related info."                     },
+	{    "MOVE",              log_move,            "Move the given file."                           },
+	{    "OFF",               log_off,             "Stop logging."                                  },
+	{    "OVERWRITE",         log_overwrite,       "Start logging, overwriting the given file."     },
+	{    "REMOVE",            log_remove,          "Remove the given file."                         },
+	{    "TIMESTAMP",         log_timestamp,       "Timestamp prepended to each log line."          },
+	{    "",                  NULL,                ""                                               }
+};
+
 DO_COMMAND(do_log)
 DO_COMMAND(do_log)
 {
 {
 	int cnt;
 	int cnt;
@@ -32,7 +63,7 @@ DO_COMMAND(do_log)
 	push_call("do_log(%p,%p)",ses,arg);
 	push_call("do_log(%p,%p)",ses,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);
-	arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN|SUB_ESC);
+	arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN|SUB_ESC);
 
 
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
@@ -75,20 +106,20 @@ DO_COMMAND(do_log)
 
 
 DO_LOG(log_append)
 DO_LOG(log_append)
 {
 {
-	if (ses->logfile)
+	if (ses->log->file)
 	{
 	{
-		fclose(ses->logfile);
+		fclose(ses->log->file);
 	}
 	}
 
 
-	if ((ses->logfile = fopen(arg2, "a")))
+	if ((ses->log->file = fopen(arg2, "a")))
 	{
 	{
-		SET_BIT(ses->logmode, LOG_FLAG_APPEND);
+		SET_BIT(ses->log->mode, LOG_FLAG_APPEND);
 
 
-		RESTRING(ses->logname, arg2);
+		RESTRING(ses->log->name, arg2);
 
 
-		loginit(ses, ses->logfile, ses->logmode);
+		logheader(ses, ses->log->file, ses->log->mode);
 
 
-		show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s' FILESIZE: %ld", arg2, ftell(ses->logfile));
+		show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s' FILESIZE: %ld", arg2, ftell(ses->log->file));
 	}
 	}
 	else
 	else
 	{
 	{
@@ -98,27 +129,48 @@ DO_LOG(log_append)
 
 
 DO_LOG(log_info)
 DO_LOG(log_info)
 {
 {
-	tintin_printf2(ses, "#LOG INFO: FILE  = %s", ses->logfile ? ses->logname : "");
-	tintin_printf2(ses, "#LOG INFO: LEVEL = %s", HAS_BIT(ses->logmode, LOG_FLAG_LOW) ? "LOW" : "HIGH");
-	tintin_printf2(ses, "#LOG INFO: MODE  = %s", HAS_BIT(ses->logmode, LOG_FLAG_HTML) ? "HTML" : HAS_BIT(ses->logmode, LOG_FLAG_PLAIN) ? "PLAIN" : "RAW");
-	tintin_printf2(ses, "#LOG INFO: LINE  = %s", ses->logline_file ? ses->logline_name : "");
-	tintin_printf2(ses, "#LOG INFO: NEXT  = %s", ses->lognext_file ? ses->lognext_name : "");
+	tintin_printf2(ses, "#LOG INFO: FILE  = %s", ses->log->file ? ses->log->name : "");
+	tintin_printf2(ses, "#LOG INFO: LEVEL = %s", HAS_BIT(ses->log->mode, LOG_FLAG_LOW) ? "LOW" : "HIGH");
+	tintin_printf2(ses, "#LOG INFO: MODE  = %s", HAS_BIT(ses->log->mode, LOG_FLAG_HTML) ? "HTML" : HAS_BIT(ses->log->mode, LOG_FLAG_PLAIN) ? "PLAIN" : "RAW");
+	tintin_printf2(ses, "#LOG INFO: LINE  = %s", ses->log->line_file ? ses->log->line_name : "");
+	tintin_printf2(ses, "#LOG INFO: NEXT  = %s", ses->log->next_file ? ses->log->next_name : "");
+}
+
+DO_LOG(log_move)
+{
+	char *arg3;
+	int result;
+
+	arg3 = str_alloc_stack(0);
+
+	arg = sub_arg_in_braces(ses, arg, arg3, GET_ALL, SUB_VAR|SUB_FUN);
+
+	result = rename(arg2, arg3);
+
+	if (result == 0)
+	{
+		show_message(ses, LIST_COMMAND, "#LOG MOVE: FILE '%s' MOVED TO '%s'.", arg2, arg3);
+	}
+	else
+	{
+		show_error(ses, LIST_COMMAND, "#LOG MOVE: COULDN'T MOVE FILE '%s' TO '%s'.", arg2, arg3);
+	}
 }
 }
 
 
 DO_LOG(log_overwrite)
 DO_LOG(log_overwrite)
 {
 {
-	if (ses->logfile)
+	if (ses->log->file)
 	{
 	{
-		fclose(ses->logfile);
+		fclose(ses->log->file);
 	}
 	}
 
 
-	if ((ses->logfile = fopen(arg2, "w")))
+	if ((ses->log->file = fopen(arg2, "w")))
 	{
 	{
-		SET_BIT(ses->logmode, LOG_FLAG_OVERWRITE);
+		SET_BIT(ses->log->mode, LOG_FLAG_OVERWRITE);
 
 
-		RESTRING(ses->logname, arg2);
+		RESTRING(ses->log->name, arg2);
 
 
-		loginit(ses, ses->logfile, ses->logmode);
+		logheader(ses, ses->log->file, ses->log->mode);
 
 
 		show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s'", arg2);
 		show_message(ses, LIST_COMMAND, "#LOG: LOGGING OUTPUT TO '%s'", arg2);
 	}
 	}
@@ -130,12 +182,12 @@ DO_LOG(log_overwrite)
 
 
 DO_LOG(log_off)
 DO_LOG(log_off)
 {
 {
-	if (ses->logfile)
+	if (ses->log->file)
 	{
 	{
-		DEL_BIT(ses->logmode, LOG_FLAG_APPEND|LOG_FLAG_OVERWRITE);
+		DEL_BIT(ses->log->mode, LOG_FLAG_APPEND|LOG_FLAG_OVERWRITE);
 
 
-		fclose(ses->logfile);
-		ses->logfile = NULL;
+		fclose(ses->log->file);
+		ses->log->file = NULL;
 
 
 		show_message(ses, LIST_COMMAND, "#LOG {OFF}: LOGGING TURNED OFF.");
 		show_message(ses, LIST_COMMAND, "#LOG {OFF}: LOGGING TURNED OFF.");
 	}
 	}
@@ -145,17 +197,72 @@ DO_LOG(log_off)
 	}
 	}
 }
 }
 
 
+DO_LOG(log_remove)
+{
+	int result = remove(arg2);
+
+	if (result == 0)
+	{
+		show_message(ses, LIST_COMMAND, "#LOG REMOVE: FILE '%s' REMOVED.", arg2);
+	}
+	else
+	{
+		show_error(ses, LIST_COMMAND, "#LOG REMOVE: COULDN'T REMOVE FILE '%s'.", arg2);
+	}
+}
+
+DO_LOG(log_timestamp)
+{
+	RESTRING(ses->log->stamp_strf, arg2);
+	ses->log->stamp_time = 0;
+
+	show_message(ses, LIST_COMMAND, "#LOG TIMESTAMP: FORMAT SET TO '%s'.", arg2);
+}
+
+void init_log(struct session *ses)
+{
+	ses->log->name        = strdup("");
+	ses->log->next_name   = strdup("");
+	ses->log->line_name   = strdup("");
+	ses->log->stamp_strf  = strdup("");
+}
+
+void free_log(struct session *ses)
+{
+	free(ses->log->name);
+	free(ses->log->next_name);
+	free(ses->log->line_name);
+	free(ses->log->stamp_strf);
+
+	free(ses->log);
+}
+
 void logit(struct session *ses, char *txt, FILE *file, int flags)
 void logit(struct session *ses, char *txt, FILE *file, int flags)
 {
 {
 	char out[BUFFER_SIZE];
 	char out[BUFFER_SIZE];
 
 
 	push_call("logit(%p,%p,%p,%d)",ses,txt,file,flags);
 	push_call("logit(%p,%p,%p,%d)",ses,txt,file,flags);
 
 
-	if (HAS_BIT(ses->logmode, LOG_FLAG_PLAIN))
+	if (*ses->log->stamp_strf)
+	{
+		if (ses->log->stamp_time != gtd->time)
+		{
+			struct tm timeval_tm = *localtime(&gtd->time);
+
+			ses->log->stamp_time = gtd->time;
+
+			substitute(ses, ses->log->stamp_strf, out, SUB_COL|SUB_ESC|SUB_VAR|SUB_FUN);
+
+			strftime(ses->log->stamp_text, 99, out, &timeval_tm);
+		}
+		fputs(ses->log->stamp_text, file);
+	}
+			
+	if (HAS_BIT(ses->log->mode, LOG_FLAG_PLAIN))
 	{
 	{
 		strip_vt102_codes(txt, out);
 		strip_vt102_codes(txt, out);
 	}
 	}
-	else if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
+	else if (HAS_BIT(ses->log->mode, LOG_FLAG_HTML))
 	{
 	{
 		vt102_to_html(ses, txt, out);
 		vt102_to_html(ses, txt, out);
 	}
 	}
@@ -176,9 +283,9 @@ void logit(struct session *ses, char *txt, FILE *file, int flags)
 	return;
 	return;
 }
 }
 
 
-void loginit(struct session *ses, FILE *file, int flags)
+void logheader(struct session *ses, FILE *file, int flags)
 {
 {
-	push_call("loginit(%p,%p,%d)",ses,file,flags);
+	push_call("logheader(%p,%p,%d)",ses,file,flags);
 
 
 	if (HAS_BIT(flags, LOG_FLAG_APPEND))
 	if (HAS_BIT(flags, LOG_FLAG_APPEND))
 	{
 	{
@@ -194,7 +301,7 @@ void loginit(struct session *ses, FILE *file, int flags)
 	}
 	}
 	else if (HAS_BIT(flags, LOG_FLAG_OVERWRITE) && HAS_BIT(flags, LOG_FLAG_HTML))
 	else if (HAS_BIT(flags, LOG_FLAG_OVERWRITE) && HAS_BIT(flags, LOG_FLAG_HTML))
 	{
 	{
-		if (HAS_BIT(ses->logmode, LOG_FLAG_HTML))
+		if (HAS_BIT(ses->log->mode, LOG_FLAG_HTML))
 		{
 		{
 			write_html_header(ses, file);
 			write_html_header(ses, file);
 		}
 		}

+ 5 - 22
src/main.c

@@ -77,22 +77,6 @@ void winch_handler(int signal)
 	SET_BIT(gtd->flags, TINTIN_FLAG_WINCHUPDATE);
 	SET_BIT(gtd->flags, TINTIN_FLAG_WINCHUPDATE);
 
 
 	gtd->time_session = gtd->time;
 	gtd->time_session = gtd->time;
-/*
-	struct session *ses;
-	init_terminal_size(gts);
-
-	for (ses = gts->next ; ses ; ses = ses->next)
-	{
-		init_terminal_size(ses);
-
-		if (HAS_BIT(ses->telopts, TELOPT_FLAG_NAWS))
-		{
-			SET_BIT(ses->telopts, TELOPT_FLAG_UPDATENAWS);
-		}
-	}
-
-	winch_daemon();
-*/
 }
 }
 
 
 
 
@@ -104,9 +88,8 @@ void abort_handler(int signal)
 void child_handler(int signal)
 void child_handler(int signal)
 {
 {
 	return;
 	return;
-	syserr_printf(gtd->ses, "child_handler");
 
 
-//	syserr_fatal(signal, "child_handler");
+	syserr_printf(gtd->ses, "child_handler");
 }
 }
 /*
 /*
 void interrupt_handler(int signal)
 void interrupt_handler(int signal)
@@ -537,9 +520,6 @@ void init_tintin(int greeting)
 	gts->config_flags   = CONFIG_FLAG_MCCP;
 	gts->config_flags   = CONFIG_FLAG_MCCP;
 	gts->socket         = 1;
 	gts->socket         = 1;
 	gts->read_max       = 16384;
 	gts->read_max       = 16384;
-	gts->logname        = strdup("");
-	gts->lognext_name   = strdup("");
-	gts->logline_name   = strdup("");
 
 
 	gts->more_output    = str_dup("");
 	gts->more_output    = str_dup("");
 
 
@@ -552,14 +532,17 @@ void init_tintin(int greeting)
 
 
 	gtd->banner_list    = init_list(gts, LIST_CONFIG, 32);
 	gtd->banner_list    = init_list(gts, LIST_CONFIG, 32);
 
 
+	gts->log            = calloc(1, sizeof(struct log_data));
+	gts->input          = calloc(1, sizeof(struct input_data));
 	gts->scroll         = calloc(1, sizeof(struct scroll_data));
 	gts->scroll         = calloc(1, sizeof(struct scroll_data));
 	gts->split          = calloc(1, sizeof(struct split_data));
 	gts->split          = calloc(1, sizeof(struct split_data));
-	gts->input          = calloc(1, sizeof(struct input_data));
 
 
 	init_local(gts);
 	init_local(gts);
 
 
 	init_terminal_size(gts);
 	init_terminal_size(gts);
 
 
+	init_log(gts);
+
 	init_input(gts, 0, 0, 0, 0);
 	init_input(gts, 0, 0, 0, 0);
 
 
 	init_buffer(gts, 10000);
 	init_buffer(gts, 10000);

+ 169 - 75
src/mapper.c

@@ -32,7 +32,6 @@
 int                 map_grid_x;
 int                 map_grid_x;
 int                 map_grid_y;
 int                 map_grid_y;
 
 
-#define             MAP_SEARCH_DIST 1000
 #define             MAP_BF_SIZE 10000
 #define             MAP_BF_SIZE 10000
 
 
 extern  int dir_flags(struct session *ses, int room, int dir);
 extern  int dir_flags(struct session *ses, int room, int dir);
@@ -2407,13 +2406,14 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 	{
 	{
 		// experimental
 		// experimental
 
 
-		substitute(ses, room->symbol, room_symbol, SUB_VAR|SUB_FUN);
+		substitute(ses, room->symbol, room_symbol, SUB_VAR|SUB_FUN|SUB_COL|SUB_ESC);
 
 
 		symsize = strip_color_strlen(ses, room_symbol);
 		symsize = strip_color_strlen(ses, room_symbol);
 
 
 		if (HAS_BIT(room->flags, ROOM_FLAG_PATH) && room->search_stamp == ses->map->search->stamp)
 		if (HAS_BIT(room->flags, ROOM_FLAG_PATH) && room->search_stamp == ses->map->search->stamp)
 		{
 		{
 			room_color = ses->map->color[MAP_COLOR_PATH];
 			room_color = ses->map->color[MAP_COLOR_PATH];
+
 			if (symsize > 1)
 			if (symsize > 1)
 			{
 			{
 				strcpy(room_symbol, " ");
 				strcpy(room_symbol, " ");
@@ -2716,32 +2716,40 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 					return buf;
 					return buf;
 				}
 				}
 
 
-				switch (exit_w)
+				if (symsize > 5)
 				{
 				{
-					case 0:
-						strcat(buf, draw_terrain_symbol(ses, room, line, 1, x, y, TERRAIN_FLAG_DOUBLE));
-						strcat(buf, draw_terrain_symbol(ses, room, line, 2, x, y, TERRAIN_FLAG_DOUBLE));
-						break;
-					case MAP_DIR_E:
-						sprintf(buf, "%s%s%s", get_exit_color(ses, 0, room_w->exit_grid[EXIT_GRID_E]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_E], draw_terrain_symbol(ses, room, line, 2, x, y, flags));
-						break;
-					case MAP_DIR_W:
-						sprintf(buf, "%s%s%s", get_exit_color(ses, 0, room->exit_grid[EXIT_GRID_W]), draw_terrain_symbol(ses, room, line, 1, x, y, flags), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_W]);
-						break;
-					case MAP_DIR_E|MAP_DIR_W:
-						if (room->exit_grid[EXIT_GRID_W]->vnum == room_w->vnum && room_w->exit_grid[EXIT_GRID_E]->vnum == room->vnum)
-						{
-							// ‒‒
-							sprintf(buf, "%s%s%s%s", get_exit_color(ses, 0, room_w->exit_grid[EXIT_GRID_E]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_EW], get_exit_color(ses, 0, room->exit_grid[EXIT_GRID_W]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_EW]);
-						}
-						else
-						{
-							sprintf(buf, "%s%s%s%s", get_exit_color(ses, 0, room_w->exit_grid[EXIT_GRID_E]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_E], get_exit_color(ses, 0, room->exit_grid[EXIT_GRID_W]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_W]);
-						}
-						break;
-					default:
-						strcat(buf, "??");
-						break;
+					room_symbol[raw_len_str(ses, room_symbol, 0, 4)] = 0;
+				}
+
+				if (symsize <= 3 || room->vnum == ses->map->in_room)
+				{
+					switch (exit_w)
+					{
+						case 0:
+							strcat(buf, draw_terrain_symbol(ses, room, line, 1, x, y, TERRAIN_FLAG_DOUBLE));
+							strcat(buf, draw_terrain_symbol(ses, room, line, 2, x, y, TERRAIN_FLAG_DOUBLE));
+							break;
+						case MAP_DIR_E:
+							sprintf(buf, "%s%s%s", get_exit_color(ses, 0, room_w->exit_grid[EXIT_GRID_E]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_E], draw_terrain_symbol(ses, room, line, 2, x, y, flags));
+							break;
+						case MAP_DIR_W:
+							sprintf(buf, "%s%s%s", get_exit_color(ses, 0, room->exit_grid[EXIT_GRID_W]), draw_terrain_symbol(ses, room, line, 1, x, y, flags), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_W]);
+							break;
+						case MAP_DIR_E|MAP_DIR_W:
+							if (room->exit_grid[EXIT_GRID_W]->vnum == room_w->vnum && room_w->exit_grid[EXIT_GRID_E]->vnum == room->vnum)
+							{
+								// ‒‒
+								sprintf(buf, "%s%s%s%s", get_exit_color(ses, 0, room_w->exit_grid[EXIT_GRID_E]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_EW], get_exit_color(ses, 0, room->exit_grid[EXIT_GRID_W]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_EW]);
+							}
+							else
+							{
+								sprintf(buf, "%s%s%s%s", get_exit_color(ses, 0, room_w->exit_grid[EXIT_GRID_E]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_E], get_exit_color(ses, 0, room->exit_grid[EXIT_GRID_W]), ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_W]);
+							}
+							break;
+						default:
+							strcat(buf, "??");
+							break;
+					}
 				}
 				}
 
 
 				if (room->vnum == ses->map->in_room)
 				if (room->vnum == ses->map->in_room)
@@ -2750,7 +2758,14 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 				}
 				}
 				else if (symsize > 1)
 				else if (symsize > 1)
 				{
 				{
-					cat_sprintf(buf, "%s%-3s", ses->map->color[MAP_COLOR_SYMBOL], room_symbol);
+					if (symsize > 3)
+					{
+						cat_sprintf(buf, "%s%s%s", ses->map->color[MAP_COLOR_SYMBOL], room_symbol, symsize == 4 ? " " : "");
+					}
+					else
+					{
+						cat_sprintf(buf, "%s%s%s", ses->map->color[MAP_COLOR_SYMBOL], room_symbol, symsize == 2 ? " " : "");
+					}
 				}
 				}
 				else
 				else
 				{
 				{
@@ -3078,9 +3093,9 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 		return buf;
 		return buf;
 	}
 	}
 
 
-
 	if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS))
 	if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIGRAPHICS))
 	{
 	{
+
 		strcpy(buf, "");
 		strcpy(buf, "");
 
 
 		switch (line)
 		switch (line)
@@ -3121,6 +3136,11 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 				break;
 				break;
 
 
 			case 2:
 			case 2:
+				if (symsize > 6)
+				{
+					room_symbol[raw_len_str(ses, room_symbol, 0, 5)] = 0;
+				}
+
 				if (HAS_BIT(room->flags, ROOM_FLAG_CURVED))
 				if (HAS_BIT(room->flags, ROOM_FLAG_CURVED))
 				{
 				{
 					sprintf(room_left,  "%s%s", room_color, ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_RL_CURVED]);
 					sprintf(room_left,  "%s%s", room_color, ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_RL_CURVED]);
@@ -3132,7 +3152,7 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 					sprintf(room_right, "%s%s", room_color, ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_RR]);
 					sprintf(room_right, "%s%s", room_color, ses->map->legend[LEGEND_UNICODE_GRAPHICS + UNICODE_DIR_RR]);
 				}
 				}
 
 
-				if (!HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS) && symsize <= 3)
+				if (!HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS) && (symsize <= 3 || room->vnum == ses->map->in_room))
 				{
 				{
 					cat_sprintf(buf, "%s%s",
 					cat_sprintf(buf, "%s%s",
 						get_exit_color(ses, room->vnum, room->exit_grid[EXIT_GRID_W]),
 						get_exit_color(ses, room->vnum, room->exit_grid[EXIT_GRID_W]),
@@ -3172,7 +3192,7 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 					}
 					}
 					else if (symsize > 3)
 					else if (symsize > 3)
 					{
 					{
-						cat_sprintf(buf, "%s%-5s", ses->map->color[MAP_COLOR_SYMBOL], room_symbol);
+						cat_sprintf(buf, "%s%s%s", ses->map->color[MAP_COLOR_SYMBOL], room_symbol, symsize > 5 ? "" : " ");
 					}
 					}
 					else if (HAS_BIT(room->flags, ROOM_FLAG_VOID))
 					else if (HAS_BIT(room->flags, ROOM_FLAG_VOID))
 					{
 					{
@@ -3228,9 +3248,12 @@ char *draw_room(struct session *ses, struct room_data *room, int line, int x, in
 					}
 					}
 				}
 				}
 
 
-				if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS) || symsize > 3)
+				if (HAS_BIT(ses->map->flags, MAP_FLAG_ASCIIVNUMS) || (symsize > 3 && room->vnum != ses->map->in_room))
 				{
 				{
-					cat_sprintf(buf, "%s%s", get_exit_color(ses, room->vnum, room->exit_grid[EXIT_GRID_E]), room->exit_grid[EXIT_GRID_E] ? "-" : draw_terrain_symbol(ses, room, line, 6, x, y, flags));
+					if (symsize < 5)
+					{
+						cat_sprintf(buf, "%s%s", get_exit_color(ses, room->vnum, room->exit_grid[EXIT_GRID_E]), room->exit_grid[EXIT_GRID_E] ? "-" : draw_terrain_symbol(ses, room, line, 6, x, y, flags));
+					}
 				}
 				}
 				else
 				else
 				{
 				{
@@ -3530,6 +3553,10 @@ void search_keywords(struct session *ses, char *arg, char *out, char *var)
 		{
 		{
 			arg = sub_arg_in_braces(ses, arg, buf[MAP_SEARCH_FLAG], GET_ALL, SUB_VAR|SUB_FUN);
 			arg = sub_arg_in_braces(ses, arg, buf[MAP_SEARCH_FLAG], GET_ALL, SUB_VAR|SUB_FUN);
 		}
 		}
+		else if (!strcasecmp(arg1, "distance"))
+		{
+			arg = sub_arg_in_braces(ses, arg, buf[MAP_SEARCH_DISTANCE], GET_ALL, SUB_VAR|SUB_FUN);
+		}
 		else if (!strcasecmp(arg1, "variable"))
 		else if (!strcasecmp(arg1, "variable"))
 		{
 		{
 			arg = sub_arg_in_braces(ses, arg, var, GET_ALL, SUB_VAR|SUB_FUN);
 			arg = sub_arg_in_braces(ses, arg, var, GET_ALL, SUB_VAR|SUB_FUN);
@@ -3778,47 +3805,62 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 		ses->map->search->terrain = NULL;
 		ses->map->search->terrain = NULL;
 	}
 	}
 
 
-	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN); // flag
+	// flag
+
+	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN);
 
 
 	if (*buf)
 	if (*buf)
 	{
 	{
-		char flags[BUFFER_SIZE];
+		char flags[BUFFER_SIZE], *ptf;
+		long long *flag;
 
 
 		ses->map->search->flag = get_number(ses, buf);
 		ses->map->search->flag = get_number(ses, buf);
+		ses->map->search->galf = 0;
 
 
 		ptb = buf;
 		ptb = buf;
 
 
 		while (*ptb)
 		while (*ptb)
 		{
 		{
 			ptb = sub_arg_in_braces(ses, ptb, flags, GET_ONE, SUB_NONE);
 			ptb = sub_arg_in_braces(ses, ptb, flags, GET_ONE, SUB_NONE);
+			ptf = flags;
 
 
-			if (is_abbrev(buf, "avoid"))
+			if (ptf[0] == '!')
 			{
 			{
-				SET_BIT(ses->map->search->flag, ROOM_FLAG_AVOID);
+				flag = &ses->map->search->galf;
+				ptf++;
 			}
 			}
-			else if (is_abbrev(buf, "curved"))
+			else
 			{
 			{
-				SET_BIT(ses->map->search->flag, ROOM_FLAG_CURVED);
+				flag = &ses->map->search->flag;
 			}
 			}
-			else if (is_abbrev(buf, "hide"))
+
+			if (is_abbrev(ptf, "avoid"))
 			{
 			{
-				SET_BIT(ses->map->search->flag, ROOM_FLAG_HIDE);
+				SET_BIT(*flag, ROOM_FLAG_AVOID);
 			}
 			}
-			else if (is_abbrev(buf, "invis"))
+			else if (is_abbrev(ptf, "curved"))
 			{
 			{
-				SET_BIT(ses->map->search->flag, ROOM_FLAG_INVIS);
+				SET_BIT(*flag, ROOM_FLAG_CURVED);
 			}
 			}
-			else if (is_abbrev(buf, "leave"))
+			else if (is_abbrev(ptf, "hide"))
 			{
 			{
-				SET_BIT(ses->map->search->flag, ROOM_FLAG_LEAVE);
+				SET_BIT(*flag, ROOM_FLAG_HIDE);
 			}
 			}
-			else if (is_abbrev(buf, "void"))
+			else if (is_abbrev(ptf, "invis"))
 			{
 			{
-				SET_BIT(ses->map->search->flag, ROOM_FLAG_VOID);
+				SET_BIT(*flag, ROOM_FLAG_INVIS);
 			}
 			}
-			else if (is_abbrev(buf, "static"))
+			else if (is_abbrev(ptf, "leave"))
 			{
 			{
-				SET_BIT(ses->map->search->flag, ROOM_FLAG_STATIC);
+				SET_BIT(*flag, ROOM_FLAG_LEAVE);
+			}
+			else if (is_abbrev(ptf, "void"))
+			{
+				SET_BIT(*flag, ROOM_FLAG_VOID);
+			}
+			else if (is_abbrev(ptf, "static"))
+			{
+				SET_BIT(*flag, ROOM_FLAG_STATIC);
 			}
 			}
 
 
 			if (*ptb == COMMAND_SEPARATOR)
 			if (*ptb == COMMAND_SEPARATOR)
@@ -3830,6 +3872,7 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 	else
 	else
 	{
 	{
 		ses->map->search->flag = 0;
 		ses->map->search->flag = 0;
+		ses->map->search->galf = 0;
 	}
 	}
 
 
 	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN); // id
 	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN); // id
@@ -3848,6 +3891,17 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 		ses->map->search->id = NULL;
 		ses->map->search->id = NULL;
 	}
 	}
 
 
+	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN); // distance
+
+	if (*buf)
+	{
+		ses->map->search->distance = (float) get_number(ses, buf);
+	}
+	else
+	{
+		ses->map->search->distance = 0;
+	}
+
 	pop_call();
 	pop_call();
 	return;
 	return;
 }
 }
@@ -3888,29 +3942,39 @@ int match_room(struct session *ses, int vnum, struct search_data *search)
 	{
 	{
 		char *arg, exit[BUFFER_SIZE];
 		char *arg, exit[BUFFER_SIZE];
 
 
-		if (search->exit_dirs != room->exit_dirs)
+		if (!strcmp(search->exit_list, "{*}"))
 		{
 		{
-			return 0;
-		}
-		if (search->exit_size != room->exit_size)
-		{
-			return 0;
+			if (search->exit_dirs != (room->exit_dirs | 1))
+			{
+				return 0;
+			}
 		}
 		}
-
-		arg = search->exit_list;
-
-		while (*arg)
+		else
 		{
 		{
-			arg = get_arg_in_braces(ses, arg, exit, GET_ONE);
-
-			if (!find_exit(ses, vnum, exit))
+			if (search->exit_dirs != room->exit_dirs)
+			{
+				return 0;
+			}
+			if (search->exit_size != room->exit_size)
 			{
 			{
 				return 0;
 				return 0;
 			}
 			}
 
 
-			if (*arg == COMMAND_SEPARATOR)
+			arg = search->exit_list;
+
+			while (*arg)
 			{
 			{
-				arg++;
+				arg = get_arg_in_braces(ses, arg, exit, GET_ONE);
+
+				if (!find_exit(ses, vnum, exit))
+				{
+					return 0;
+				}
+
+				if (*arg == COMMAND_SEPARATOR)
+				{
+					arg++;
+				}
 			}
 			}
 		}
 		}
 	}
 	}
@@ -3954,6 +4018,32 @@ int match_room(struct session *ses, int vnum, struct search_data *search)
 			return 0;
 			return 0;
 		}
 		}
 	}
 	}
+
+	if (search->galf)
+	{
+		if ((room->flags & search->galf) == search->galf)
+		{
+			return 0;
+		}
+	}
+
+	if (search->distance)
+	{
+		if (ses->map->search->stamp != room->search_stamp)
+		{
+			if (search->distance != -1)
+			{
+				return 0;
+			}
+		}
+		else
+		{
+			if (room->length > search->distance)
+			{
+				return 0;
+			}
+		}
+	}
 	return 1;
 	return 1;
 }
 }
 
 
@@ -4648,11 +4738,11 @@ void shortest_path(struct session *ses, int run, char *delay, char *arg)
 		{
 		{
 			if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW))
 			if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW))
 			{
 			{
-				check_append_path(ses, exit->cmd, "", exit->delay, 0);
+				check_append_path(ses, exit->cmd, "", exit->delay, 1, 0);
 			}
 			}
 			else
 			else
 			{
 			{
-				check_append_path(ses, exit->name, "", exit->delay, 0);
+				check_append_path(ses, exit->name, "", exit->delay, 1, 0);
 			}
 			}
 		}
 		}
 
 
@@ -4660,7 +4750,7 @@ void shortest_path(struct session *ses, int run, char *delay, char *arg)
 
 
 		if (ses->map->room_list[vnum]->search_stamp != ses->map->search->stamp)
 		if (ses->map->room_list[vnum]->search_stamp != ses->map->search->stamp)
 		{
 		{
-			show_error(ses, LIST_COMMAND, "%d bad search stamp %d vs %d", vnum, ses->map->room_list[vnum]->search_stamp, ses->map->search->stamp);
+			show_error(ses, LIST_COMMAND, "#SHORTEST PATH: %d bad search stamp %d vs %d", vnum, ses->map->room_list[vnum]->search_stamp, ses->map->search->stamp);
 		}
 		}
 
 
 		if (vnum == dest)
 		if (vnum == dest)
@@ -4848,11 +4938,11 @@ void explore_path(struct session *ses, int run, char *arg1, char *arg2)
 
 
 	if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW))
 	if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW))
 	{
 	{
-		check_append_path(ses, exit->cmd, "", exit->delay, 0);
+		check_append_path(ses, exit->cmd, "", exit->delay, 1, 0);
 	}
 	}
 	else
 	else
 	{
 	{
-		check_append_path(ses, exit->name, "", exit->delay, 0);
+		check_append_path(ses, exit->name, "", exit->delay, 1, 0);
 	}
 	}
 
 
 	SET_BIT(ses->map->room_list[room]->flags, ROOM_FLAG_PATH);
 	SET_BIT(ses->map->room_list[room]->flags, ROOM_FLAG_PATH);
@@ -4876,11 +4966,11 @@ void explore_path(struct session *ses, int run, char *arg1, char *arg2)
 		{
 		{
 			if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW))
 			if (HAS_BIT(ses->map->flags, MAP_FLAG_NOFOLLOW))
 			{
 			{
-				check_append_path(ses, exit->cmd, "", exit->delay, 0);
+				check_append_path(ses, exit->cmd, "", exit->delay, 1, 0);
 			}
 			}
 			else
 			else
 			{
 			{
-				check_append_path(ses, exit->name, "", exit->delay, 0);
+				check_append_path(ses, exit->name, "", exit->delay, 1, 0);
 			}
 			}
 		}
 		}
 
 
@@ -5419,7 +5509,7 @@ DO_MAP(map_dig)
 		return;
 		return;
 	}
 	}
 
 
-	room = (int) tintoi(arg1);
+	room = (int) get_number(ses, arg1);
 
 
 	if (room > 0 && room < ses->map->size)
 	if (room > 0 && room < ses->map->size)
 	{
 	{
@@ -6223,6 +6313,8 @@ DO_MAP(map_goto)
 	}
 	}
 	add_undo(ses, "%d %d %d", room, ses->map->in_room, MAP_UNDO_MOVE);
 	add_undo(ses, "%d %d %d", room, ses->map->in_room, MAP_UNDO_MOVE);
 
 
+	ses->map->dir = 0;
+
 	goto_room(ses, room);
 	goto_room(ses, room);
 
 
 	show_message(ses, LIST_COMMAND, "#MAP GOTO: MOVED TO ROOM %d {%s}.", room, *ses->map->room_list[room]->name ? ses->map->room_list[room]->name : ses->map->room_list[room]->id);
 	show_message(ses, LIST_COMMAND, "#MAP GOTO: MOVED TO ROOM %d {%s}.", room, *ses->map->room_list[room]->name ? ses->map->room_list[room]->name : ses->map->room_list[room]->id);
@@ -6455,6 +6547,8 @@ DO_MAP(map_jump)
 	{
 	{
 		add_undo(ses, "%d %d %d", room, ses->map->in_room, MAP_UNDO_MOVE);
 		add_undo(ses, "%d %d %d", room, ses->map->in_room, MAP_UNDO_MOVE);
 
 
+		ses->map->dir = 0;
+
 		goto_room(ses, room);
 		goto_room(ses, room);
 
 
 		show_message(ses, LIST_COMMAND, "#MAP JUMP: JUMPED TO ROOM %d {%s}.", room, *ses->map->room_list[room]->name ? ses->map->room_list[room]->name : ses->map->room_list[room]->id);
 		show_message(ses, LIST_COMMAND, "#MAP JUMP: JUMPED TO ROOM %d {%s}.", room, *ses->map->room_list[room]->name ? ses->map->room_list[room]->name : ses->map->room_list[room]->id);
@@ -6916,7 +7010,7 @@ DO_MAP(map_map)
 
 
 				if (logfile)
 				if (logfile)
 				{
 				{
-					loginit(ses, logfile, LOG_FLAG_APPEND | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
+					logheader(ses, logfile, LOG_FLAG_APPEND | HAS_BIT(ses->log->mode, LOG_FLAG_HTML));
 				}
 				}
 				else
 				else
 				{
 				{
@@ -6947,7 +7041,7 @@ DO_MAP(map_map)
 
 
 				if (logfile)
 				if (logfile)
 				{
 				{
-					loginit(ses, logfile, LOG_FLAG_OVERWRITE | HAS_BIT(ses->logmode, LOG_FLAG_HTML));
+					logheader(ses, logfile, LOG_FLAG_OVERWRITE | HAS_BIT(ses->log->mode, LOG_FLAG_HTML));
 				}
 				}
 				else
 				else
 				{
 				{
@@ -7727,7 +7821,7 @@ DO_MAP(map_roomflag)
 	}
 	}
 	if (HAS_BIT(flag, ROOM_FLAG_BLOCK))
 	if (HAS_BIT(flag, ROOM_FLAG_BLOCK))
 	{
 	{
-		show_message(ses, LIST_COMMAND, "#MAP: Block flag set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_AVOID) ? "ON" : "OFF");
+		show_message(ses, LIST_COMMAND, "#MAP: Block flag set to %s.", HAS_BIT(ses->map->room_list[ses->map->in_room]->flags, ROOM_FLAG_BLOCK) ? "ON" : "OFF");
 	}
 	}
 	if (HAS_BIT(flag, ROOM_FLAG_CURVED))
 	if (HAS_BIT(flag, ROOM_FLAG_CURVED))
 	{
 	{

+ 0 - 4
src/math.c

@@ -139,12 +139,8 @@ long double get_number(struct session *ses, char *str)
 	long double val;
 	long double val;
 	char result[BUFFER_SIZE];
 	char result[BUFFER_SIZE];
 
 
-	SET_BIT(gtd->flags, TINTIN_FLAG_GETNUMBER);
-
 	val = mathexp(ses, str, result, 0);
 	val = mathexp(ses, str, result, 0);
 
 
-	DEL_BIT(gtd->flags, TINTIN_FLAG_GETNUMBER);
-
 	return val;
 	return val;
 }
 }
 
 

ファイルの差分が大きいため隠しています
+ 0 - 81
src/misc.c


+ 1 - 8
src/nest.c

@@ -549,7 +549,6 @@ int get_nest_size_val(struct listroot *root, char *variable, char **result)
 {
 {
 	char name[BUFFER_SIZE], *arg;
 	char name[BUFFER_SIZE], *arg;
 	int index, count;
 	int index, count;
-	static int warning;
 
 
 	arg = get_arg_to_brackets(root->ses, variable, name);
 	arg = get_arg_to_brackets(root->ses, variable, name);
 
 
@@ -637,14 +636,9 @@ int get_nest_size_val(struct listroot *root, char *variable, char **result)
 		{
 		{
 			if (!strcmp(arg, "[]"))
 			if (!strcmp(arg, "[]"))
 			{
 			{
-				if (++warning < 100)
-				{
-					tintin_printf2(root->ses, "\n\e[1;5;31mdebug: please use *%s instead of $%s.\n", variable, variable);
-				}
-
 				for (index = 0 ; index < root->used ; index++)
 				for (index = 0 ; index < root->used ; index++)
 				{
 				{
-					str_cat_printf(result, "{%s}", root->list[index]->arg1);
+					str_cat_printf(result, "{%s}", root->list[index]->arg2);
 				}
 				}
 				return root->used + 1;
 				return root->used + 1;
 			}
 			}
@@ -980,7 +974,6 @@ struct listnode *set_nest_node_ses(struct session *ses, char *arg1, char *format
 		arg = get_arg_to_brackets(ses, arg1, name);
 		arg = get_arg_to_brackets(ses, arg1, name);
 
 
 		check_all_events(root->ses, EVENT_FLAG_VARIABLE, 1, 3, "VARIABLE UPDATED %s", name, name, arg2, arg1);
 		check_all_events(root->ses, EVENT_FLAG_VARIABLE, 1, 3, "VARIABLE UPDATED %s", name, name, arg2, arg1);
-		check_all_events(root->ses, EVENT_FLAG_VARIABLE, 1, 3, "VARIABLE UPDATED %s", arg1, name, arg2, arg1);
 	}
 	}
 	free(arg2);
 	free(arg2);
 
 

+ 1 - 0
src/net.c

@@ -32,6 +32,7 @@
 #include <netinet/in.h>
 #include <netinet/in.h>
 #include <netdb.h>
 #include <netdb.h>
 #include <signal.h>
 #include <signal.h>
+#include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/types.h>
 
 
 /*
 /*

+ 11 - 10
src/parse.c

@@ -171,7 +171,7 @@ struct session *parse_input(struct session *ses, char *input)
 	char *line;
 	char *line;
 
 
 	push_call("parse_input(%s,%s)",ses->name,input);
 	push_call("parse_input(%s,%s)",ses->name,input);
-
+/*
 	if (*input == 0)
 	if (*input == 0)
 	{
 	{
 		write_mud(ses, input, SUB_EOL);
 		write_mud(ses, input, SUB_EOL);
@@ -179,7 +179,7 @@ struct session *parse_input(struct session *ses, char *input)
 		pop_call();
 		pop_call();
 		return ses;
 		return ses;
 	}
 	}
-
+*/
 	line = str_alloc_stack(0);
 	line = str_alloc_stack(0);
 
 
 	if (VERBATIM(ses))
 	if (VERBATIM(ses))
@@ -211,7 +211,7 @@ struct session *parse_input(struct session *ses, char *input)
 		return ses;
 		return ses;
 	}
 	}
 
 
-	while (*input)
+	do
 	{
 	{
 		input = space_out(input);
 		input = space_out(input);
 
 
@@ -239,6 +239,7 @@ struct session *parse_input(struct session *ses, char *input)
 			input++;
 			input++;
 		}
 		}
 	}
 	}
+	while (*input);
 
 
 	pop_call();
 	pop_call();
 	return ses;
 	return ses;
@@ -664,7 +665,7 @@ char *get_arg_in_braces(struct session *ses, char *string, char *result, int fla
 
 
 	if (*pti == 0)
 	if (*pti == 0)
 	{
 	{
-		tintin_printf2(ses, "#ERROR: GET BRACED ARGUMENT: UNMATCHED BRACE.");
+		show_error(ses, LIST_COMMAND, "#ERROR: GET BRACED ARGUMENT: UNMATCHED BRACE.");
 	}
 	}
 	else
 	else
 	{
 	{
@@ -1025,7 +1026,7 @@ char *get_arg_at_brackets(struct session *ses, char *string, char *result)
 
 
 	if (nest)
 	if (nest)
 	{
 	{
-		tintin_printf2(NULL, "#ERROR: GET BRACKETED VARIABLE: UNMATCHED BRACKET.");
+		show_error(ses, LIST_COMMAND, "#ERROR: GET BRACKETED VARIABLE: UNMATCHED BRACKET.");
 	}
 	}
 	*pto = 0;
 	*pto = 0;
 
 
@@ -1076,7 +1077,7 @@ char *get_arg_in_brackets(struct session *ses, char *string, char *result)
 
 
 	if (*pti == 0)
 	if (*pti == 0)
 	{
 	{
-		tintin_printf2(NULL, "#ERROR: GET BRACKETED ARGUMENT: UNMATCHED BRACKET.");
+		show_error(ses, LIST_COMMAND, "#ERROR: GET BRACKETED ARGUMENT: UNMATCHED BRACKET.");
 	}
 	}
 	else
 	else
 	{
 	{
@@ -1122,7 +1123,7 @@ void write_mud(struct session *ses, char *command, int flags)
 	{
 	{
 		if (ses->map == NULL || ses->map->nofollow == 0)
 		if (ses->map == NULL || ses->map->nofollow == 0)
 		{
 		{
-			check_append_path(ses, command, NULL, 0.0, 1);
+			check_append_path(ses, command, NULL, 0.0, 0, 1);
 		}
 		}
 	}
 	}
 
 
@@ -1195,11 +1196,11 @@ void do_one_line(char *line, struct session *ses)
 		check_all_highlights(ses, line, strip);
 		check_all_highlights(ses, line, strip);
 	}
 	}
 
 
-	if (HAS_BIT(ses->logmode, LOG_FLAG_NEXT))
+	if (HAS_BIT(ses->log->mode, LOG_FLAG_NEXT))
 	{
 	{
-		logit(ses, line, ses->lognext_file, LOG_FLAG_LINEFEED);
+		logit(ses, line, ses->log->next_file, LOG_FLAG_LINEFEED);
 
 
-		DEL_BIT(ses->logmode, LOG_FLAG_NEXT);
+		DEL_BIT(ses->log->mode, LOG_FLAG_NEXT);
 	}
 	}
 
 
 	pop_script_stack();
 	pop_script_stack();

+ 16 - 62
src/path.c

@@ -299,6 +299,10 @@ DO_PATH(path_get)
 			(root->list[root->update]->val64 - gtd->utime) / 1000000.0);
 			(root->list[root->update]->val64 - gtd->utime) / 1000000.0);
 	}
 	}
 	else if (*arg2 == 0)
 	else if (*arg2 == 0)
+	{
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #PATH GET <INFO|LENGTH|MAPPING|POSITION|RUNNING> <VARIABLE NAME>");
+	}
+	else if (is_abbrev(arg1, "INFO"))
 	{
 	{
 		set_nest_node_ses(ses, arg2, "{length}{%d}", root->used);
 		set_nest_node_ses(ses, arg2, "{length}{%d}", root->used);
 
 
@@ -350,7 +354,7 @@ DO_PATH(path_get)
 	}
 	}
 	else
 	else
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #PATH GET <LENGTH|POSITION> <VARIABLE NAME>");
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #PATH GET <INFO|LENGTH|MAPPING|POSITION|RUNNING> <VARIABLE NAME>");
 	}
 	}
 }
 }
 
 
@@ -510,7 +514,6 @@ DO_PATH(path_delete)
 
 
 DO_PATH(path_insert)
 DO_PATH(path_insert)
 {
 {
-	struct listroot *root = ses->list[LIST_PATH];
 	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[BUFFER_SIZE];
 	char arg1[BUFFER_SIZE], arg2[BUFFER_SIZE], arg3[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);
@@ -523,14 +526,9 @@ DO_PATH(path_insert)
 	}
 	}
 	else
 	else
 	{
 	{
-		create_node_list(root, arg1, arg2, arg3, "");
-
 		show_message(ses, LIST_COMMAND, "#PATH INSERT: FORWARD {%s} BACKWARD {%s} DELAY {%s}.", arg1, arg2, arg3);
 		show_message(ses, LIST_COMMAND, "#PATH INSERT: FORWARD {%s} BACKWARD {%s} DELAY {%s}.", arg1, arg2, arg3);
 
 
-		if (HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING))
-		{
-			root->update = root->used;
-		}
+		check_append_path(ses, arg1, arg2, (float) get_number(ses, arg3), 1, HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING));
 	}
 	}
 }
 }
 
 
@@ -835,59 +833,6 @@ DO_PATH(path_unzip)
 			}
 			}
 		}
 		}
 	}
 	}
-/*
-		arg = get_arg_in_braces(ses, arg, temp, GET_ALL);
-
-		if (is_speedwalk(ses, temp))
-		{
-			char dir[2];
-			int cnt, i;
-
-			str = temp;
-
-			for (dir[1] = 0 ; *str ; str++)
-			{
-				if (is_digit(*str))
-				{
-					sscanf(str, "%d%c", &cnt, dir);
-
-					while (*str != dir[0])
-					{
-						str++;
-					}
-				}
-				else
-				{
-					cnt = 1;
-					dir[0] = *str;
-				}
-
-				for (i = 0 ; i < cnt ; i++)
-				{
-					if ((node = search_node_list(ses->list[LIST_PATHDIR], dir)))
-					{
-						create_node_list(root, node->arg1, node->arg2, "0", "");
-					}
-					else
-					{
-						create_node_list(root, dir, dir, "0", "");
-					}
-				}
-			}
-		}
-		else
-		{
-			if ((node = search_node_list(ses->list[LIST_PATHDIR], temp)))
-			{
-				create_node_list(root, node->arg1, node->arg2, "0", "");
-			}
-			else
-			{
-				create_node_list(root, temp, temp, "0", "");
-			}
-		}
-	}
-*/
 	show_message(ses, LIST_COMMAND, "#PATH UNZIP: PATH WITH %d NODES UNZIPPED.", root->used);
 	show_message(ses, LIST_COMMAND, "#PATH UNZIP: PATH WITH %d NODES UNZIPPED.", root->used);
 }
 }
 
 
@@ -1009,7 +954,7 @@ DO_PATH(path_undo)
 	show_message(ses, LIST_COMMAND, "#PATH MOVE: POSITION SET TO %d.", root->update);
 	show_message(ses, LIST_COMMAND, "#PATH MOVE: POSITION SET TO %d.", root->update);
 }
 }
 
 
-void check_append_path(struct session *ses, char *forward, char *backward, float delay, int follow)
+void check_append_path(struct session *ses, char *forward, char *backward, float delay, int force, int follow)
 {
 {
 	struct listroot *root = ses->list[LIST_PATH];
 	struct listroot *root = ses->list[LIST_PATH];
 	struct listnode *node;
 	struct listnode *node;
@@ -1024,6 +969,15 @@ void check_append_path(struct session *ses, char *forward, char *backward, float
 
 
 			root->update = root->used;
 			root->update = root->used;
 		}
 		}
+		else if (force)
+		{
+			show_debug(ses, LIST_PATHDIR, "#DEBUG PATHDIR {%s} {%s}", forward, backward);
+				
+			create_node_list(root, forward, backward, ftos(delay), "");
+
+			root->update = root->used;
+		}
+				
 	}
 	}
 	else
 	else
 	{
 	{

+ 1 - 1
src/regex.c

@@ -1190,7 +1190,7 @@ void tintin_macro_compile(char *input, char *output)
 
 
 					case 'n':
 					case 'n':
 						*pto++ = ASCII_LF;
 						*pto++ = ASCII_LF;
-						*pti += 2;
+						pti  += 2;
 						break;
 						break;
 
 
 					case 'r':
 					case 'r':

+ 1 - 0
src/scan.c

@@ -33,6 +33,7 @@
   #endif
   #endif
 #endif
 #endif
 #include <dirent.h>
 #include <dirent.h>
+#include <limits.h>
 
 
 #define DO_SCAN(scan) struct session *scan(struct session *ses, FILE *fp, char *arg, char *arg1, char *arg2)
 #define DO_SCAN(scan) struct session *scan(struct session *ses, FILE *fp, char *arg, char *arg1, char *arg2)
 
 

+ 18 - 25
src/session.c

@@ -30,15 +30,15 @@
 
 
 DO_COMMAND(do_all)
 DO_COMMAND(do_all)
 {
 {
-	struct session *sesptr;
+	struct session *sesptr, *sesptr_next;
 
 
 	if (gts->next)
 	if (gts->next)
 	{
 	{
 		sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
 		sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
 
 
-		for (sesptr = gts->next ; sesptr ; sesptr = gtd->all)
+		for (sesptr = gts->next ; sesptr ; sesptr = sesptr_next)
 		{
 		{
-			gtd->all = sesptr->next;
+			sesptr_next = sesptr->next;
 
 
 			if (!HAS_BIT(sesptr->flags, SES_FLAG_CLOSED))
 			if (!HAS_BIT(sesptr->flags, SES_FLAG_CLOSED))
 			{
 			{
@@ -80,7 +80,7 @@ DO_COMMAND(do_session)
 				sesptr->ssl ? "(ssl)" : sesptr->port ? "(port)" : HAS_BIT(sesptr->flags, SES_FLAG_RUN) ? " (run)" : "",
 				sesptr->ssl ? "(ssl)" : sesptr->port ? "(port)" : HAS_BIT(sesptr->flags, SES_FLAG_RUN) ? " (run)" : "",
 				sesptr->mccp2 && sesptr->mccp3 ? "(mccp 2+3)" : sesptr->mccp2 ? "(mccp 2)" : sesptr->mccp3 ? "(mccp 3)" : "",
 				sesptr->mccp2 && sesptr->mccp3 ? "(mccp 2+3)" : sesptr->mccp2 ? "(mccp 2)" : sesptr->mccp3 ? "(mccp 3)" : "",
 				HAS_BIT(sesptr->flags, SES_FLAG_SNOOP|SES_FLAG_SNOOPSCROLL) ? "(snoop)" : "",
 				HAS_BIT(sesptr->flags, SES_FLAG_SNOOP|SES_FLAG_SNOOPSCROLL) ? "(snoop)" : "",
-				sesptr->logfile ? "(log)" : "");
+				sesptr->log->file ? "(log)" : "");
 		}
 		}
 	}
 	}
 	else if (*arg1 && *arg == 0)
 	else if (*arg1 && *arg == 0)
@@ -404,7 +404,6 @@ struct session *new_session(struct session *ses, char *name, char *arg, int desc
 	newses->flags          = gts->flags;
 	newses->flags          = gts->flags;
 	newses->config_flags   = gts->config_flags;
 	newses->config_flags   = gts->config_flags;
 	newses->color          = gts->color;
 	newses->color          = gts->color;
-	newses->logmode        = gts->logmode;
 	newses->charset        = gts->charset;
 	newses->charset        = gts->charset;
 
 
 	newses->telopts        = gts->telopts;
 	newses->telopts        = gts->telopts;
@@ -416,9 +415,6 @@ struct session *new_session(struct session *ses, char *name, char *arg, int desc
 	newses->read_max       = gts->read_max;
 	newses->read_max       = gts->read_max;
 	newses->read_buf       = (unsigned char *) calloc(1, gts->read_max);
 	newses->read_buf       = (unsigned char *) calloc(1, gts->read_max);
 
 
-	newses->logname        = strdup("");
-	newses->lognext_name   = strdup("");
-	newses->logline_name   = strdup("");
 	newses->rand           = ++gtd->utime;
 	newses->rand           = ++gtd->utime;
 
 
 	newses->more_output    = str_dup("");
 	newses->more_output    = str_dup("");
@@ -458,13 +454,16 @@ struct session *new_session(struct session *ses, char *name, char *arg, int desc
 
 
 	newses->wrap          = gts->wrap;
 	newses->wrap          = gts->wrap;
 
 
-	newses->scroll        = calloc(1, sizeof(struct scroll_data));
-	init_buffer(newses, gts->scroll->size);
+	newses->log           = calloc(1, sizeof(struct log_data));
+	init_log(newses);
+	ses->log->mode        = gts->log->mode;
 
 
 	newses->input         = calloc(1, sizeof(struct input_data));
 	newses->input         = calloc(1, sizeof(struct input_data));
-
 	init_input(newses, 0, 0, 0, 0);
 	init_input(newses, 0, 0, 0, 0);
 
 
+	newses->scroll        = calloc(1, sizeof(struct scroll_data));
+	init_buffer(newses, gts->scroll->size);
+
 	memcpy(&newses->cur_terminal, &gts->cur_terminal, sizeof(gts->cur_terminal));
 	memcpy(&newses->cur_terminal, &gts->cur_terminal, sizeof(gts->cur_terminal));
 
 
 	if (desc == 0)
 	if (desc == 0)
@@ -651,11 +650,6 @@ void cleanup_session(struct session *ses)
 		gtd->update = ses->next;
 		gtd->update = ses->next;
 	}
 	}
 
 
-	if (ses == gtd->all)
-	{
-		gtd->all = ses->next;
-	}
-
 	UNLINK(ses, gts->next, gts->prev);
 	UNLINK(ses, gts->next, gts->prev);
 
 
 	if (ses->socket)
 	if (ses->socket)
@@ -748,19 +742,19 @@ void dispose_session(struct session *ses)
 
 
 	UNLINK(ses, gtd->dispose_next, gtd->dispose_prev);
 	UNLINK(ses, gtd->dispose_next, gtd->dispose_prev);
 
 
-	if (ses->logfile)
+	if (ses->log->file)
 	{
 	{
-		fclose(ses->logfile);
+		fclose(ses->log->file);
 	}
 	}
 
 
-	if (ses->lognext_file)
+	if (ses->log->next_file)
 	{
 	{
-		fclose(ses->lognext_file);
+		fclose(ses->log->next_file);
 	}
 	}
 
 
-	if (ses->logline_file)
+	if (ses->log->line_file)
 	{
 	{
-		fclose(ses->logline_file);
+		fclose(ses->log->line_file);
 	}
 	}
 
 
 	if (ses->map)
 	if (ses->map)
@@ -777,6 +771,8 @@ void dispose_session(struct session *ses)
 
 
 	free_input(ses);
 	free_input(ses);
 
 
+	free_log(ses);
+
 	free(ses->name);
 	free(ses->name);
 	free(ses->session_host);
 	free(ses->session_host);
 	free(ses->session_ip);
 	free(ses->session_ip);
@@ -784,9 +780,6 @@ void dispose_session(struct session *ses)
 	free(ses->group);
 	free(ses->group);
 	free(ses->read_buf);
 	free(ses->read_buf);
 	free(ses->cmd_color);
 	free(ses->cmd_color);
-	free(ses->logname);
-	free(ses->lognext_name);
-	free(ses->logline_name);
 	free(ses->split);
 	free(ses->split);
 	free(ses->input);
 	free(ses->input);
 
 

+ 48 - 36
src/show.c

@@ -31,14 +31,14 @@
 DO_COMMAND(do_showme)
 DO_COMMAND(do_showme)
 {
 {
 	char *out, *tmp;
 	char *out, *tmp;
-	int lnf;
+	int prompt;
 
 
 	out = str_alloc_stack(0);
 	out = str_alloc_stack(0);
 	tmp = str_alloc_stack(0);
 	tmp = str_alloc_stack(0);
 
 
 	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
 	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
 
 
-	lnf = is_suffix(arg1, "\\") && !is_suffix(arg1, "\\\\");
+	prompt = is_suffix(arg1, "\\") && !is_suffix(arg1, "\\\\");
 
 
 	substitute(ses, arg1, tmp, SUB_VAR|SUB_FUN);
 	substitute(ses, arg1, tmp, SUB_VAR|SUB_FUN);
 	substitute(ses, tmp, arg1, SUB_COL|SUB_ESC);
 	substitute(ses, tmp, arg1, SUB_COL|SUB_ESC);
@@ -64,34 +64,46 @@ DO_COMMAND(do_showme)
 		return ses;
 		return ses;
 	}
 	}
 
 
-	if (strip_vt102_strlen(ses, ses->more_output) != 0)
-	{
-		str_cpy_printf(&out, "\n%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
-	}
-	else
-	{
-		str_cpy_printf(&out, "%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
-	}
+	str_cpy_printf(&out, "%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
 
 
-	add_line_buffer(ses, out, lnf);
+	tintin_puts3(ses, out, prompt);
 
 
-	if (ses == gtd->ses)
-	{
-		if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
-		{
-			save_pos(ses);
+	return ses;
+}
 
 
-			goto_pos(ses, ses->split->bot_row, ses->split->top_col);
-		}
+DO_COMMAND(do_echo)
+{
+	char *result, *out;
+	int prompt;
 
 
-		print_line(ses, &out, lnf);
+	result = arg2;
 
 
-		if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
-		{
-			restore_pos(ses);
-		}
+	out = str_alloc_stack(0);
+
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
+
+	format_string(ses, arg1, arg, result);
+
+	arg = get_arg_in_braces(ses, result, arg1, GET_ALL);
+
+	prompt = is_suffix(arg1, "\\") && !is_suffix(arg1, "\\\\");
+
+	substitute(ses, arg1, arg1, SUB_COL|SUB_ESC);
+
+	arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
+	arg = sub_arg_in_braces(ses, arg, arg3, GET_ONE, SUB_VAR|SUB_FUN);
+
+	if (*arg2)
+	{
+		split_show(ses, arg1, arg2, arg3);
+
+		return ses;
 	}
 	}
 
 
+	str_cpy_printf(&out, "%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
+
+	tintin_puts3(ses, out, prompt);
+
 	return ses;
 	return ses;
 }
 }
 
 
@@ -150,7 +162,7 @@ void show_message(struct session *ses, int index, char *format, ...)
 
 
 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
 	{
 	{
-		if (ses->logfile)
+		if (ses->log->file)
 		{
 		{
 			va_start(args, format);
 			va_start(args, format);
 
 
@@ -163,7 +175,7 @@ void show_message(struct session *ses, int index, char *format, ...)
 			}
 			}
 			va_end(args);
 			va_end(args);
 
 
-			logit(ses, buffer, ses->logfile, LOG_FLAG_LINEFEED);
+			logit(ses, buffer, ses->log->file, LOG_FLAG_LINEFEED);
 
 
 			free(buffer);
 			free(buffer);
 		}
 		}
@@ -218,9 +230,9 @@ void show_error(struct session *ses, int index, char *format, ...)
 
 
 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
 	{
 	{
-		if (ses->logfile)
+		if (ses->log->file)
 		{
 		{
-			logit(ses, buffer, ses->logfile, LOG_FLAG_LINEFEED);
+			logit(ses, buffer, ses->log->file, LOG_FLAG_LINEFEED);
 		}
 		}
 	}
 	}
 
 
@@ -268,9 +280,9 @@ void show_debug(struct session *ses, int index, char *format, ...)
 
 
 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
 	if (HAS_BIT(root->flags, LIST_FLAG_LOG))
 	{
 	{
-		if (ses->logfile)
+		if (ses->log->file)
 		{
 		{
-			logit(ses, buf, ses->logfile, LOG_FLAG_LINEFEED);
+			logit(ses, buf, ses->log->file, LOG_FLAG_LINEFEED);
 		}
 		}
 	}
 	}
 	pop_call();
 	pop_call();
@@ -363,7 +375,7 @@ void show_lines(struct session *ses, char *str)
 		}
 		}
 		*ptf++ = 0;
 		*ptf++ = 0;
 
 
-		tintin_puts3(ses, str);
+		tintin_puts3(ses, str, FALSE);
 
 
 		str = ptf;
 		str = ptf;
 	}
 	}
@@ -503,7 +515,7 @@ void tintin_puts2(struct session *ses, char *string)
 
 
 	str_cpy_printf(&output, "%s%s%s", COLOR_TEXT, string, COLOR_TEXT);
 	str_cpy_printf(&output, "%s%s%s", COLOR_TEXT, string, COLOR_TEXT);
 
 
-	tintin_puts3(ses, output);
+	tintin_puts3(ses, output, FALSE);
 
 
 	pop_call();
 	pop_call();
 	return;
 	return;
@@ -515,11 +527,11 @@ void tintin_puts2(struct session *ses, char *string)
 	show string, no triggers, no color reset
 	show string, no triggers, no color reset
 */
 */
 
 
-void tintin_puts3(struct session *ses, char *string)
+void tintin_puts3(struct session *ses, char *string, int prompt)
 {
 {
 	char *output;
 	char *output;
 
 
-	push_call("tintin_puts3(%p,%p)",ses,string);
+	push_call("tintin_puts3(%p,%p,%d)",ses,string,prompt);
 
 
 	if (ses == NULL)
 	if (ses == NULL)
 	{
 	{
@@ -552,10 +564,10 @@ void tintin_puts3(struct session *ses, char *string)
 	}
 	}
 	else
 	else
 	{
 	{
-		str_cpy_printf(&output, "%s", string);
+		str_cpy(&output, string);
 	}
 	}
 
 
-	add_line_buffer(ses, output, FALSE);
+	add_line_buffer(ses, output, prompt);
 
 
 	if (ses == gtd->ses)
 	if (ses == gtd->ses)
 	{
 	{
@@ -566,7 +578,7 @@ void tintin_puts3(struct session *ses, char *string)
 			goto_pos(ses, ses->split->bot_row, ses->split->top_col);
 			goto_pos(ses, ses->split->bot_row, ses->split->top_col);
 		}
 		}
 
 
-		print_line(ses, &output, FALSE);
+		print_line(ses, &output, prompt);
 
 
 		if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
 		if (!HAS_BIT(ses->flags, SES_FLAG_READMUD) && IS_SPLIT(ses))
 		{
 		{

+ 4 - 5
src/split.c

@@ -258,7 +258,7 @@ void dirty_screen(struct session *ses)
 void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 {
 {
 	char buf1[BUFFER_SIZE];
 	char buf1[BUFFER_SIZE];
-	int row, col, len, width, clear;
+	int row, col, width, clear;
 
 
 	row = 0;
 	row = 0;
 
 
@@ -315,7 +315,7 @@ void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 		return;
 		return;
 	}
 	}
 
 
-	len = strip_vt102_width(ses, prompt, &width);
+	strip_vt102_width(ses, prompt, &width);
 
 
 	if (col - 1 + width <= gtd->screen->cols)
 	if (col - 1 + width <= gtd->screen->cols)
 	{
 	{
@@ -323,11 +323,10 @@ void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 	}
 	}
 	else
 	else
 	{
 	{
-		show_debug(ses, LIST_PROMPT, "#DEBUG PROMPT {%s}", prompt);
+		sprintf(buf1, "%.*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, "#PROMPT WIDTH %d WITH OFFSET %d LONGER THAN ROW SIZE %d.", width, col, gtd->screen->cols);
-
-		sprintf(buf1, "#PROMPT WIDTH %d WITH OFFSET %d LONGER THAN ROW SIZE %d.", len, col, gtd->screen->cols);
 	}
 	}
 
 
 	save_pos(ses);
 	save_pos(ses);

+ 2 - 0
src/ssl.c

@@ -363,6 +363,8 @@ nocert:
 		{
 		{
 			tintin_printf(ses, "#SSL ERROR: %s", err);
 			tintin_printf(ses, "#SSL ERROR: %s", err);
 
 
+			get_cert_file(ses, filename);
+
 			tintin_printf(ses, "#SSL ALERT: THE SERVER'S SETTINGS WERE CHANGED IN AN UNEXPECTED WAY.");
 			tintin_printf(ses, "#SSL ALERT: THE SERVER'S SETTINGS WERE CHANGED IN AN UNEXPECTED WAY.");
 			tintin_printf(ses, "#SSL ALERT: YOU MAY BE VULNERABLE TO MAN-IN-THE-MIDDLE ATTACKS.");
 			tintin_printf(ses, "#SSL ALERT: YOU MAY BE VULNERABLE TO MAN-IN-THE-MIDDLE ATTACKS.");
 			tintin_printf(ses, "#SSL ALERT: TO CONTINUE, PLEASE DELETE THE FILE:");
 			tintin_printf(ses, "#SSL ALERT: TO CONTINUE, PLEASE DELETE THE FILE:");

+ 5 - 5
src/string.c

@@ -84,7 +84,7 @@ int str_len_str(struct session *ses, char *str, int start, int end)
 		}
 		}
 		else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(str))
 		else if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(str))
 		{
 		{
-			tmp_cnt = get_utf8_width(str, &width);
+			tmp_cnt = get_utf8_width(str, &width, NULL);
 
 
 			if (str_cnt >= start)
 			if (str_cnt >= start)
 			{
 			{
@@ -133,7 +133,7 @@ int str_len_raw(struct session *ses, char *str, int start, int end)
 		}
 		}
 		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]))
 		{
 		{
-			raw_cnt += get_utf8_width(&str[raw_cnt], &width);
+			raw_cnt += get_utf8_width(&str[raw_cnt], &width, NULL);
 			ret_cnt += width;
 			ret_cnt += width;
 		}
 		}
 		else
 		else
@@ -170,7 +170,7 @@ int raw_len_str(struct session *ses, char *str, int start, int end)
 		}
 		}
 		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);
+			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 
 
 			if (str_cnt >= start)
 			if (str_cnt >= start)
 			{
 			{
@@ -229,7 +229,7 @@ int raw_len_str_min(struct session *ses, char *str, int start, int end)
 		}
 		}
 		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);
+			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 
 
 			if (str_cnt >= start)
 			if (str_cnt >= start)
 			{
 			{
@@ -288,7 +288,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);
+			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 
 
 			if (str_cnt >= start)
 			if (str_cnt >= start)
 			{
 			{

+ 68 - 23
src/substitute.c

@@ -329,19 +329,11 @@ int is_variable(struct session *ses, char *str)
 
 
 	if (root == NULL)
 	if (root == NULL)
 	{
 	{
-		if (str[0] == '&' && HAS_BIT(gtd->flags, TINTIN_FLAG_GETNUMBER))
-		{
-			show_error(ses, LIST_VARIABLE, "\e[1;31m#WARNING: FOUND %c%s. USE %c{%s} INSTEAD?", str[0], temp, str[0], temp);
-		}
 		return FALSE;
 		return FALSE;
 	}
 	}
 
 
 	if (search_node_list(root, temp) == NULL)
 	if (search_node_list(root, temp) == NULL)
 	{
 	{
-		if (str[0] == '&' && HAS_BIT(gtd->flags, TINTIN_FLAG_GETNUMBER))
-		{
-			show_error(ses, LIST_VARIABLE, "\e[1;31m#WARNING: FOUND %c%s. USE %c{%s} INSTEAD?", str[0], temp, str[0], temp);
-		}
 		return FALSE;
 		return FALSE;
 	}
 	}
 
 
@@ -1069,7 +1061,22 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 			case '\0':
 			case '\0':
 				if (HAS_BIT(flags, SUB_EOL))
 				if (HAS_BIT(flags, SUB_EOL))
 				{
 				{
-					if (HAS_BIT(ses->flags, SES_FLAG_RUN))
+					if (HAS_BIT(ses->telopts, TELOPT_FLAG_CR|TELOPT_FLAG_LF))
+					{
+						if (HAS_BIT(ses->telopts, TELOPT_FLAG_CR))
+						{
+							*pto++ = '\r';
+						}
+						if (HAS_BIT(ses->telopts, TELOPT_FLAG_LF))
+						{
+							*pto++ = '\n';
+						}
+						if (HAS_BIT(ses->telopts, TELOPT_FLAG_NUL))
+						{
+							*pto++ = '\0';
+						}
+					}
+					else if (HAS_BIT(ses->flags, SES_FLAG_RUN))
 					{
 					{
 						*pto++ = '\r';
 						*pto++ = '\r';
 					}
 					}
@@ -1703,6 +1710,30 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 								}
 								}
 								ptt++;
 								ptt++;
 							}
 							}
+							else if (HAS_BIT(flags, SUB_BRA))
+							{
+								switch (*ptt)
+								{
+									case '{':
+										*pto++ = '\\';
+										*pto++ = 'x';
+										*pto++ = '7';
+										*pto++ = 'B';
+										break;
+
+									case '}':
+										*pto++ = '\\';
+										*pto++ = 'x';
+										*pto++ = '7';
+										*pto++ = 'D';
+										break;
+
+									default:
+										*pto++ = *ptt;
+										break;
+								}
+								ptt++;
+							}
 							else
 							else
 							{
 							{
 								*pto++ = *ptt++;
 								*pto++ = *ptt++;
@@ -2133,6 +2164,34 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 				}
 				}
 				break;
 				break;
 
 
+			case '{':
+			case '}':
+				if (HAS_BIT(flags, SUB_SEC|SUB_BRA) && !HAS_BIT(flags, SUB_ARG))
+				{
+					switch (*pti)
+					{
+						case '{':
+							*pto++ = '\\';
+							*pto++ = 'x';
+							*pto++ = '7';
+							*pto++ = 'B';
+							break;
+
+						case '}':
+							*pto++ = '\\';
+							*pto++ = 'x';
+							*pto++ = '7';
+							*pto++ = 'D';
+							break;
+					}
+					pti++;
+				}
+				else
+				{
+					*pto++ = *pti++;
+				}
+				break;	
+
 			default:
 			default:
 				if (HAS_BIT(flags, SUB_SEC) && !HAS_BIT(flags, SUB_ARG))
 				if (HAS_BIT(flags, SUB_SEC) && !HAS_BIT(flags, SUB_ARG))
 				{
 				{
@@ -2152,20 +2211,6 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 							}
 							}
 							break;
 							break;
 
 
-						case '{':
-							*pto++ = '\\';
-							*pto++ = 'x';
-							*pto++ = '7';
-							*pto++ = 'B';
-							break;
-
-						case '}':
-							*pto++ = '\\';
-							*pto++ = 'x';
-							*pto++ = '7';
-							*pto++ = 'D';
-							break;
-
 						case COMMAND_SEPARATOR:
 						case COMMAND_SEPARATOR:
 							*pto++ = '\\';
 							*pto++ = '\\';
 							*pto++ = COMMAND_SEPARATOR;
 							*pto++ = COMMAND_SEPARATOR;

+ 13 - 15
src/tables.c

@@ -57,15 +57,16 @@ struct list_type list_table[LIST_MAX] =
 struct substitution_type substitution_table[] =
 struct substitution_type substitution_table[] =
 {
 {
 	{    "ARGUMENTS",            SUB_ARG },
 	{    "ARGUMENTS",            SUB_ARG },
-	{    "VARIABLES",            SUB_VAR },
-	{    "FUNCTIONS",            SUB_FUN },
+	{    "BRACES",               SUB_BRA },
 	{    "COLORS",               SUB_COL },
 	{    "COLORS",               SUB_COL },
-	{    "ESCAPES",              SUB_ESC },
 //	{    "COMMANDS",             SUB_CMD },
 //	{    "COMMANDS",             SUB_CMD },
-	{    "SECURE",               SUB_SEC },
 	{    "EOL",                  SUB_EOL },
 	{    "EOL",                  SUB_EOL },
-	{    "LNF",                  SUB_LNF },
+	{    "ESCAPES",              SUB_ESC },
+	{    "FUNCTIONS",            SUB_FUN },
         {    "LITERAL",              SUB_LIT },
         {    "LITERAL",              SUB_LIT },
+	{    "LNF",                  SUB_LNF },
+	{    "SECURE",               SUB_SEC },
+	{    "VARIABLES",            SUB_VAR },
 	{    "",                     0       }
 	{    "",                     0       }
 };
 };
 
 
@@ -927,7 +928,7 @@ struct cursor_type cursor_table[] =
 	{     "",                   "",                                               "\e[1;2a",                        0,    cursor_buffer_up,             ""          },
 	{     "",                   "",                                               "\e[1;2a",                        0,    cursor_buffer_up,             ""          },
 	{     "",                   "",                                               "\e[1;2b",                        0,    cursor_buffer_down,           ""          },
 	{     "",                   "",                                               "\e[1;2b",                        0,    cursor_buffer_down,           ""          },
 	{     "",                   "",                                               "",                              0,    cursor_buffer_lock,           ""          },
 	{     "",                   "",                                               "",                              0,    cursor_buffer_lock,           ""          },
-//	{     "",                   "",                                               "\e[13;2u",                       0,    cursor_enter,                 ""          },
+	{     "",                   "",                                               "\e[13;129u",                     0,    cursor_enter,                 ""          },
 	{     "",                   "",                                               "\eOM",                           0,    cursor_enter,                 ""          },
 	{     "",                   "",                                               "\eOM",                           0,    cursor_enter,                 ""          },
 	{     "",                   "",                                               "\e[7~",                          0,    cursor_home,                  ""          },
 	{     "",                   "",                                               "\e[7~",                          0,    cursor_home,                  ""          },
 	{     "",                   "",                                               "\e[1~",                          0,    cursor_home,                  ""          },
 	{     "",                   "",                                               "\e[1~",                          0,    cursor_home,                  ""          },
@@ -935,15 +936,20 @@ struct cursor_type cursor_table[] =
 	{     "",                   "",                                               "\e[H",                           0,    cursor_home,                  ""          },
 	{     "",                   "",                                               "\e[H",                           0,    cursor_home,                  ""          },
 	{     "",                   "",                                               "\eOD",                           0,    cursor_move_left,             ""          },
 	{     "",                   "",                                               "\eOD",                           0,    cursor_move_left,             ""          },
 	{     "",                   "",                                               "\e[D",                           0,    cursor_move_left,             ""          },
 	{     "",                   "",                                               "\e[D",                           0,    cursor_move_left,             ""          },
+	{     "",                   "",                                               "\e[1;129D",                      0,    cursor_move_left,             ""          },
 	{     "",                   "",                                               "\e[8~",                          0,    cursor_end,                   ""          },
 	{     "",                   "",                                               "\e[8~",                          0,    cursor_end,                   ""          },
 	{     "",                   "",                                               "\e[4~",                          0,    cursor_end,                   ""          },
 	{     "",                   "",                                               "\e[4~",                          0,    cursor_end,                   ""          },
 	{     "",                   "",                                               "\eOF",                           0,    cursor_end,                   ""          },
 	{     "",                   "",                                               "\eOF",                           0,    cursor_end,                   ""          },
 	{     "",                   "",                                               "\e[F",                           0,    cursor_end,                   ""          },
 	{     "",                   "",                                               "\e[F",                           0,    cursor_end,                   ""          },
 	{     "",                   "",                                               "\eOC",                           0,    cursor_move_right,            ""          },
 	{     "",                   "",                                               "\eOC",                           0,    cursor_move_right,            ""          },
 	{     "",                   "",                                               "\e[C",                           0,    cursor_move_right,            ""          },
 	{     "",                   "",                                               "\e[C",                           0,    cursor_move_right,            ""          },
+	{     "",                   "",                                               "\e[1;129C",                      0,    cursor_move_right,            ""          },
 	{     "",                   "",                                               "\x7F",                           0,    cursor_backspace,             ""          },
 	{     "",                   "",                                               "\x7F",                           0,    cursor_backspace,             ""          },
+	{     "",                   "",                                               "\e[127;129u",                    0,    cursor_backspace,             ""          },
 	{     "",                   "",                                               "\eOB",                           0,    cursor_move_down,             ""          },
 	{     "",                   "",                                               "\eOB",                           0,    cursor_move_down,             ""          },
+	{     "",                   "",                                               "\e[1;129B",                      0,    cursor_move_down,             ""          },
 	{     "",                   "",                                               "\eOA",                           0,    cursor_move_up,               ""          },
 	{     "",                   "",                                               "\eOA",                           0,    cursor_move_up,               ""          },
+	{     "",                   "",                                               "\e[1;129A",                      0,    cursor_move_up,               ""          },
 	{     "",                   "",                                               "\e[1;5D",                        0,    cursor_move_left_word,        ""          },
 	{     "",                   "",                                               "\e[1;5D",                        0,    cursor_move_left_word,        ""          },
 	{     "",                   "",                                               "\e[1;5C",                        0,    cursor_move_right_word,       ""          },
 	{     "",                   "",                                               "\e[1;5C",                        0,    cursor_move_right_word,       ""          },
 	{     "",                   "",                                               "\e[1;5B",                        0,    cursor_move_page_down,        ""          },
 	{     "",                   "",                                               "\e[1;5B",                        0,    cursor_move_page_down,        ""          },
@@ -1044,6 +1050,7 @@ struct event_type event_table[] =
 	{    "READ FILE",                              0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "the read command finished"  },
 	{    "READ FILE",                              0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "the read command finished"  },
 	{    "RECEIVED ERROR",                         0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "an error is received"       },
 	{    "RECEIVED ERROR",                         0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "an error is received"       },
 	{    "RECEIVED INPUT",                         0, EVENT_FLAG_INPUT,    "INPUT",     "keyboard input is received" },
 	{    "RECEIVED INPUT",                         0, EVENT_FLAG_INPUT,    "INPUT",     "keyboard input is received" },
+	{    "RECEIVED INPUT CHARACTER",               0, EVENT_FLAG_INPUT,    "INPUT",     "keyboard input character"   },
 	{    "RECEIVED KEYPRESS",                      0, EVENT_FLAG_INPUT,    "INPUT",     "a keypress is received"     },
 	{    "RECEIVED KEYPRESS",                      0, EVENT_FLAG_INPUT,    "INPUT",     "a keypress is received"     },
 	{    "RECEIVED LINE",                          0, EVENT_FLAG_OUTPUT,   "OUTPUT",    "a new line is received"     },
 	{    "RECEIVED LINE",                          0, EVENT_FLAG_OUTPUT,   "OUTPUT",    "a new line is received"     },
 	{    "RECEIVED OUTPUT",                        0, EVENT_FLAG_OUTPUT,   "OUTPUT",    "bulk output is received"    },
 	{    "RECEIVED OUTPUT",                        0, EVENT_FLAG_OUTPUT,   "OUTPUT",    "bulk output is received"    },
@@ -1157,15 +1164,6 @@ struct line_type line_table[] =
 	{    "",                  NULL,                ""                                               }
 	{    "",                  NULL,                ""                                               }
 };
 };
 
 
-struct log_type log_table[] =
-{
-	{    "APPEND",            log_append,          "Start logging, appending to given file."        },
-	{    "INFO",              log_info,            "Some logging related info."                     },
-	{    "OFF",               log_off,             "Stop logging."                                  },
-	{    "OVERWRITE",         log_overwrite,       "Start logging, overwriting the given file."     },
-	{    "",                  NULL,                ""                                               }
-};
-
 struct history_type history_table[] =
 struct history_type history_table[] =
 {
 {
 //	{    "CHARACTER",         history_character,   "Set the character used for repeating commands." },
 //	{    "CHARACTER",         history_character,   "Set the character used for repeating commands." },

+ 2 - 2
src/telopt_client.c

@@ -216,9 +216,9 @@ int client_translate_telopts(struct session *ses, unsigned char *src, int cplen)
 		cpsrc = src;
 		cpsrc = src;
 	}
 	}
 
 
-	if (HAS_BIT(ses->logmode, LOG_FLAG_LOW) && ses->logfile)
+	if (HAS_BIT(ses->log->mode, LOG_FLAG_LOW) && ses->log->file)
 	{
 	{
-		fwrite(cpsrc, 1, cplen, ses->logfile);
+		fwrite(cpsrc, 1, cplen, ses->log->file);
 	}
 	}
 
 
  	if (ses->read_len + cplen >= ses->read_max)
  	if (ses->read_len + cplen >= ses->read_max)

+ 75 - 64
src/tintin.h

@@ -89,6 +89,9 @@
 #define gnutls_session_t int
 #define gnutls_session_t int
 #endif
 #endif
 
 
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
 
 
 #ifdef HAVE_SYS_TYPES_H
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #include <sys/types.h>
@@ -207,7 +210,7 @@
 #define STRING_SIZE        2 * BUFFER_SIZE
 #define STRING_SIZE        2 * BUFFER_SIZE
 
 
 #define CLIENT_NAME              "TinTin++"
 #define CLIENT_NAME              "TinTin++"
-#define CLIENT_VERSION           "2.02.11 "
+#define CLIENT_VERSION           "2.02.12 "
 
 
 
 
 #define XT_E                            0x27
 #define XT_E                            0x27
@@ -549,45 +552,47 @@ enum operators
 
 
 #define SUB_ARG                       BV01
 #define SUB_ARG                       BV01
 #define SUB_SEC                       BV02
 #define SUB_SEC                       BV02
-#define SUB_CMD                       BV03
-#define SUB_VAR                       BV04
-#define SUB_FUN                       BV05
-#define SUB_COL                       BV06
-#define SUB_ESC                       BV07
-#define SUB_EOL                       BV08 // telnet
-#define SUB_LNF                       BV09
-#define SUB_SIL                       BV10 // silent
-#define SUB_LIT                       BV11 // no soft escaping
-
+#define SUB_BRA                       BV03
+#define SUB_CMD                       BV04
+#define SUB_VAR                       BV05
+#define SUB_FUN                       BV06
+#define SUB_COL                       BV07
+#define SUB_ESC                       BV08
+#define SUB_EOL                       BV09 // telnet
+#define SUB_LNF                       BV10
+#define SUB_SIL                       BV11 // silent
+#define SUB_LIT                       BV12 // no soft escaping
 
 
 /*
 /*
 #define SUB_ARG                       BV01
 #define SUB_ARG                       BV01
 #define SUB_SEC                       BV02
 #define SUB_SEC                       BV02
+#define SUB_BRA                       BV03
 */
 */
-#define EVENT_FLAG_CATCH              BV03
-#define EVENT_FLAG_CLASS              BV04
-#define EVENT_FLAG_GAG                BV05
-#define EVENT_FLAG_INPUT              BV06
-#define EVENT_FLAG_MAP                BV07
-#define EVENT_FLAG_MOUSE              BV08
-#define EVENT_FLAG_OUTPUT             BV09
-#define EVENT_FLAG_PORT               BV10
-#define EVENT_FLAG_SCAN               BV11
-#define EVENT_FLAG_SCREEN             BV12
-#define EVENT_FLAG_SESSION            BV13
-#define EVENT_FLAG_SYSTEM             BV14
-#define EVENT_FLAG_TELNET             BV15
-#define EVENT_FLAG_TIME               BV16
-#define EVENT_FLAG_UPDATE             BV17
-#define EVENT_FLAG_VARIABLE           BV18
-#define EVENT_FLAG_VT100              BV19
-
+#define EVENT_FLAG_CATCH              BV04
+#define EVENT_FLAG_CLASS              BV05
+#define EVENT_FLAG_GAG                BV06
+#define EVENT_FLAG_INPUT              BV07
+#define EVENT_FLAG_MAP                BV08
+#define EVENT_FLAG_MOUSE              BV09
+#define EVENT_FLAG_OUTPUT             BV10
+#define EVENT_FLAG_PORT               BV11
+#define EVENT_FLAG_SCAN               BV12
+#define EVENT_FLAG_SCREEN             BV13
+#define EVENT_FLAG_SESSION            BV14
+#define EVENT_FLAG_SYSTEM             BV15
+#define EVENT_FLAG_TELNET             BV16
+#define EVENT_FLAG_TIME               BV17
+#define EVENT_FLAG_UPDATE             BV18
+#define EVENT_FLAG_VARIABLE           BV19
+#define EVENT_FLAG_VT100              BV20
 
 
 #define TAB_FLAG_FORWARD              BV01
 #define TAB_FLAG_FORWARD              BV01
 #define TAB_FLAG_BACKWARD             BV02
 #define TAB_FLAG_BACKWARD             BV02
 #define TAB_FLAG_COMPLETE             BV03
 #define TAB_FLAG_COMPLETE             BV03
-#define TAB_FLAG_LIST                 BV04
-#define TAB_FLAG_SCROLLBACK           BV05
+#define TAB_FLAG_CASELESS             BV04
+#define TAB_FLAG_DICTIONARY           BV05
+#define TAB_FLAG_LIST                 BV06
+#define TAB_FLAG_SCROLLBACK           BV07
 
 
 #define REGEX_FLAG_NONE                  0
 #define REGEX_FLAG_NONE                  0
 #define REGEX_FLAG_FIX                BV01
 #define REGEX_FLAG_FIX                BV01
@@ -596,7 +601,7 @@ enum operators
 
 
 
 
 
 
-#define TINTIN_FLAG_GETNUMBER         BV01
+#define TINTIN_FLAG_GETNUMBER         BV01 // UNUSED
 #define TINTIN_FLAG_SESSIONUPDATE     BV02
 #define TINTIN_FLAG_SESSIONUPDATE     BV02
 #define TINTIN_FLAG_PROCESSINPUT      BV03
 #define TINTIN_FLAG_PROCESSINPUT      BV03
 #define TINTIN_FLAG_INHERITANCE       BV04
 #define TINTIN_FLAG_INHERITANCE       BV04
@@ -657,6 +662,9 @@ enum operators
 #define TELOPT_FLAG_TTYPE             BV08
 #define TELOPT_FLAG_TTYPE             BV08
 #define TELOPT_FLAG_MTTS              BV09
 #define TELOPT_FLAG_MTTS              BV09
 #define TELOPT_FLAG_UPDATENAWS        BV10
 #define TELOPT_FLAG_UPDATENAWS        BV10
+#define TELOPT_FLAG_CR                BV11
+#define TELOPT_FLAG_LF                BV12
+#define TELOPT_FLAG_NUL               BV13
 
 
 #define LIST_FLAG_IGNORE              BV01
 #define LIST_FLAG_IGNORE              BV01
 #define LIST_FLAG_PRIORITY            BV02
 #define LIST_FLAG_PRIORITY            BV02
@@ -761,7 +769,8 @@ enum operators
 #define MAP_SEARCH_TERRAIN             5
 #define MAP_SEARCH_TERRAIN             5
 #define MAP_SEARCH_FLAG                6
 #define MAP_SEARCH_FLAG                6
 #define MAP_SEARCH_ID                  7
 #define MAP_SEARCH_ID                  7
-#define MAP_SEARCH_MAX                 8
+#define MAP_SEARCH_DISTANCE            8
+#define MAP_SEARCH_MAX                 9
 
 
 #define MAP_EXIT_N                     1
 #define MAP_EXIT_N                     1
 #define MAP_EXIT_E                     2
 #define MAP_EXIT_E                     2
@@ -1084,7 +1093,6 @@ struct tintin_data
 {
 {
 	struct session        * ses;
 	struct session        * ses;
 	struct session        * update;
 	struct session        * update;
-	struct session        * all;
 	struct session        * dispose_next;
 	struct session        * dispose_next;
 	struct session        * dispose_prev;
 	struct session        * dispose_prev;
 	struct listroot       * dispose_list;
 	struct listroot       * dispose_list;
@@ -1148,20 +1156,12 @@ struct session
 	z_stream              * mccp3;
 	z_stream              * mccp3;
 	gnutls_session_t        ssl;
 	gnutls_session_t        ssl;
 	struct termios          cur_terminal;
 	struct termios          cur_terminal;
+	struct log_data       * log;
 	struct scroll_data    * scroll;
 	struct scroll_data    * scroll;
 	struct split_data     * split;
 	struct split_data     * split;
 	struct input_data     * input;
 	struct input_data     * input;
 	char                  * name;
 	char                  * name;
 	char                  * group;
 	char                  * group;
-	FILE                  * logfile;
-	char                  * logname;
-	int                     logmode;
-	FILE                  * lognext_file;
-	char                  * lognext_name;
-	time_t                  lognext_time;
-	FILE                  * logline_file;
-	char                  * logline_name;
-	time_t                  logline_time;
 	char                  * line_capturefile;
 	char                  * line_capturefile;
 	int                     line_captureindex;
 	int                     line_captureindex;
 	int                     gagline;
 	int                     gagline;
@@ -1278,6 +1278,22 @@ struct level_data
 	unsigned int            verbose;
 	unsigned int            verbose;
 };
 };
 
 
+struct log_data
+{
+	FILE                  * file;
+	char                  * name;
+	int                     mode;
+	FILE                  * next_file;
+	char                  * next_name;
+	time_t                  next_time;
+	FILE                  * line_file;
+	char                  * line_name;
+	time_t                  line_time;
+	char                    stamp_text[100];
+	char                  * stamp_strf;
+	time_t                  stamp_time;
+};
+
 struct split_data
 struct split_data
 {
 {
 	int                     sav_top_row;
 	int                     sav_top_row;
@@ -1488,7 +1504,9 @@ struct search_data
 	pcre                  * note;
 	pcre                  * note;
 	pcre                  * terrain;
 	pcre                  * terrain;
 	long long               flag;
 	long long               flag;
+	long long               galf;
 	char                  * id;
 	char                  * id;
+	float                   distance;
 };
 };
 
 
 struct msdp_data
 struct msdp_data
@@ -1601,7 +1619,6 @@ struct window_data
 #define DO_EDIT(edit)          struct session *edit (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_EDIT(edit)          struct session *edit (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_HISTORY(history)            void history (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_HISTORY(history)            void history (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_LINE(line)          struct session *line (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3)
 #define DO_LINE(line)          struct session *line (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3)
-#define DO_LOG(log)                        void log (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_MAP(map)                        void map (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_MAP(map)                        void map (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_PATH(path)                     void path (struct session *ses, char *arg)
 #define DO_PATH(path)                     void path (struct session *ses, char *arg)
 #define DO_PORT(port)          struct session *port (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_PORT(port)          struct session *port (struct session *ses, char *arg, char *arg1, char *arg2)
@@ -1621,7 +1638,6 @@ typedef void            CURSOR  (struct session *ses, char *arg);
 typedef void            DAEMON  (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef void            DAEMON  (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef struct session *EDIT    (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef struct session *EDIT    (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef void            HISTORY (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef void            HISTORY (struct session *ses, char *arg, char *arg1, char *arg2);
-typedef void            LOG     (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef struct session *LINE    (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3);
 typedef struct session *LINE    (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3);
 typedef void            MAP     (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef void            MAP     (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef void            MSDP    (struct session *ses, struct port_data *buddy, int index);
 typedef void            MSDP    (struct session *ses, struct port_data *buddy, int index);
@@ -1738,13 +1754,6 @@ struct line_type
 	char                  * desc;
 	char                  * desc;
 };
 };
 
 
-struct log_type
-{
-	char                  * name;
-	LOG                   * fun;
-	char                  * desc;
-};
-
 struct map_type
 struct map_type
 {
 {
 	char                  * name;
 	char                  * name;
@@ -2027,8 +2036,6 @@ extern DO_CURSOR(cursor_set);
 extern DO_CURSOR(cursor_soft_enter);
 extern DO_CURSOR(cursor_soft_enter);
 extern DO_CURSOR(cursor_suspend);
 extern DO_CURSOR(cursor_suspend);
 extern DO_CURSOR(cursor_tab);
 extern DO_CURSOR(cursor_tab);
-extern DO_CURSOR(cursor_tab_backward);
-extern DO_CURSOR(cursor_tab_forward);
 
 
 #endif
 #endif
 
 
@@ -2238,6 +2245,7 @@ extern void dump_stack(void);
 extern DO_COMMAND(do_dictionary);
 extern DO_COMMAND(do_dictionary);
 
 
 extern int spellcheck_count(struct session *ses, char *in);
 extern int spellcheck_count(struct session *ses, char *in);
+extern int cursor_dictionary_tab_add(int stop_after_first);
 
 
 #endif
 #endif
 
 
@@ -2363,13 +2371,10 @@ extern DO_LINE(line_verbose);
 #ifndef __LOG_H__
 #ifndef __LOG_H__
 #define __LOG_H__
 #define __LOG_H__
 
 
-DO_LOG(log_append);
-DO_LOG(log_info);
-DO_LOG(log_overwrite);
-DO_LOG(log_off);
-DO_LOG(log_remove);
+extern void logheader(struct session *ses, FILE *file, int newline);
+extern void init_log(struct session *ses);
+extern void free_log(struct session *ses);
 
 
-extern void loginit(struct session *ses, FILE *file, int newline);
 extern void logit(struct session *ses, char *txt, FILE *file, int newline);
 extern void logit(struct session *ses, char *txt, FILE *file, int newline);
 extern void write_html_header(struct session *ses, FILE *fp);
 extern void write_html_header(struct session *ses, FILE *fp);
 extern void vt102_to_html(struct session *ses, char *txt, char *out);
 extern void vt102_to_html(struct session *ses, char *txt, char *out);
@@ -2570,7 +2575,7 @@ int exit_to_dir(struct session *ses, char *name);
 unsigned char pdir(struct listnode *node);
 unsigned char pdir(struct listnode *node);
 char *dir_to_exit(struct session *ses, int dir);
 char *dir_to_exit(struct session *ses, int dir);
 
 
-extern void check_append_path(struct session *ses, char *forward, char *backward, float delay, int follow);
+extern void check_append_path(struct session *ses, char *forward, char *backward, float delay, int force, int follow);
 
 
 extern DO_PATH(path_create);
 extern DO_PATH(path_create);
 extern DO_PATH(path_describe);
 extern DO_PATH(path_describe);
@@ -2722,7 +2727,7 @@ extern void telnet_printf(struct session *ses, int length, char *format, ...);
 extern void tintin_printf2(struct session *ses, char *format, ...);
 extern void tintin_printf2(struct session *ses, char *format, ...);
 extern void tintin_printf(struct session *ses, char *format, ...);
 extern void tintin_printf(struct session *ses, char *format, ...);
 
 
-extern void tintin_puts3(struct session *ses, char *string);
+extern void tintin_puts3(struct session *ses, char *string, int prompt);
 extern void tintin_puts2(struct session *ses, char *string);
 extern void tintin_puts2(struct session *ses, char *string);
 extern void tintin_puts(struct session *ses, char *string);
 extern void tintin_puts(struct session *ses, char *string);
 
 
@@ -2766,6 +2771,9 @@ extern gnutls_session_t ssl_negotiate(struct session *ses);
 extern int get_raw_len_str_range_str_width(struct session *ses, char *str, int start, int end, int *raw_width);
 extern int get_raw_len_str_range_str_width(struct session *ses, char *str, int start, int end, int *raw_width);
 extern int get_raw_off_str_range_raw_width(struct session *ses, char *str, int start, int end, int *raw_width);
 extern int get_raw_off_str_range_raw_width(struct session *ses, char *str, int start, int end, int *raw_width);
 
 
+extern int raw_len_str(struct session *ses, char *str, int start, int end);
+extern int str_len_raw(struct session *ses, char *str, int start, int end);
+
 extern char *str_ins_str(struct session *ses, char **str, char *ins, int str_start, int str_end);
 extern char *str_ins_str(struct session *ses, char **str, char *ins, int str_start, int str_end);
 
 
 extern char *calign(struct session *ses, char *in, char *out, int width);
 extern char *calign(struct session *ses, char *in, char *out, int width);
@@ -2825,7 +2833,6 @@ extern struct event_type event_table[];
 extern struct history_type history_table[];
 extern struct history_type history_table[];
 extern struct line_type line_table[];
 extern struct line_type line_table[];
 extern struct list_type list_table[LIST_MAX];
 extern struct list_type list_table[LIST_MAX];
-extern struct log_type log_table[];
 extern struct map_type map_table[];
 extern struct map_type map_table[];
 extern struct path_type path_table[];
 extern struct path_type path_table[];
 extern struct port_type port_table[];
 extern struct port_type port_table[];
@@ -2916,6 +2923,7 @@ 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, char *str);
+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);
 #endif
 #endif
@@ -2980,12 +2988,15 @@ extern int is_suffix(char *str1, char *str2);
 #ifndef __UTF8_H__
 #ifndef __UTF8_H__
 #define __UTF8_H__
 #define __UTF8_H__
 
 
+extern void big5toutf8_info(struct session *ses);
+extern void utf8tobig5_info(struct session *ses);
+
 extern int get_ascii_width(char *str, int *width);
 extern int get_ascii_width(char *str, int *width);
 
 
 extern int is_utf8_head(char *str);
 extern int is_utf8_head(char *str);
 extern int is_utf8_tail(char *str);
 extern int is_utf8_tail(char *str);
 extern int get_utf8_size(char *str);
 extern int get_utf8_size(char *str);
-extern int get_utf8_width(char *str, int *width);
+extern int get_utf8_width(char *str, int *width, int *index);
 extern int get_utf8_index(char *str, int *index);
 extern int get_utf8_index(char *str, int *index);
 extern int unicode_to_utf8(int index, char *out);
 extern int unicode_to_utf8(int index, char *out);
 extern int utf8_strlen(char *str, int *width);
 extern int utf8_strlen(char *str, int *width);

+ 11 - 7
src/tokenize.c

@@ -1219,12 +1219,6 @@ char *view_script(struct session *ses, struct scriptroot *root)
 		token = token->next;
 		token = token->next;
 	}
 	}
 
 
-	while (root->next)
-	{
-		deltoken(root, root->next);
-	}
-
-	free(root);
 
 
 	return buf;
 	return buf;
 }
 }
@@ -1278,6 +1272,7 @@ char *script_writer(struct session *ses, char *str)
 char *script_viewer(struct session *ses, char *str)
 char *script_viewer(struct session *ses, char *str)
 {
 {
 	struct scriptroot *root;
 	struct scriptroot *root;
+	char *pts;
 
 
 	root = (struct scriptroot *) calloc(1, sizeof(struct scriptroot));
 	root = (struct scriptroot *) calloc(1, sizeof(struct scriptroot));
 
 
@@ -1285,5 +1280,14 @@ char *script_viewer(struct session *ses, char *str)
 
 
 	tokenize_script(root, 1, str);
 	tokenize_script(root, 1, str);
 
 
-	return view_script(ses, root);
+	pts = view_script(ses, root);
+
+	while (root->next)
+	{
+		deltoken(root, root->next);
+	}
+
+	free(root);
+
+	return pts;
 }
 }

ファイルの差分が大きいため隠しています
+ 15 - 8
src/utf8.c


+ 39 - 17
src/variable.c

@@ -655,27 +655,49 @@ void hexstring(char *str)
 
 
 void reversestring(char *str)
 void reversestring(char *str)
 {
 {
-	char t;
-	int a = 0, z = strlen(str) - 1;
+	char *pts, *ptz, *dup = str_mim(str);
+	int skip;
 
 
-	while (z > a)
-	{
-		t = str[z];
-		str[z--] = str[a];
-		str[a++] = t;
-	}
+	pts = str;
+	ptz = dup + strlen(str);
 
 
-	z = strlen(str) - 1;
+	*ptz-- = 0;
 
 
-	for (a = 1 ; a < z ; a++)
+	while (*pts)
 	{
 	{
-		if (str[a] == '\\' && str[a + 1] != '\\')
+		switch (*pts)
+		{
+			case '\\':
+				skip = pts[1] ? 2 : 0;
+				break;
+
+			case '\e':
+				skip = skip_vt102_codes(pts);
+				break;
+
+			case '<':
+				skip = is_color_code(pts);
+				break;
+
+			default:
+				skip = 0;
+				break;
+		}
+
+		if (skip)
+		{
+			ptz -= skip;
+			memcpy(ptz + 1, pts, skip);
+			pts += skip;
+		}
+		else
 		{
 		{
-			str[a] = str[a - 1];
-			str[a - 1] = '\\';
+			*ptz-- = *pts++;
 		}
 		}
 	}
 	}
+	strcpy(str, dup);
 
 
+	str_free(dup);
 }
 }
 
 
 void mathstring(struct session *ses, char *str)
 void mathstring(struct session *ses, char *str)
@@ -935,7 +957,7 @@ void wrapstring(struct session *ses, char *str, char *wrap)
 		{
 		{
 			*pte++ = 0;
 			*pte++ = 0;
 
 
-			substitute(ses, pts, arg1, SUB_SEC);
+			substitute(ses, pts, arg1, SUB_BRA);
 
 
 			cat_sprintf(str, "{%d}{%s}", ++cnt, arg1);
 			cat_sprintf(str, "{%d}{%s}", ++cnt, arg1);
 
 
@@ -946,7 +968,7 @@ void wrapstring(struct session *ses, char *str, char *wrap)
 			pte++;
 			pte++;
 		}
 		}
 	}
 	}
-	substitute(ses, pts, arg1, SUB_SEC);
+	substitute(ses, pts, arg1, SUB_BRA);
 
 
 	cat_sprintf(str, "{%d}{%s}", ++cnt, arg1);
 	cat_sprintf(str, "{%d}{%s}", ++cnt, arg1);
 
 
@@ -1039,7 +1061,7 @@ int string_str_raw_len(struct session *ses, char *str, int start, int end)
 		}
 		}
 		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);
+			tmp_cnt = get_utf8_width(&str[raw_cnt], &width, NULL);
 
 
 			if (str_cnt >= start)
 			if (str_cnt >= start)
 			{
 			{
@@ -1115,7 +1137,7 @@ int string_raw_str_len(struct session *ses, char *str, int raw_start, int raw_en
 		}
 		}
 		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]))
 		{
 		{
-			raw_cnt += get_utf8_width(&str[raw_cnt], &width);
+			raw_cnt += get_utf8_width(&str[raw_cnt], &width, NULL);
 
 
 			ret_cnt += width;
 			ret_cnt += width;
 		}
 		}

+ 2 - 2
src/vt102.c

@@ -409,7 +409,7 @@ int get_vt102_width(struct session *ses, char *str, int *str_len)
 
 
 		if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8))
 		if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8))
 		{
 		{
-			return get_utf8_width(str, str_len);
+			return get_utf8_width(str, str_len, NULL);
 		}
 		}
 
 
 		return get_ascii_width(str, str_len);
 		return get_ascii_width(str, str_len);
@@ -1015,7 +1015,7 @@ int strip_vt102_strlen(struct session *ses, char *str)
 */
 */
 			if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(pti))
 			if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(pti))
 			{
 			{
-				size = get_utf8_width(pti, &width);
+				size = get_utf8_width(pti, &width, NULL);
 			}
 			}
 			else
 			else
 			{
 			{

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません