Scandum 4 ani în urmă
părinte
comite
e8686858ef
35 a modificat fișierele cu 1503 adăugiri și 1154 ștergeri
  1. 12 1
      NEWS
  2. 13 104
      TODO
  3. 109 88
      docs/help.html
  4. 32 20
      docs/syntax.txt
  5. 43 1
      mods/igr.mods
  6. 7 1
      src/buffer.c
  7. 9 2
      src/cursor.c
  8. 263 199
      src/data.c
  9. 10 7
      src/dict.c
  10. 22 5
      src/draw.c
  11. 7 0
      src/edit.c
  12. 29 26
      src/gui.h
  13. 114 96
      src/help.c
  14. 5 5
      src/history.c
  15. 33 5
      src/main.c
  16. 44 17
      src/mapper.c
  17. 377 347
      src/math.c
  18. 1 12
      src/misc.c
  19. 16 4
      src/nest.c
  20. 1 1
      src/port.c
  21. 3 3
      src/regex.c
  22. 18 7
      src/scan.c
  23. 21 1
      src/screen.c
  24. 50 25
      src/session.c
  25. 3 2
      src/split.c
  26. 64 1
      src/string.c
  27. 42 18
      src/substitute.c
  28. 4 2
      src/tables.c
  29. 2 0
      src/text.c
  30. 18 18
      src/tintin.h
  31. 2 0
      src/tokenize.c
  32. 2 2
      src/trigger.c
  33. 29 0
      src/update.c
  34. 83 129
      src/utils.c
  35. 15 5
      src/variable.c

+ 12 - 1
NEWS

@@ -1,6 +1,17 @@
 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.11
+----------------
+
+01) %w now translates to {[a-zA-Z0-9_]*} instead of {[a-zA-Z]*} so it matches
+    the behavior of \w. Same for %W.
+
+02) The : time operator in #math should no longer be used since that is
+    going to be changed to c style ? : ternary operator support.
+
+03) #math and #if no longer recognize .1 as a number, you need to use 0.1.
+
 TinTin++ 2.02.04
 TinTin++ 2.02.04
 ----------------
 ----------------
 
 
@@ -32,7 +43,7 @@ TinTin++ 2.02.00
 03) $variable() *variable() and &variable() are reserved until further notice,
 03) $variable() *variable() and &variable() are reserved until further notice,
     use ${variable}( for proper behavior.
     use ${variable}( for proper behavior.
 
 
-04) %+ should no longer be used in regular expressions.
+04) %+ now has different behavior when followed by a number.
 
 
     You can replace '%+' with '%+1..a', see #help regex for more information.
     You can replace '%+' with '%+1..a', see #help regex for more information.
 
 

+ 13 - 104
TODO

@@ -1,83 +1,27 @@
-  - double check packet patch code, gagging patched line? Echo command?
-
   - look into large variable handling, foreach, once again
   - look into large variable handling, foreach, once again
 
 
-
-  - output from the other session remains in the input line of the new session sometimes.
-
-  - dev/test/mouse/windowmap.tin has issues with ; in chat window
-    caused by %w in format, add SUB_BRA to just substitute braces.
-
-  - #echo {%g} {10684.3609}
+  - tab window, add tab ordering and garbage collection
 
 
 ----------------
 ----------------
+  - ãã is messing up
 
 
-  - backspace rewrites the input line, which can confuse screen readers.
-
-  - precision is poorly handled in #math (sprintf(temp, "%.12Lf", value);) needs to be improved.
+  - Add RECEIVED INPUT CHARACTER event / filter mouse input sequences.
 
 
-  - Add #event {SESSION CONNECTED} {5.1} option.
+  - handle signals in the mainloop.
 
 
-  - allow using #snoop to print to the foreground in provided square?
+  - add ctrl-r support for scrollback
 
 
-  - #split 0 1;#screen inputregion -2 1 -2 -1;#showme bug -1
-
-  - look into using $HOME/.config/tintin
-  - look into checking XDG: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
-
-  - Display directory on failed #read.
+  - Add #event {SESSION CONNECTED} {5.1} option.
 
 
   - Add the option to use + ? . and * as variable exit fields. 
   - Add the option to use + ? . and * as variable exit fields. 
 
 
   - TT++ HANDBOOK for meticulous organized details.
   - TT++ HANDBOOK for meticulous organized details.
 
 
-  - improve #draw bar.▪▪ ◼◼ ■■ ◆◆ ▬▬ ●● ⣿⣿⣿⣷
-    dual bar using reverse color and ██ ▀▀ ▄▄
-    128 bit flags
-    text inside bar.    
-
-  - store creation epoch in arg4 for #tick, add example script to display.
-
-  - get rid of SORT_DELAY due to one shot code.
-
-  - add #path load option to #path create
-
-  - double check script crashes on screen resize
-
-  - Add catch events for SIGUSR1 and SIGUSR2
-  - See about turning window close into a program termination event.
-
-  - check out hibbmap.dat in dev/test, mudlet to tt++ conversion
-
-  - add #history filter option to filter out 1 letter commands.
-
-  - no longer works?
-
-          #event {SESSION ACTIVATED} {
-                #BUFFER end;
-                };
-
-  - Possible crash with launching 2 sessions reading a large variable.
-
-  - https://tintin.sourceforge.io/forum/viewtopic.php?f=3&t=2818 (likely a
-    telnet compatibility issue)
+  - vertical bar drawing
 
 
+  - error: cursor_check_line_modified1: 
   - https://tintin.sourceforge.io/forum/viewtopic.php?f=10&t=2811 (possible
   - https://tintin.sourceforge.io/forum/viewtopic.php?f=10&t=2811 (possible
-    issue with iniating input buffer for a new session, possibly prompt
-    related somehow)
-
-  - possible issue with sessions randomly getting activated.
-
-  - possible wordwrapping on raw string length instead of stripped length
-    in some edge case.
-
-  - Look into WSL sound handling
-
-  - CP949.TXT full table support
-
-  - Look into escaped color code handling in zmp, possibly msdp
-
-  - See about making @$var{} work. Maybe allow @{$var}{}
+    issue with initiating input buffer for a new session)
 
 
   - finish BUFFER_SIZE replacement.
   - finish BUFFER_SIZE replacement.
 
 
@@ -85,34 +29,16 @@
 
 
   - update msdp scripts with #line msdp feature
   - update msdp scripts with #line msdp feature
 
 
-  - refresh input on session switch
-
-  - swap arg1, arg2, arg for do_port
-
-  - https://tintin.sourceforge.io/forum/viewtopic.php?f=5&t=2776
-    Need special casing for non capturing {?!} regex handling.
-
   - #cursor get word option, maybe get the yank buffer as well.
   - #cursor get word option, maybe get the yank buffer as well.
 
 
-  - Look into config option to change the working directory
-
   - Add a way to set env variables either 1) for the current process, and/or 2) as a parameter to #system (i.e. after fork in the child process).
   - Add a way to set env variables either 1) for the current process, and/or 2) as a parameter to #system (i.e. after fork in the child process).
 
 
-  - Add #info input, mainly to save the cursor position
-
 * STUFF THAT IS PROBABLY GONNA GET DONE
 * STUFF THAT IS PROBABLY GONNA GET DONE
 
 
-  - #path get position saves as 1 if no path is loaded. 
-
   - Finish port proxy support: resizing, input, security
   - Finish port proxy support: resizing, input, security
 
 
   - look into transparent drawing
   - look into transparent drawing
 
 
-  - if error pcre.h, need export C_INCLUDE_PATH= where it locate
-
-  - The #else command could follow a #foreach so as to create "for-else" loops
-    in case a loop is not broken.
-
   - Add #line gag 2 +2 -2 support.
   - Add #line gag 2 +2 -2 support.
 
 
   - Work on VT2020 protocol (mouse click)
   - Work on VT2020 protocol (mouse click)
@@ -120,8 +46,6 @@
   - $var[%*][%*] support.
   - $var[%*][%*] support.
   - make list sorting move nests as well
   - make list sorting move nests as well
 
 
-  - #line convert utf-8 support.
-
   - better #draw font support
   - better #draw font support
 
 
   - case insensitive tabbing (partial start with rewrite)
   - case insensitive tabbing (partial start with rewrite)
@@ -131,18 +55,6 @@
 #0  0x00005555555a5418 in tunnel_void (ses=0x555558a97b00, from=8004, room=1931506785, dir=1684955508) at mapper.c:4220
 #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
 #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}",
 #2  0x00005555555afb44 in map_list (ses=0x555558a97b00, arg=0x5555572e1b95 "{} {} {} {$roomarea} {variable} {area_mapped}",
-    arg1=0x555555d2d910 "", arg2=0x555555d23cb0 "") at mapper.c:6791
-#3  0x0000555555596562 in do_map (ses=0x555558a97b00, arg=0x5555572e1b95 "{} {} {} {$roomarea} {variable} {area_mapped}",
-    arg1=0x555555d2d910 "", arg2=0x555555d23cb0 "", arg3=0x0, arg4=0x0) at mapper.c:133
-#4  0x00005555555be82a in parse_script (root=0x555557f71960, lvl=0, token=0x55555c6ba230, shift=0x55555767ab10) at tokenize.c:812
-#5  0x00005555555bfded in script_driver (ses=0x555558a97b00, list=1,
-    str=0x555555d19ff0 "#map {get} {ROOMVNUM} {roomvnum};#map {get} {ROOMAREA} {roomarea};#map {get} {ROOMNAME} {roomname};#map {get} {ROOMDESC} {roomdesc};#format {roomname_len}\t{%L} {$roomname};#format {roomvnum_len}\t{%L} "...) at tokenize.c:1242
-#6  0x0000555555581ee1 in parse_input (ses=0x555558a97b00, input=0x55555767c099 "") at parse.c:226
-#7  0x00005555555bef73 in parse_script (root=0x555557680c80, lvl=0, token=0x555557f719d0, shift=0x555557f719d0) at tokenize.c:1011
-#8  0x00005555555bfded in script_driver (ses=0x555558a97b00, list=6, str=0x555558d95d10 "mapupdate") at tokenize.c:1242
-#9  0x00005555555865af in delay_update () at update.c:938
-#10 0x000055555558434d in mainloop () at update.c:159
-#11 0x000055555557df19 in main (argc=2, argv=0x7fffffffe4c8) at main.c:416
 
 
   - #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
@@ -203,21 +115,14 @@
 
 
   - add packets patched counter
   - add packets patched counter
 
 
-  - Fix arrow key up history recall overwriting the prompt (partial redesign)
-    Auto prompt fixing on overwrite.
-
   - reportable_sounds
   - reportable_sounds
 
 
-  - https://tintin.sourceforge.io/forum/viewtopic.php?f=4&t=2597 #add #screen support
-
   - TELNET documentation.
   - TELNET documentation.
 
 
   - Add JSON support to #scan
   - Add JSON support to #scan
 
 
   - see if #break 2 is possible, maybe #continue 2 as well.
   - see if #break 2 is possible, maybe #continue 2 as well.
 
 
-  - http://tintin.sourceforge.net/board/viewtopic.php?p=9625 (map undo issue) (not a big issue)
-
   - http://tintin.sourceforge.net/board/viewtopic.php?t=2339 (map area data)
   - http://tintin.sourceforge.net/board/viewtopic.php?t=2339 (map area data)
 
 
   - IPv6 for chat
   - IPv6 for chat
@@ -244,6 +149,10 @@
 
 
   - Start of line anchors aren't working in #replace.
   - Start of line anchors aren't working in #replace.
 
 
+  - add #history filter option to filter out 1 letter commands.
+
+  - Look into config option to change the working directory
+
 --------------------------------------------------------------------------------
 --------------------------------------------------------------------------------
 
 
 * ROADMAP
 * ROADMAP

+ 109 - 88
docs/help.html

@@ -721,6 +721,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          You can further prefix the option as following:
          You can further prefix the option as following:
 
 
          ASCII      will draw in ASCII mode.
          ASCII      will draw in ASCII mode.
+         BALIGN     will bottom align text.
          BLANKED    will blank the lines and corners.
          BLANKED    will blank the lines and corners.
          BOTTOM     will draw on the bottom side if possible.
          BOTTOM     will draw on the bottom side if possible.
          BOXED      will draw a box along the square.
          BOXED      will draw a box along the square.
@@ -761,7 +762,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          The following types are available.
          The following types are available.
 
 
          [HORIZONTAL] </span><span style='color:#FFF'>BAR</span><span style='color:#AAA'> {&lt;MIN&gt;;&lt;MAX&gt;;[COLOR]}
          [HORIZONTAL] </span><span style='color:#FFF'>BAR</span><span style='color:#AAA'> {&lt;MIN&gt;;&lt;MAX&gt;;[COLOR]}
-          will draw a bar.
+          will draw a bar, use two 256 color codes for a color gradient.
          [ASCII|UNICODE|HUGE] </span><span style='color:#FFF'>BOX</span><span style='color:#AAA'> {[TEXT1]} {[TEXT2]}
          [ASCII|UNICODE|HUGE] </span><span style='color:#FFF'>BOX</span><span style='color:#AAA'> {[TEXT1]} {[TEXT2]}
            will draw a box.
            will draw a box.
          [BOXED|FOREGROUND] </span><span style='color:#FFF'>BUFFER
          [BOXED|FOREGROUND] </span><span style='color:#FFF'>BUFFER
@@ -805,7 +806,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
 
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #echo {The current date is %t.} {%Y-%m-%d %H:%M:%S}
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #echo {The current date is %t.} {%Y-%m-%d %H:%M:%S}
          #echo {[%38s][%-38s]} {Hello World} {Hello World}
          #echo {[%38s][%-38s]} {Hello World} {Hello World}
-         #echo {{this is %s on the top row} {-1}} {printed}
+         #echo {{this is %s on the top row} {1}} {printed}
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#BUFFER'>buffer</a>, <a href='#FORMAT'>format</a>, <a href='#GREP'>grep</a> and <a href='#SHOWME'>showme</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#BUFFER'>buffer</a>, <a href='#FORMAT'>format</a>, <a href='#GREP'>grep</a> and <a href='#SHOWME'>showme</a>.
 <a name='EDIT'></a>
 <a name='EDIT'></a>
@@ -1013,6 +1014,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          &bsol;x7B  send the '{' character.
          &bsol;x7B  send the '{' character.
          &bsol;x7D  send the '}' character.
          &bsol;x7D  send the '}' character.
          &bsol;u    print a 16 bit unicode character, &bsol;uFFFD for example.
          &bsol;u    print a 16 bit unicode character, &bsol;uFFFD for example.
+         &bsol;u{}  print a 8-21 bit unicode character, &bsol;u{2AF21} for example.
          &bsol;U    print a 21 bit unicode character, &bsol;U02AF21 for example.
          &bsol;U    print a 21 bit unicode character, &bsol;U02AF21 for example.
          &bsol;v    send a vertical tab
          &bsol;v    send a vertical tab
 
 
@@ -1137,6 +1139,38 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          </span><span style='color:#FFF'>PORT LOG MESSAGE       </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 plain data
          </span><span style='color:#FFF'>PORT LOG MESSAGE       </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 plain data
          </span><span style='color:#FFF'>PORT RECEIVED MESSAGE  </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 plain data
          </span><span style='color:#FFF'>PORT RECEIVED MESSAGE  </span><span style='color:#AAA'>%0 name %1 ip %2 port %3 data %4 plain data
 
 
+         </span><span style='color:#5F5'>SCAN EVENTS</span><span style='color:#AAA'>
+
+         SCAN CSV HEADER        %0 all args %1 arg1 %2 arg2 .. %99 arg99
+         SCAN CSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99
+         SCAN TSV HEADER        %0 all args %1 arg1 %2 arg3 .. %99 arg99
+         SCAN TSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99
+
+         </span><span style='color:#5F5'>SCREEN EVENTS</span><span style='color:#AAA'>
+
+         </span><span style='color:#FFF'>SCREEN FOCUS
+         </span><span style='color:#AAA'>  %0 focus (0 or 1)
+
+         SCREEN LOCATION        %0 rows %1 cols  %2 height %3 width
+
+         </span><span style='color:#FFF'>SCREEN MOUSE LOCATION
+         </span><span style='color:#AAA'>  %0 row  %1 col  %2 -row  %3 -col  %4 pix row  %5 pix col
+           %6 -pix row  %7 -pix col  %8 location
+
+         SCREEN RESIZE          %0 rows %1 cols %2 height %3 width
+         SCREEN SPLIT           %0 top row %1 top col %2 bot row %3 bot col
+         SCREEN UNSPLIT         %0 top row %1 top col %2 bot row %3 bot col
+
+         </span><span style='color:#5F5'>SESSION EVENTS</span><span style='color:#AAA'>
+
+         SESSION ACTIVATED      %0 name
+         SESSION CONNECTED      %0 name %1 host %2 ip %3 port
+         SESSION CREATED        %0 name %1 host %2 ip %3 port
+         SESSION DEACTIVATED    %0 name
+         SESSION DISCONNECTED   %0 name %1 host %2 ip %3 port
+         SESSION TIMED OUT      %0 name %1 host %2 ip %3 port
+
+
          </span><span style='color:#5F5'>SYSTEM EVENTS</span><span style='color:#AAA'>
          </span><span style='color:#5F5'>SYSTEM EVENTS</span><span style='color:#AAA'>
 
 
          DAEMON ATTACHED        %0 file %1 pid
          DAEMON ATTACHED        %0 file %1 pid
@@ -1152,6 +1186,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          SYSTEM CRASH           %0 message
          SYSTEM CRASH           %0 message
          SYSTEM ERROR           %0 name %1 system msg %2 error %3 error msg
          SYSTEM ERROR           %0 name %1 system msg %2 error %3 error msg
          UNKNOWN COMMAND        %0 raw text
          UNKNOWN COMMAND        %0 raw text
+         SIGUSR                 %0 signal
 
 
          </span><span style='color:#5F5'>TELNET EVENTS
          </span><span style='color:#5F5'>TELNET EVENTS
 
 
@@ -1174,37 +1209,6 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          </span><span style='color:#AAA'>  %0 year  %1 month  %2 day of week  %3 day of month  %4 hour
          </span><span style='color:#AAA'>  %0 year  %1 month  %2 day of week  %3 day of month  %4 hour
            %5 minute  %6 second
            %5 minute  %6 second
 
 
-         </span><span style='color:#5F5'>SCAN EVENTS</span><span style='color:#AAA'>
-
-         SCAN CSV HEADER        %0 all args %1 arg1 %2 arg2 .. %99 arg99
-         SCAN CSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99
-         SCAN TSV HEADER        %0 all args %1 arg1 %2 arg3 .. %99 arg99
-         SCAN TSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99
-
-         </span><span style='color:#5F5'>SCREEN EVENTS</span><span style='color:#AAA'>
-
-         </span><span style='color:#FFF'>SCREEN FOCUS
-         </span><span style='color:#AAA'>  %0 focus (0 or 1)
-
-         SCREEN LOCATION        %0 rows %1 cols  %2 height %3 width
-
-         </span><span style='color:#FFF'>SCREEN MOUSE LOCATION
-         </span><span style='color:#AAA'>  %0 row  %1 col  %2 -row  %3 -col  %4 pix row  %5 pix col
-           %6 -pix row  %7 -pix col  %8 location
-
-         SCREEN RESIZE          %0 rows %1 cols %2 height %3 width
-         SCREEN SPLIT           %0 top row %1 top col %2 bot row %3 bot col
-         SCREEN UNSPLIT         %0 top row %1 top col %2 bot row %3 bot col
-
-         </span><span style='color:#5F5'>SESSION EVENTS</span><span style='color:#AAA'>
-
-         SESSION ACTIVATED      %0 name
-         SESSION CONNECTED      %0 name %1 host %2 ip %3 port
-         SESSION CREATED        %0 name %1 host %2 ip %3 port
-         SESSION DEACTIVATED    %0 name
-         SESSION DISCONNECTED   %0 name %1 host %2 ip %3 port
-         SESSION TIMED OUT      %0 name %1 host %2 ip %3 port
-
          </span><span style='color:#5F5'>VARIABLE EVENTS</span><span style='color:#AAA'>
          </span><span style='color:#5F5'>VARIABLE EVENTS</span><span style='color:#AAA'>
 
 
          VARIABLE UPDATE &lt;VAR&gt;  %0 name %1 new value %2 path
          VARIABLE UPDATE &lt;VAR&gt;  %0 name %1 new value %2 path
@@ -1271,7 +1275,6 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
                                          optional {{string}{width}} syntax
                                          optional {{string}{width}} syntax
          #format {test} {%x}      {hex}  print corresponding charset character
          #format {test} {%x}      {hex}  print corresponding charset character
          #format {test} {%A}     {char}  store corresponding character value
          #format {test} {%A}     {char}  store corresponding character value
-         #format {test} {%C}   {number}  store number in chronological notation
          #format {test} {%D}      {hex}  convert hex to decimal in {test}
          #format {test} {%D}      {hex}  convert hex to decimal in {test}
          #format {hash} {%H}   {string}  store a 64 bit string hash in {hash}
          #format {hash} {%H}   {string}  store a 64 bit string hash in {hash}
          #format {test} {%L}   {string}  store the string length in {test}
          #format {test} {%L}   {string}  store the string length in {test}
@@ -1340,7 +1343,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.06b                    </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'>                                                                  </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'>#
@@ -1478,23 +1481,28 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
 
 </span><span style='color:#5F5'>         IF
 </span><span style='color:#5F5'>         IF
 
 
-</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #if </span><span style='color:#FFF'>{</span><span style='color:#AAA'>conditional</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>commands if true</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>commands if false</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
+</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #if </span><span style='color:#FFF'>{</span><span style='color:#AAA'>conditional</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>commands if true</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
 
 
-         The 'if' command is one of the most powerful commands added since
-         TINTIN III. It works similar to an 'if' statement in other languages,
-         and is strictly based on the way C handles its conditional statements.
-         When an 'if' command is encountered, the conditional statement is
+         The #if command is one of the most powerful commands added since
+         TINTIN III. It works similar to an if statement in other languages,
+         and is based on the way C handles its conditional statements.
+         When an #if command is encountered, the conditional statement is
          evaluated, and if TRUE (any non-zero result) the commands are executed.
          evaluated, and if TRUE (any non-zero result) the commands are executed.
 
 
-         The 'if' statement is only evaluated if it is read, so you must nest
-         the 'if' statement inside another statement (most likely an 'action'
+         The if statement is only evaluated if it is read, so you must nest
+         the if statement inside another statement (most likely an #action
          command). The conditional is evaluated exactly the same as in the
          command). The conditional is evaluated exactly the same as in the
-         'math' command only instead of storing the result, the result is used
+         #math command, only instead of storing the result, the result is used
          to determine whether to execute the commands.
          to determine whether to execute the commands.
 
 
-</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #action {%0 gives you %1 gold coins.} {#if {%1&gt;5000} {thank %0}}
+         To handle the case where an if statement is false it can be followed
+         by the #else command.
+
+</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #action {%0 gives you %1 gold coins.} {#if {%1 &gt; 5000} {thank %0}}
          If someone gives you more than 5000 coins, thank them.
          If someone gives you more than 5000 coins, thank them.
 
 
+</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #alias {k} {#if {&quot;%0&quot; == &quot;&quot;} {kill &dollar;target};#else {kill %0}}
+
 </span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: See '#help math', for more information.
 </span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: See '#help math', for more information.
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CASE'>case</a>, <a href='#DEFAULT'>default</a>, <a href='#ELSE'>else</a>, <a href='#ELSEIF'>elseif</a>, <a href='#SWITCH'>switch</a> and <a href='#REGEXP'>regexp</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CASE'>case</a>, <a href='#DEFAULT'>default</a>, <a href='#ELSE'>else</a>, <a href='#ELSEIF'>elseif</a>, <a href='#SWITCH'>switch</a> and <a href='#REGEXP'>regexp</a>.
@@ -1515,11 +1523,9 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
 
 </span><span style='color:#5F5'>         INDEX
 </span><span style='color:#5F5'>         INDEX
 
 
-         INDEX
-</span><span style='color:#AAA'>
          On this page you'll find an introduction to using TinTin++. Additional
          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]
@@ -1787,12 +1793,16 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
 
 
          By providing the name of a list and the LIST option it shows all
          By providing the name of a list and the LIST option it shows all
          triggers/variables associated with that list. With the SAVE option
          triggers/variables associated with that list. With the SAVE option
-         This data is written to the info variable.
+         this data is written to the info variable.
 
 
          #info cpu will show information about tintin's cpu usage.
          #info cpu will show information about tintin's cpu usage.
+         #info environ will show the environment variables.
+         #info input will show information about the input line.
          #info mccp will show information about data compression.
          #info mccp will show information about data compression.
+         #info memory will show information about the memory stack.
          #info stack will show the low level debugging stack.
          #info stack will show the low level debugging stack.
-         #info session will show some session information.
+         #info session will show information on the session.
+         #info sessions will show information on all sessions.
          #info system will show some system information.
          #info system will show some system information.
          #info unicode will show information on the provided character.
          #info unicode will show information on the provided character.
 
 
@@ -2345,7 +2355,8 @@ Terminal -&gt; Window Settings -&gt; Emulation.
          </span><span style='color:#AAA'>  Sets displaying center of the map viewer, default is 0 0 0.
          </span><span style='color:#AAA'>  Sets displaying center of the map viewer, default is 0 0 0.
 
 
          </span><span style='color:#FFF'>#map color &lt;field&gt; [value]
          </span><span style='color:#FFF'>#map color &lt;field&gt; [value]
-         </span><span style='color:#AAA'>  Sets the map color for the given color field.
+         </span><span style='color:#AAA'>  Sets the map color for the given color field. Use #map color reset
+           to restore colors to default.
 
 
          </span><span style='color:#FFF'>#map create &lt;size&gt;
          </span><span style='color:#FFF'>#map create &lt;size&gt;
          </span><span style='color:#AAA'>  Creates a new map and room 1. The default size is 50000 rooms.
          </span><span style='color:#AAA'>  Creates a new map and room 1. The default size is 50000 rooms.
@@ -2754,31 +2765,33 @@ Terminal -&gt; Window Settings -&gt; Emulation.
          ------------------------------------------------
          ------------------------------------------------
          !               0            logical not
          !               0            logical not
          ~               0            bitwise not
          ~               0            bitwise not
-         *               1            integer multiply
-         **              1            integer power
-         /               1            integer divide
-         //              1            integer sqrt // 2 or cbrt // 3
-         %               1            integer modulo
-         d               1            integer random dice roll
-         +               2            integer addition
-         -               2            integer subtraction
-         &lt;&lt;              3            bitwise shift
-         &gt;&gt;              3            bitwise shift
-         ..              3            bitwise ellipsis
-         &gt;               4            logical greater than
-         &gt;=              4            logical greater than or equal
-         &lt;               4            logical less than
-         &lt;=              4            logical less than or equal
-         ==              5            logical equal (can use regex)
-         ===             5            logical equal (never regex)
-         !=              5            logical not equal (can use regex)
-         !==             5            logical not equal (never regex)
-          &amp;              6            bitwise and
-          ^              7            bitwise xor
-          |              8            bitwise or
-         &amp;&amp;              9            logical and
-         ^^             10            logical xor
-         ||             11            logical or
+         d               1            integer random dice
+         *               2            integer multiply
+         **              2            integer power
+         /               2            integer divide
+         //              2            integer sqrt // 2 or cbrt // 3
+         %               2            integer modulo
+         +               3            integer addition
+         -               3            integer subtraction
+         &lt;&lt;              4            bitwise shift
+         &gt;&gt;              4            bitwise shift
+         ..              4            bitwise ellipsis
+         &gt;               5            logical greater than
+         &gt;=              5            logical greater than or equal
+         &lt;               5            logical less than
+         &lt;=              5            logical less than or equal
+         ==              6            logical equal (can use regex)
+         ===             6            logical equal (never regex)
+         !=              6            logical not equal (can use regex)
+         !==             6            logical not equal (never regex)
+          &amp;              7            bitwise and
+          ^              8            bitwise xor
+          |              9            bitwise or
+         &amp;&amp;             10            logical and
+         ^^             11            logical xor
+         ||             12            logical or
+         ?              13            logical ternary if (unfinished code)
+         :              14            logical ternary else 
 
 
          True is any non-zero number, and False is zero.  Parentheses () have
          True is any non-zero number, and False is zero.  Parentheses () have
          highest precedence, so inside the () is always evaluated first.
          highest precedence, so inside the () is always evaluated first.
@@ -2973,7 +2986,7 @@ Related</span><span style='color:#AAA'>: <a href='#EVENT'>event</a> and <a href=
 
 
          This would make you start a reply when clicking on a tell.
          This would make you start a reply when clicking on a tell.
 
 
-Website: https://tintin.mudhalla.net/protocols/mslp
+</span><span style='color:#FFF'>Website</span><span style='color:#AAA'>: https://tintin.mudhalla.net/protocols/mslp
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#EVENT'>event</a> and <a href='#PORT'>port</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#EVENT'>event</a> and <a href='#PORT'>port</a>.
 <a name='NOP'></a>
 <a name='NOP'></a>
@@ -3321,7 +3334,7 @@ Example: #action {~&bsol;e[1;37m%1} {#var roomname %1}
          Prompt is a feature for split window mode, which will capture a line
          Prompt is a feature for split window mode, which will capture a line
          received from the server and display it on the status bar of your
          received from the server and display it on the status bar of your
          split screen terminal. You would define &lt;text&gt; and &lt;new text&gt; the
          split screen terminal. You would define &lt;text&gt; and &lt;new text&gt; the
-         same way as with a substitution.
+         same way as you would with #substitute.
 
 
          The row number is optional and useful if you use a non standard split
          The row number is optional and useful if you use a non standard split
          mode. A positive row number draws #row lines from the top while a
          mode. A positive row number draws #row lines from the top while a
@@ -3332,8 +3345,8 @@ Example: #action {~&bsol;e[1;37m%1} {#var roomname %1}
          The col number is optional and can be used to set the column index.
          The col number is optional and can be used to set the column index.
          A positive col number draws the given number of columns from the left,
          A positive col number draws the given number of columns from the left,
          while a negative col number draws from the right. If you leave the
          while a negative col number draws from the right. If you leave the
-         column argument empty tintin will clear the row before printing at
-         the start of the row.
+         col number empty tintin will clear the row before printing at the
+         start of the row.
 
 
          The #show command takes a row and col argument as well so it's also
          The #show command takes a row and col argument as well so it's also
          possible to place text on your split lines using #show.
          possible to place text on your split lines using #show.
@@ -3389,19 +3402,22 @@ Example: #action {~&bsol;e[1;37m%1} {#var roomname %1}
 
 
          Of the following the (lazy) match is available at %1-%99 + 1
          Of the following the (lazy) match is available at %1-%99 + 1
 
 
-      %a match zero to any number of characters including newlines.
-      %A match zero to any number of newlines.
       %d match zero to any number of digits.
       %d match zero to any number of digits.
       %D match zero to any number of non digits.
       %D match zero to any number of non digits.
-      %p match zero to any number of printable characters.
-      %P match zero to any number of non printable characters.
       %s match zero to any number of spaces.
       %s match zero to any number of spaces.
       %S match zero to any number of non spaces.
       %S match zero to any number of non spaces.
-      %u match zero to any number of unicode characters.
-      %U match zero to any number of non unicode characters.
       %w match zero to any number of word characters.
       %w match zero to any number of word characters.
       %W match zero to any number of non word characters.
       %W match zero to any number of non word characters.
 
 
+      Experimental (subject to change) matches are:
+
+      %a match zero to any number of characters including newlines.
+      %A match zero to any number of newlines.
+      %p match zero to any number of printable characters.
+      %P match zero to any number of non printable characters.
+      %u match zero to any number of unicode characters.
+      %U match zero to any number of non unicode characters.
+
       If you want to match 1 digit use %+1d, if you want to match between 3
       If you want to match 1 digit use %+1d, if you want to match between 3
       and 5 spaces use %+3..5s, if you want to match 0 or more word
       and 5 spaces use %+3..5s, if you want to match 0 or more word
       characters use %+0..w, etc.
       characters use %+0..w, etc.
@@ -3423,7 +3439,7 @@ Example: #action {~&bsol;e[1;37m%1} {#var roomname %1}
 
 
 </span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: Like an alias or function #regex has its own scope.
 </span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: Like an alias or function #regex has its own scope.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#REPLACE'>replace</a>
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#PCRE'>pcre</a> and <a href='#REPLACE'>replace</a>.
 <a name='REPEAT'></a>
 <a name='REPEAT'></a>
 
 
 </span><span style='color:#5F5'>         REPEAT
 </span><span style='color:#5F5'>         REPEAT
@@ -3638,7 +3654,7 @@ easiest way to accomplish that.
          treats the generated echos as commands if no variable is provided.
          treats the generated echos as commands if no variable is provided.
 
 
          This is useful for running php, perl, ruby, and python scripts. You
          This is useful for running php, perl, ruby, and python scripts. You
-         can run these scrips either from file or from within tintin if the
+         can run these scripts either from file or from within tintin if the
          scripting language allows this.
          scripting language allows this.
 
 
          If you provide a variable the output of the script is stored as a list.
          If you provide a variable the output of the script is stored as a list.
@@ -3747,7 +3763,7 @@ session one will remain the active session.
 
 
 </span><span style='color:#5F5'>         SNOOP
 </span><span style='color:#5F5'>         SNOOP
 
 
-</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #snoop </span><span style='color:#FFF'>{</span><span style='color:#AAA'>session name</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>on</span><span style='color:#FFF'>|</span><span style='color:#AAA'>off</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
+</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #snoop </span><span style='color:#FFF'>{</span><span style='color:#AAA'>session name</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>on</span><span style='color:#FFF'>|</span><span style='color:#AAA'>off</span><span style='color:#FFF'>|</span><span style='color:#AAA'>scroll</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
 
 
          If there are multiple sessions active, this command allows you to
          If there are multiple sessions active, this command allows you to
          monitor what is going on in the sessions that are not currently active.
          monitor what is going on in the sessions that are not currently active.
@@ -3756,6 +3772,11 @@ session one will remain the active session.
 
 
          You can toggle off snoop mode by executing #snoop a second time.
          You can toggle off snoop mode by executing #snoop a second time.
 
 
+         By using the scroll argument you will snoop the session's scroll
+         region which will overwrite the display of whichever session is active.
+         You can change the size and location of a session's scroll region by
+         using the #split and #screen scrollregion commands.
+
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#ALL'>all</a>, <a href='#PORT'>port</a>, <a href='#RUN'>run</a>, <a href='#SESSION'>session</a>, <a href='#SESSIONNAME'>sessionname</a>, <a href='#SSL'>ssl</a> and <a href='#ZAP'>zap</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#ALL'>all</a>, <a href='#PORT'>port</a>, <a href='#RUN'>run</a>, <a href='#SESSION'>session</a>, <a href='#SESSIONNAME'>sessionname</a>, <a href='#SSL'>ssl</a> and <a href='#ZAP'>zap</a>.
 <a name='SPEEDWALK'></a>
 <a name='SPEEDWALK'></a>
 
 

+ 32 - 20
docs/syntax.txt

@@ -4,9 +4,10 @@ CHARACTERS
 
 
 #         The hashtag is the default character for starting a command and is
 #         The hashtag is the default character for starting a command and is
           subsequently known as the command character or tintin character.
           subsequently known as the command character or tintin character.
+
           When loading a command file the command character is set to the
           When loading a command file the command character is set to the
           first character in the file. The character can also be redefined
           first character in the file. The character can also be redefined
-          using #config.
+          using #config. It's adviced not to redefine the command character.
 
 
 ;         The semi-colon is used as the command separator and can be used to
 ;         The semi-colon is used as the command separator and can be used to
           separate two commands. Multiple commands can be strung together as
           separate two commands. Multiple commands can be strung together as
@@ -18,8 +19,9 @@ CHARACTERS
           easily be escaped and must always be used in pairs.
           easily be escaped and must always be used in pairs.
 
 
 " "       Quote characters are used for strings in the #math, #if, #switch,
 " "       Quote characters are used for strings in the #math, #if, #switch,
-          and #case commands. It is however suggested to use an extra
-          set of braces { } to define strings.
+          and #case commands. Instead of " " you can use an extra set of
+          braces { } to define strings, this is suggested if you are
+          expecting input to contain " characters.
 
 
 !         The exclamation sign is used to repeat commands, see #help history.
 !         The exclamation sign is used to repeat commands, see #help history.
           The character can be redefined using #config.
           The character can be redefined using #config.
@@ -29,7 +31,6 @@ CHARACTERS
           #config.
           #config.
 
 
 
 
-
 SUBSTITUTIONS
 SUBSTITUTIONS
 -------------
 -------------
 
 
@@ -49,14 +50,20 @@ $         The dollar sign is used to retrieve the value of a variable.
           associative array. Associative arrays are also known as tables and
           associative array. Associative arrays are also known as tables and
           maps. Regex can be used within brackets to match multiple variables.
           maps. Regex can be used within brackets to match multiple variables.
 
 
-&0- &99   The ampersand sign followed by a number is used for arguments in the
-          regex command.
+          Variables are ordered alphanumerically.
+
++ -       The plus and minus sign is used to access variables by their index,
+          with the first variable having index 1, and the last variable
+          having index -1.
 
 
 %0- %99   The percent sign followed by a number is used for arguments by the
 %0- %99   The percent sign followed by a number is used for arguments by the
           following triggers:
           following triggers:
 
 
           alias, action, button, delay, event, function, substitute, and tick.
           alias, action, button, delay, event, function, substitute, and tick.
 
 
+&0- &99   The ampersand sign followed by a number is used for arguments in the
+          regex and replace commands.
+
 <000>     Three alphanumeric characters encapsulated by the less- and greater-
 <000>     Three alphanumeric characters encapsulated by the less- and greater-
           than signs are used for 4 and 8 bit color codes.
           than signs are used for 4 and 8 bit color codes.
 
 
@@ -73,8 +80,10 @@ $         The dollar sign is used to retrieve the value of a variable.
 \         The back slash is used to escape a character. All available options
 \         The back slash is used to escape a character. All available options
           are listed at #help escape. Escapes are typically escaped when text
           are listed at #help escape. Escapes are typically escaped when text
           leaves the client, by being send to a server, the shell, or being
           leaves the client, by being send to a server, the shell, or being
-          displayed on the screen.
+          displayed on the screen. Escapes try to mimic escapes in PCRE when
+          possible.
 
 
+\a        07  bell character.
 \t        08  horizontal tab character.
 \t        08  horizontal tab character.
 \n        10  line feed character.
 \n        10  line feed character.
 \v        11  vertical tab character.
 \v        11  vertical tab character.
@@ -83,42 +92,49 @@ $         The dollar sign is used to retrieve the value of a variable.
 \c            6 bit control character, \ca for ctrl-a.
 \c            6 bit control character, \ca for ctrl-a.
 \x            8 bit character using 2 hexadecimal numbers.
 \x            8 bit character using 2 hexadecimal numbers.
 \u            16 bit unicode character, \uFFFD for example.
 \u            16 bit unicode character, \uFFFD for example.
+\U            21 bit unicode character, \U02AF21 for example.
 
 
           All variables and functions can be escaped by doubling the sign,
           All variables and functions can be escaped by doubling the sign,
           like $$variable_name or @@function_name. To escape a variable
           like $$variable_name or @@function_name. To escape a variable
           twice use $$$var_name. One escape is removed each time tintin
           twice use $$$var_name. One escape is removed each time tintin
           needs to substitute a variable or function.
           needs to substitute a variable or function.
 
 
+          All trigger arguments can be escaped by double the ampersand,
+          like %%1. One escape is removed each time tintin substitutes
+          trigger arguments.
+
           All command arguments can be escaped by doubling the ampersand,
           All command arguments can be escaped by doubling the ampersand,
           like &&1. One escape is removed each time tintin substitutes
           like &&1. One escape is removed each time tintin substitutes
           command arguments.
           command arguments.
 
 
-          All trigger arguments can be escaped by double the ampersand,
-          like %%1. One escape is removed each time tintin substitutes
-          trigger arguments.
 
 
 COORDINATES
 COORDINATES
 -----------
 -----------
 
 
           When the 0,0 coordinate is in the upper left corner TinTin++ uses
           When the 0,0 coordinate is in the upper left corner TinTin++ uses
           a y,x / rows,cols notation, starting at 1,1. Subsequently -1,-1
           a y,x / rows,cols notation, starting at 1,1. Subsequently -1,-1
-          will indicate the bottom right corner.
+          will indicate the bottom right corner. This type of argument is
+          used by the #showme command.
 
 
           When the 0,0 coordinate is in the bottom left corner tintin uses
           When the 0,0 coordinate is in the bottom left corner tintin uses
-          a standard x,y notation.
+          a standard x,y notation. This type of argument is used by the
+          #map jump command.
 
 
 SQUARES
 SQUARES
 -------
 -------
 
 
           A square argument takes 4 coordinates. The first two coordinates
           A square argument takes 4 coordinates. The first two coordinates
           define the upper left corner, the last two coordinates define the
           define the upper left corner, the last two coordinates define the
-          bottom right corner.
+          bottom right corner. The upper left corner of the terminal is
+          defined as 1,1 and the bottom right corner as -1,-1. This type
+          of argument is use by the #draw, #button, #map offset, 
 
 
 PANES
 PANES
 -----
 -----
           A panes argument takes 4 size values, which are: top pane, bottom
           A panes argument takes 4 size values, which are: top pane, bottom
           pane, left pane, right pane. When a negative value is provided the
           pane, left pane, right pane. When a negative value is provided the
-          size is the maximum size, minus the value.
+          size is the maximum size, minus the value. This type of argument
+          is used by the #split command.
 
 
 MATH
 MATH
 ----
 ----
@@ -129,7 +145,7 @@ MATH
           *               1            integer multiply
           *               1            integer multiply
           **              1            integer power
           **              1            integer power
           /               1            integer divide
           /               1            integer divide
-          //              1            integer sqrt // 2 or cbrt // 3
+          //              1            integer root
           %               1            integer modulo
           %               1            integer modulo
           d               1            integer random dice roll
           d               1            integer random dice roll
           +               2            integer addition
           +               2            integer addition
@@ -151,11 +167,7 @@ MATH
           ^^             10            logical xor
           ^^             10            logical xor
           ||             11            logical or
           ||             11            logical or
 
 
-:         The colon can be used in #math to indicate a time value.
-1:30      This means 1 minute and 30 seconds and equals 90 seconds.
-2:1:30    This means 2 hours, 1 minute and 30 seconds.
-6:2:1:30  This means 6 days, 2 hours, 1 minute and 30 seconds.
-          #math time 6:2:1:30 equals 525690
+? :       The ? : symbols can be used for simple ternary operations.
 
 
 M,K,m,u   These four metric suffixes are allowed for numbers.
 M,K,m,u   These four metric suffixes are allowed for numbers.
 
 

+ 43 - 1
mods/igr.mods

@@ -1,4 +1,46 @@
-Nov 2020        2.02.06
+Mar 2021        2.02.11
+------------------------------------------------------------------------------
+draw.c          #draw BALIGN will push text to the bottom if there aren't
+                enough lines to fill the entire square.
+
+main.c          Synchronized terminal resize handling which might fix some odd
+                crashes.
+
+variable.c      Getting rid of #format %C for chronological formatting since
+                I'm abandoning chronological notation support. While it was
+                a cute feature it's more important to support the ? : ternary
+                operation. This frees up the %C argument for a more complex
+                column operation.
+
+mapper.c        Added support to use #map list 1..6 to provide a vnum range.
+
+substitute.c    Added \u{} which supports between 2 and 6 hexadecimals.
+
+data.c          Added the #info input and #info input save option.
+
+data.c          Added the #info environ and #info environ save option.
+
+main.c          Added SIGUSR event. %0 will contain either 1 or 2.
+                #event {SIGUSR} {#showme RECEIVED SIGUSR %0}
+		#info system save
+		#system {kill -USR1 $info[SYSTEM][PID]
+
+main.c          Added SIGHUB event which should trigger when the terminal is
+                closed with TinTin++ still running inside. You can use
+                #event {SIGHUB} {#end} to have tintin close normally.
+
+session.c       Added #snoop {session} scroll {on|off} to snoop a session's
+                scroll region, which will be printed on top of the active
+                session's screen.
+
+math.c          Made #math / #if about 3x faster.
+
+math.c          Updated // to support powers other than 2 and 3.
+
+regex.c         Changed %w to match any letter, number, or undescore instead
+                of just letters, to make it match \w. Same for %W.
+
+Nov 2020        2.02.10
 
 
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 
 

+ 7 - 1
src/buffer.c

@@ -160,6 +160,12 @@ void add_line_buffer(struct session *ses, char *line, int prompt)
 
 
 	push_call("add_line_buffer(%p,%s,%d)",ses,line,prompt);
 	push_call("add_line_buffer(%p,%s,%d)",ses,line,prompt);
 
 
+	if (HAS_BIT(ses->flags, SES_FLAG_SNOOPSCROLL))
+	{
+		SET_BIT(gtd->flags, TINTIN_FLAG_SESSIONUPDATE);
+		SET_BIT(ses->flags, SES_FLAG_PRINTLINE);
+	}
+
 	if (gtd->level->scroll)
 	if (gtd->level->scroll)
 	{
 	{
 		pop_call();
 		pop_call();
@@ -438,7 +444,7 @@ int show_buffer(struct session *ses)
 {
 {
 	int scroll_size, scroll_cnt, scroll_tmp, scroll_add, scroll_cut, start, end, row;
 	int scroll_size, scroll_cnt, scroll_tmp, scroll_add, scroll_cut, start, end, row;
 
 
-	if (ses != gtd->ses)
+	if (ses != gtd->ses && !HAS_BIT(ses->flags, SES_FLAG_SNOOPSCROLL))
 	{
 	{
 		return TRUE;
 		return TRUE;
 	}
 	}

+ 9 - 2
src/cursor.c

@@ -908,8 +908,15 @@ DO_CURSOR(cursor_delete)
 		}
 		}
 	}
 	}
 
 
-	cursor_redraw_line(ses, "");
-
+	if (gtd->ses->input->raw_len == gtd->ses->input->raw_pos)
+	{
+		input_printf("\e[1X");
+		cursor_check_line(ses, arg);
+	}
+	else
+	{
+		cursor_redraw_line(ses, "");
+	}
 	modified_input();
 	modified_input();
 }
 }
 
 

+ 263 - 199
src/data.c

@@ -422,10 +422,6 @@ struct listnode *search_node_list(struct listroot *root, char *text)
 			index = bsearch_alnum_list(root, text, 0);
 			index = bsearch_alnum_list(root, text, 0);
 			break;
 			break;
 
 
-		case SORT_DELAY:
-			index = bsearch_priority_list(root, text, text, 0);
-			break;
-
 		default:
 		default:
 			index = nsearch_list(root, text);
 			index = nsearch_list(root, text);
 			break;
 			break;
@@ -452,9 +448,6 @@ int search_index_list(struct listroot *root, char *text, char *priority)
 		case SORT_ALNUM:
 		case SORT_ALNUM:
 			return bsearch_alnum_list(root, text, 0);
 			return bsearch_alnum_list(root, text, 0);
 
 
-		case SORT_DELAY:
-			return bsearch_priority_list(root, text, text, 0);
-
 		case SORT_PRIORITY:
 		case SORT_PRIORITY:
 			if (priority)
 			if (priority)
 			{
 			{
@@ -483,9 +476,6 @@ int locate_index_list(struct listroot *root, char *text, char *priority)
 		case SORT_ALNUM:
 		case SORT_ALNUM:
 			return bsearch_alnum_list(root, text, SEEK_REPLACE);
 			return bsearch_alnum_list(root, text, SEEK_REPLACE);
 
 
-		case SORT_DELAY:
-			return bsearch_priority_list(root, text, text, SEEK_REPLACE);
-
 		case SORT_PRIORITY:
 		case SORT_PRIORITY:
 			return bsearch_priority_list(root, text, priority, SEEK_REPLACE);
 			return bsearch_priority_list(root, text, priority, SEEK_REPLACE);
 
 
@@ -524,7 +514,7 @@ int bsearch_alpha_list(struct listroot *root, char *text, int seek)
 
 
 	if (seek)
 	if (seek)
 	{
 	{
-		return bot += strcmp(text, root->list[bot]->arg1) > 0;
+		return bot + (strcmp(text, root->list[bot]->arg1) > 0);
 	}
 	}
 
 
 	return -1;
 	return -1;
@@ -826,10 +816,6 @@ int show_node_with_wild(struct session *ses, char *text, struct listroot *root)
 			index = bsearch_alnum_list(root, text, 0);
 			index = bsearch_alnum_list(root, text, 0);
 			break;
 			break;
 
 
-		case SORT_DELAY:
-			index = bsearch_priority_list(root, text, text, 0);
-			break;
-
 		default:
 		default:
 			index = nsearch_list(root, text);
 			index = nsearch_list(root, text);
 			break;
 			break;
@@ -936,10 +922,6 @@ int delete_node_with_wild(struct session *ses, int type, char *text)
 			index = bsearch_alnum_list(root, arg1, 0);
 			index = bsearch_alnum_list(root, arg1, 0);
 			break;
 			break;
 
 
-		case SORT_DELAY:
-			index = bsearch_priority_list(root, arg1, arg1, 0);
-			break;
-
 		default:
 		default:
 			index = nsearch_list(root, arg1);
 			index = nsearch_list(root, arg1);
 			break;
 			break;
@@ -1258,14 +1240,14 @@ DO_COMMAND(do_info)
 		{
 		{
 			if (!HAS_BIT(ses->list[index]->flags, LIST_FLAG_HIDE))
 			if (!HAS_BIT(ses->list[index]->flags, LIST_FLAG_HIDE))
 			{
 			{
-				tintin_printf2(ses, "%-15s %5d   IGNORE %3s   MESSAGE %3s   INFO %3s   DEBUG %3s %3s",
+				tintin_printf2(ses, "%-15s %5d   IGNORE %3s   MESSAGE %3s   INFO %3s   DEBUG %3s%s",
 					list_table[index].name_multi,
 					list_table[index].name_multi,
 					ses->list[index]->used,
 					ses->list[index]->used,
 					HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE)  ?  "ON" : "OFF",
 					HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE)  ?  "ON" : "OFF",
 					HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ?  "ON" : "OFF",
 					HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ?  "ON" : "OFF",
 					HAS_BIT(ses->list[index]->flags, LIST_FLAG_INFO)    ?  "ON" : "OFF",
 					HAS_BIT(ses->list[index]->flags, LIST_FLAG_INFO)    ?  "ON" : "OFF",
 					HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG)   ?  "ON" : "OFF",
 					HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG)   ?  "ON" : "OFF",
-					HAS_BIT(ses->list[index]->flags, LIST_FLAG_LOG)     ? "LOG" : "   ");
+					HAS_BIT(ses->list[index]->flags, LIST_FLAG_LOG)     ? " LOG" : "");
 			}
 			}
 		}
 		}
 		tintin_header(ses, 80, "");
 		tintin_header(ses, 80, "");
@@ -1329,240 +1311,322 @@ DO_COMMAND(do_info)
 			}
 			}
 			show_message(ses, LIST_COMMAND, "#OK: #INFO STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_INFO) ? "ON" : "OFF");
 			show_message(ses, LIST_COMMAND, "#OK: #INFO STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_INFO) ? "ON" : "OFF");
 
 
+			if (strcasecmp(arg1, "ALL"))
+			{
+				return ses;
+			}
 			found = TRUE;
 			found = TRUE;
 		}
 		}
 
 
-		if (found == FALSE)
+		if (found)
 		{
 		{
-			if (is_abbrev(arg1, "CPU"))
-			{
-				show_cpu(ses);
-			}
-			else if (is_abbrev(arg1, "MCCP"))
-			{
-				if (ses->mccp2)
-				{
-					tintin_printf2(ses, "#INFO MCCP2: TOTAL IN: %9u TOTAL OUT: %9u PERCENT: %3d", ses->mccp2->total_in, ses->mccp2->total_out, ses->mccp2->total_out ? 100 * ses->mccp2->total_in / ses->mccp2->total_out : 0);
-				}
-				if (ses->mccp3)
-				{
-					tintin_printf2(ses, "#INFO MCCP3: TOTAL IN: %9u TOTAL OUT: %9u PERCENT: %3d", ses->mccp3->total_in, ses->mccp3->total_out, ses->mccp3->total_in ? 100 * ses->mccp3->total_out / ses->mccp3->total_in : 0);
-				}
-			}
-			else if (is_abbrev(arg1, "MEMORY"))
-			{
-				struct str_data *str_ptr;
-
-				long long quan, used, max;
+			return ses;
+		}
 
 
-				max  = 0;
-				quan = 0;
-				used = 0;
+		*gtd->is_result = 0;
 
 
-				for (index = 0 ; index < gtd->memory->stack_cap ; index++)
+		switch (*arg1 % 32)
+		{
+			case CTRL_C:
+				if (is_abbrev(arg1, "CPU"))
 				{
 				{
-					max++;
-					quan += gtd->memory->stack[index]->max;
-					used += gtd->memory->stack[index]->len;
+					show_cpu(ses);
 				}
 				}
+				break;
 
 
-				tintin_printf2(ses, "#INFO MEMORY: STACK SIZE: %d", quan);
+			case CTRL_E:
+				if (is_abbrev(arg1, "ENVIRON"))
+				{
+					char **env, *sep;
 
 
-				tintin_printf2(ses, "#INFO MEMORY: STACK  MAX: %d", gtd->memory->stack_max);
-				tintin_printf2(ses, "#INFO MEMORY: STACK  CAP: %d", gtd->memory->stack_cap);
-				tintin_printf2(ses, "#INFO MEMORY: STACK  LEN: %d", gtd->memory->stack_len);
+					if (is_abbrev(arg2, "SAVE"))
+					{
+						set_nest_node_ses(ses, "info[ENVIRON]", "");
 
 
-				tintin_printf2(ses, "");
+						for (env = environ ; *env ; env++)
+						{
+							sep = strchr(*env, '=');
 
 
-				max  = 0;
-				quan = 0;
-				used = 0;
+							*sep = 0;
 
 
-				for (index = 0 ; index < gtd->memory->list_len ; index++)
-				{
-					str_ptr = gtd->memory->list[index];
+							add_nest_node_ses(ses, "info[ENVIRON]", "{%s}{%s}", *env, sep + 1);
 
 
-					if (str_ptr->max != NAME_SIZE + 1 && strlen(get_str_str(str_ptr)) != str_ptr->len)
+							*sep = '=';
+						}
+					}
+					else
 					{
 					{
-						tintin_printf2(ses, "#ERROR: index %d len = %d/%d max = %d flags = %d (%s)", index, strlen(get_str_str(str_ptr)), str_ptr->len, str_ptr->max, str_ptr->flags, get_str_str(str_ptr));
+						for (env = environ ; *env ; env++)
+						{
+							tintin_printf2(ses, "%s", *env);
+						}
 					}
 					}
+				}
+				break;
 
 
-					if (!HAS_BIT(str_ptr->flags, STR_FLAG_FREE))
+			case CTRL_I:
+				if (is_abbrev(arg1, "INPUT"))
+				{
+					if (is_abbrev(arg2, "SAVE"))
 					{
 					{
-						max++;
-						quan += str_ptr->max;
-						used += str_ptr->len;
+						set_nest_node_ses(ses, "info[INPUT]", "{BUFFER}{%s}", gtd->ses->input->buf);
+						add_nest_node_ses(ses, "info[INPUT]", "{CUT}{%s}", gtd->ses->input->cut);
+						add_nest_node_ses(ses, "info[INPUT]", "{COL}{%d}", inputline_cur_col());
+						add_nest_node_ses(ses, "info[INPUT]", "{HEIGHT}{%d}", inputline_max_row());
+						add_nest_node_ses(ses, "info[INPUT]", "{LENGTH}{%d}", inputline_cur_str_len());
+						add_nest_node_ses(ses, "info[INPUT]", "{NAME}{%s}", gtd->ses->input->line_name);
+						add_nest_node_ses(ses, "info[INPUT]", "{OFFSET}{%d}", inputline_cur_off());
+						add_nest_node_ses(ses, "info[INPUT]", "{ROW}{%d}", inputline_cur_row());
+						add_nest_node_ses(ses, "info[INPUT]", "{WIDTH}{%d}", inputline_max_str_len());
+					}
+					else
+					{
+						tintin_printf2(ses, "#INFO INPUT: BUFFER: %s", gtd->ses->input->buf);
+						tintin_printf2(ses, "#INFO INPUT: CUT: %s", gtd->ses->input->cut);
+						tintin_printf2(ses, "#INFO INPUT: COL: %d", inputline_cur_col());
+						tintin_printf2(ses, "#INFO INPUT: HEIGHT: %d", inputline_max_row());
+						tintin_printf2(ses, "#INFO INPUT: LENGTH: %d", inputline_cur_str_len());
+						tintin_printf2(ses, "#INFO INPUT: NAME: %s", gtd->ses->input->line_name);
+						tintin_printf2(ses, "#INFO INPUT: OFFSET: %d", inputline_cur_off());
+						tintin_printf2(ses, "#INFO INPUT: ROW: %d", inputline_cur_row());
+						tintin_printf2(ses, "#INFO INPUT: WIDTH: %d", inputline_max_str_len());
 					}
 					}
 				}
 				}
+				break;
 
 
-				tintin_printf2(ses, "#INFO MEMORY: ALLOC SIZE: %d", quan);
-				tintin_printf2(ses, "#INFO MEMORY: ALLOC USED: %d", used);
-
-				tintin_printf2(ses, "#INFO MEMORY: ALLOC  MAX: %d", gtd->memory->list_max);
-				tintin_printf2(ses, "#INFO MEMORY: ALLOC  LEN: %d", gtd->memory->list_len);
-
-				tintin_printf2(ses, "");
+			case CTRL_M:
+				if (is_abbrev(arg1, "MCCP"))
+				{
+					if (ses->mccp2)
+					{
+						tintin_printf2(ses, "#INFO MCCP2: TOTAL IN: %9u TOTAL OUT: %9u PERCENT: %3d", ses->mccp2->total_in, ses->mccp2->total_out, ses->mccp2->total_out ? 100 * ses->mccp2->total_in / ses->mccp2->total_out : 0);
+					}
+					if (ses->mccp3)
+					{
+						tintin_printf2(ses, "#INFO MCCP3: TOTAL IN: %9u TOTAL OUT: %9u PERCENT: %3d", ses->mccp3->total_in, ses->mccp3->total_out, ses->mccp3->total_in ? 100 * ses->mccp3->total_out / ses->mccp3->total_in : 0);
+					}
+				}
+				else if (is_abbrev(arg1, "MEMORY"))
+				{
+					struct str_data *str_ptr;
 
 
-				quan = 0;
-				used = 0;
+					long long quan, used, max;
 
 
-				for (index = 0 ; index < gtd->memory->free_len ; index++)
-				{
-					str_ptr = gtd->memory->list[gtd->memory->free[index]];
+					max  = 0;
+					quan = 0;
+					used = 0;
 
 
-					if (HAS_BIT(str_ptr->flags, STR_FLAG_FREE))
+					for (index = 0 ; index < gtd->memory->stack_cap ; index++)
 					{
 					{
-						quan += str_ptr->max;
-						used += str_ptr->len;
+						max++;
+						quan += gtd->memory->stack[index]->max;
+						used += gtd->memory->stack[index]->len;
 					}
 					}
-					else
+
+					tintin_printf2(ses, "#INFO MEMORY: STACK SIZE: %d", quan);
+
+					tintin_printf2(ses, "#INFO MEMORY: STACK  MAX: %d", gtd->memory->stack_max);
+					tintin_printf2(ses, "#INFO MEMORY: STACK  CAP: %d", gtd->memory->stack_cap);
+					tintin_printf2(ses, "#INFO MEMORY: STACK  LEN: %d", gtd->memory->stack_len);
+
+					tintin_printf2(ses, "");
+
+					max  = 0;
+					quan = 0;
+					used = 0;
+
+					for (index = 0 ; index < gtd->memory->list_len ; index++)
 					{
 					{
-						tintin_printf2(ses, "error: found freed memory not marked as free.");
+						str_ptr = gtd->memory->list[index];
+
+						if (str_ptr->max != NAME_SIZE + 1 && strlen(get_str_str(str_ptr)) != str_ptr->len)
+						{
+							tintin_printf2(ses, "#ERROR: index %d len = %d/%d max = %d flags = %d (%s)", index, strlen(get_str_str(str_ptr)), str_ptr->len, str_ptr->max, str_ptr->flags, get_str_str(str_ptr));
+						}
+
+						if (!HAS_BIT(str_ptr->flags, STR_FLAG_FREE))
+						{
+							max++;
+							quan += str_ptr->max;
+							used += str_ptr->len;
+						}
 					}
 					}
-				}
 
 
-				tintin_printf2(ses, "#INFO MEMORY: FREED SIZE: %d", quan);
+					tintin_printf2(ses, "#INFO MEMORY: ALLOC SIZE: %d", quan);
+					tintin_printf2(ses, "#INFO MEMORY: ALLOC USED: %d", used);
 
 
-				tintin_printf2(ses, "#INFO MEMORY: FREED  MAX: %d", gtd->memory->free_max);
-				tintin_printf2(ses, "#INFO MEMORY: FREED  LEN: %d", gtd->memory->free_len);
+					tintin_printf2(ses, "#INFO MEMORY: ALLOC  MAX: %d", gtd->memory->list_max);
+					tintin_printf2(ses, "#INFO MEMORY: ALLOC  LEN: %d", gtd->memory->list_len);
 
 
-				tintin_printf2(ses, "");
+					tintin_printf2(ses, "");
 
 
-				quan = 0;
-				used = 0;
+					quan = 0;
+					used = 0;
 
 
-				for (index = 0 ; index < gtd->memory->debug_len ; index++)
-				{
-					quan += NAME_SIZE;
-				}
+					for (index = 0 ; index < gtd->memory->free_len ; index++)
+					{
+						str_ptr = gtd->memory->list[gtd->memory->free[index]];
+
+						if (HAS_BIT(str_ptr->flags, STR_FLAG_FREE))
+						{
+							quan += str_ptr->max;
+							used += str_ptr->len;
+						}
+						else
+						{
+							tintin_printf2(ses, "error: found freed memory not marked as free.");
+						}
+					}
 
 
-				tintin_printf2(ses, "#INFO MEMORY: DEBUG SIZE: %d", quan);
+					tintin_printf2(ses, "#INFO MEMORY: FREED SIZE: %d", quan);
 
 
-				tintin_printf2(ses, "#INFO MEMORY: DEBUG  MAX: %d", gtd->memory->debug_max);
-				tintin_printf2(ses, "#INFO MEMORY: DEBUG  LEN: %d", gtd->memory->debug_len);
-			}
-			else if (is_abbrev(arg1, "SESSION"))
-			{
-				if (is_abbrev(arg2, "SAVE"))
-				{
-					sprintf(name, "info[SESSION]");
+					tintin_printf2(ses, "#INFO MEMORY: FREED  MAX: %d", gtd->memory->free_max);
+					tintin_printf2(ses, "#INFO MEMORY: FREED  LEN: %d", gtd->memory->free_len);
 
 
-					set_nest_node_ses(ses, name, "{NAME}{%s}", ses->name);
-					add_nest_node_ses(ses, name, "{ACTIVE}{%d}", gtd->ses == ses);
-					add_nest_node_ses(ses, name, "{CLASS}{%s}", ses->group);
-					add_nest_node_ses(ses, name, "{CREATED}{%d}", ses->created);
-					add_nest_node_ses(ses, name, "{HOST} {%s}", ses->session_host);
-					add_nest_node_ses(ses, name, "{IP} {%s}", ses->session_ip);
-					add_nest_node_ses(ses, name, "{PORT} {%s}", ses->session_port);
+					tintin_printf2(ses, "");
 
 
-					show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SESSION]}");
-				}
-				else
-				{
-					tintin_printf2(ses, "{NAME}{%s}", ses->name);
-					tintin_printf2(ses, "{ACTIVE}{%d}", gtd->ses == ses);
-					tintin_printf2(ses, "{CLASS}{%s}", ses->group);
-					tintin_printf2(ses, "{CREATED}{%d}", ses->created);
-					tintin_printf2(ses, "{HOST} {%s}", ses->session_host);
-					tintin_printf2(ses, "{IP} {%s}", ses->session_ip);
-					tintin_printf2(ses, "{PORT} {%s}", ses->session_port);
+					quan = 0;
+					used = 0;
+
+					for (index = 0 ; index < gtd->memory->debug_len ; index++)
+					{
+						quan += NAME_SIZE;
+					}
+
+					tintin_printf2(ses, "#INFO MEMORY: DEBUG SIZE: %d", quan);
+
+					tintin_printf2(ses, "#INFO MEMORY: DEBUG  MAX: %d", gtd->memory->debug_max);
+					tintin_printf2(ses, "#INFO MEMORY: DEBUG  LEN: %d", gtd->memory->debug_len);
 				}
 				}
-			}
-			else if (is_abbrev(arg1, "SESSIONS"))
-			{
-				struct session *sesptr;
+				break;
 
 
-				if (is_abbrev(arg2, "SAVE"))
+			case CTRL_S:
+				if (is_abbrev(arg1, "SESSION"))
 				{
 				{
-					set_nest_node_ses(ses, "info[SESSIONS]", "");
-
-					for (sesptr = gts ; sesptr ; sesptr = sesptr->next)
+					if (is_abbrev(arg2, "SAVE"))
+					{
+						set_nest_node_ses(ses, "info[SESSION]", "{NAME}{%s}", ses->name);
+						add_nest_node_ses(ses, "info[SESSION]", "{ACTIVE}{%d}", gtd->ses == ses);
+						add_nest_node_ses(ses, "info[SESSION]", "{CLASS}{%s}", ses->group);
+						add_nest_node_ses(ses, "info[SESSION]", "{CREATED}{%d}", ses->created);
+						add_nest_node_ses(ses, "info[SESSION]", "{HOST} {%s}", ses->session_host);
+						add_nest_node_ses(ses, "info[SESSION]", "{IP} {%s}", ses->session_ip);
+						add_nest_node_ses(ses, "info[SESSION]", "{PORT} {%s}", ses->session_port);
+
+						show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SESSION]}");
+					}
+					else
 					{
 					{
-						sprintf(name, "info[SESSIONS][%s]", sesptr->name);
-
-						add_nest_node_ses(ses, name, "{NAME}{%s}", sesptr->name);
-						add_nest_node_ses(ses, name, "{ACTIVE}{%d}", gtd->ses == sesptr);
-						add_nest_node_ses(ses, name, "{CLASS}{%s}", sesptr->group);
-						add_nest_node_ses(ses, name, "{CREATED}{%d}", sesptr->created);
-						add_nest_node_ses(ses, name, "{HOST} {%s}", sesptr->session_host);
-						add_nest_node_ses(ses, name, "{IP} {%s}", sesptr->session_ip);
-						add_nest_node_ses(ses, name, "{PORT} {%s}", sesptr->session_port);
+						tintin_printf2(ses, "{NAME}{%s}", ses->name);
+						tintin_printf2(ses, "{ACTIVE}{%d}", gtd->ses == ses);
+						tintin_printf2(ses, "{CLASS}{%s}", ses->group);
+						tintin_printf2(ses, "{CREATED}{%d}", ses->created);
+						tintin_printf2(ses, "{HOST} {%s}", ses->session_host);
+						tintin_printf2(ses, "{IP} {%s}", ses->session_ip);
+						tintin_printf2(ses, "{PORT} {%s}", ses->session_port);
 					}
 					}
-					show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SESSION]}");
 				}
 				}
-				else
+				else if (is_abbrev(arg1, "SESSIONS"))
 				{
 				{
-					for (sesptr = gts ; sesptr ; sesptr = sesptr->next)
+					struct session *sesptr;
+
+					if (is_abbrev(arg2, "SAVE"))
 					{
 					{
-						tintin_printf2(ses, "{%s}{NAME}{%s}", sesptr->name, sesptr->name);
-						tintin_printf2(ses, "{%s}{ACTIVE}{%d}", sesptr->name, gtd->ses == sesptr);
-						tintin_printf2(ses, "{%s}{CLASS}{%s}", sesptr->name, sesptr->group);
-						tintin_printf2(ses, "{%s}{CREATED}{%d}", sesptr->name, sesptr->created);
-						tintin_printf2(ses, "{%s}{HOST} {%s}", sesptr->name, sesptr->session_host);
-						tintin_printf2(ses, "{%s}{IP} {%s}", sesptr->name, sesptr->session_ip);
-						tintin_printf2(ses, "{%s}{PORT} {%s}", sesptr->name, sesptr->session_port);
+						set_nest_node_ses(ses, "info[SESSIONS]", "");
+
+						for (sesptr = gts ; sesptr ; sesptr = sesptr->next)
+						{
+							sprintf(name, "info[SESSIONS][%s]", sesptr->name);
+
+							add_nest_node_ses(ses, name, "{NAME}{%s}", sesptr->name);
+							add_nest_node_ses(ses, name, "{ACTIVE}{%d}", gtd->ses == sesptr);
+							add_nest_node_ses(ses, name, "{CLASS}{%s}", sesptr->group);
+							add_nest_node_ses(ses, name, "{CREATED}{%d}", sesptr->created);
+							add_nest_node_ses(ses, name, "{HOST} {%s}", sesptr->session_host);
+							add_nest_node_ses(ses, name, "{IP} {%s}", sesptr->session_ip);
+							add_nest_node_ses(ses, name, "{PORT} {%s}", sesptr->session_port);
+						}
+						show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SESSION]}");
+					}
+					else
+					{
+						for (sesptr = gts ; sesptr ; sesptr = sesptr->next)
+						{
+							tintin_printf2(ses, "{%s}{NAME}{%s}", sesptr->name, sesptr->name);
+							tintin_printf2(ses, "{%s}{ACTIVE}{%d}", sesptr->name, gtd->ses == sesptr);
+							tintin_printf2(ses, "{%s}{CLASS}{%s}", sesptr->name, sesptr->group);
+							tintin_printf2(ses, "{%s}{CREATED}{%d}", sesptr->name, sesptr->created);
+							tintin_printf2(ses, "{%s}{HOST} {%s}", sesptr->name, sesptr->session_host);
+							tintin_printf2(ses, "{%s}{IP} {%s}", sesptr->name, sesptr->session_ip);
+							tintin_printf2(ses, "{%s}{PORT} {%s}", sesptr->name, sesptr->session_port);
+						}
 					}
 					}
 				}
 				}
-			}
-			else if (is_abbrev(arg1, "STACK"))
-			{
-				dump_stack();
-			}
-			else if (is_abbrev(arg1, "SYSTEM"))
-			{
-				char cwd[PATH_MAX];
-
-				if (getcwd(cwd, PATH_MAX) == NULL)
+				else if (is_abbrev(arg1, "STACK"))
 				{
 				{
-					syserr_printf(ses, "do_info: getcwd:");
+					dump_stack();
 				}
 				}
-
-				if (is_abbrev(arg2, "SAVE"))
+				else if (is_abbrev(arg1, "SYSTEM"))
 				{
 				{
-					sprintf(name, "info[SYSTEM]");
+					char cwd[PATH_MAX];
+
+					if (getcwd(cwd, PATH_MAX) == NULL)
+					{
+						syserr_printf(ses, "do_info: getcwd:");
+
+						cwd[0] = 0;
+					}
+
+					if (is_abbrev(arg2, "SAVE"))
+					{
+						sprintf(name, "info[SYSTEM]");
 
 
-					set_nest_node_ses(ses, name, "{CLIENT_NAME}{%s}{CLIENT_VERSION}{%s}", CLIENT_NAME, CLIENT_VERSION);
-//					add_nest_node_ses(ses, name, "{CLIENT}{{NAME}{%s}{VERSION}{%s}}", CLIENT_NAME, CLIENT_VERSION);
-					add_nest_node_ses(ses, name, "{CWD}{%s}{EXEC}{%s}{HOME}{%s}{LANG}{%s}{OS}{%s}{TERM}{%s}{TINTIN}{%s}", cwd, gtd->system->exec, gtd->system->home, gtd->system->lang, gtd->system->os, gtd->system->term, gtd->system->tt_dir);
-					add_nest_node_ses(ses, name, "{DETACH_FILE}{%s}{ATTACH_FILE}{%s}", gtd->detach_port > 0 ? gtd->detach_file : "", gtd->attach_sock > 0 ? gtd->attach_file : "");
+						set_nest_node_ses(ses, name, "{CLIENT_NAME}{%s}{CLIENT_VERSION}{%s}", CLIENT_NAME, CLIENT_VERSION);
+						add_nest_node_ses(ses, name, "{CWD}{%s}{EXEC}{%s}{HOME}{%s}{LANG}{%s}{OS}{%s}{PID}{%d}{TERM}{%s}{TINTIN}{%s}", cwd, gtd->system->exec, gtd->system->home, gtd->system->lang, gtd->system->os, getpid(), gtd->system->term, gtd->system->tt_dir);
+						add_nest_node_ses(ses, name, "{DETACH_FILE}{%s}{ATTACH_FILE}{%s}", gtd->detach_port > 0 ? gtd->detach_file : "", gtd->attach_sock > 0 ? gtd->attach_file : "");
 
 
-					show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SYSTEM]}");
+						show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SYSTEM]}");
+					}
+					else
+					{
+						tintin_printf2(ses, "#INFO SYSTEM: CLIENT_NAME    = %s", CLIENT_NAME);
+						tintin_printf2(ses, "#INFO SYSTEM: CLIENT_VERSION = %s", CLIENT_VERSION);
+						tintin_printf2(ses, "#INFO SYSTEM: CWD            = %s", cwd);
+						tintin_printf2(ses, "#INFO SYSTEM: EXEC           = %s", gtd->system->exec);
+						tintin_printf2(ses, "#INFO SYSTEM: HOME           = %s", gtd->system->home);
+						tintin_printf2(ses, "#INFO SYSTEM: LANG           = %s", gtd->system->lang);
+						tintin_printf2(ses, "#INFO SYSTEM: OS             = %s", gtd->system->os);
+						tintin_printf2(ses, "#INFO SYSTEM: PID            = %d", getpid());
+						tintin_printf2(ses, "#INFO SYSTEM: TERM           = %s", gtd->system->term);
+						tintin_printf2(ses, "#INFO SYSTEM: TINTIN         = %s", gtd->system->tt_dir);
+						tintin_printf2(ses, "#INFO SYSTEM: DETACH_PORT    = %d", gtd->detach_port);
+						tintin_printf2(ses, "#INFO SYSTEM: DETACH_FILE    = %s", gtd->detach_port ? gtd->detach_file : "");
+						tintin_printf2(ses, "#INFO SYSTEM: ATTACH_SOCK    = %d", gtd->attach_sock);
+						tintin_printf2(ses, "#INFO SYSTEM: ATTACH_FILE    = %s", gtd->attach_sock ? gtd->attach_file : "");
+					}
 				}
 				}
-				else
+				break;
+
+			case CTRL_U:
+				if (is_abbrev(arg1, "UNICODE"))
 				{
 				{
-					tintin_printf2(ses, "#INFO SYSTEM: CLIENT_NAME    = %s", CLIENT_NAME);
-					tintin_printf2(ses, "#INFO SYSTEM: CLIENT_VERSION = %s", CLIENT_VERSION);
-					tintin_printf2(ses, "#INFO SYSTEM: CWD            = %s", cwd);
-					tintin_printf2(ses, "#INFO SYSTEM: EXEC           = %s", gtd->system->exec);
-					tintin_printf2(ses, "#INFO SYSTEM: HOME           = %s", gtd->system->home);
-					tintin_printf2(ses, "#INFO SYSTEM: LANG           = %s", gtd->system->lang);
-					tintin_printf2(ses, "#INFO SYSTEM: OS             = %s", gtd->system->os);
-					tintin_printf2(ses, "#INFO SYSTEM: TERM           = %s", gtd->system->term);
-					tintin_printf2(ses, "#INFO SYSTEM: TINTIN         = %s", gtd->system->tt_dir);
-					tintin_printf2(ses, "#INFO SYSTEM: DETACH_PORT    = %d", gtd->detach_port);
-					tintin_printf2(ses, "#INFO SYSTEM: DETACH_FILE    = %s", gtd->detach_port ? gtd->detach_file : "");
-					tintin_printf2(ses, "#INFO SYSTEM: ATTACH_SOCK    = %d", gtd->attach_sock);
-					tintin_printf2(ses, "#INFO SYSTEM: ATTACH_FILE    = %s", gtd->attach_sock ? gtd->attach_file : "");
-				}
-			}
-			else if (is_abbrev(arg1, "UNICODE"))
-			{
-				int size, width, index;
+					int size, width, index;
 
 
-				size = get_utf8_size(arg2);
-				get_utf8_width(arg2, &width);
-				get_utf8_index(arg2, &index);
+					size = get_utf8_size(arg2);
+					get_utf8_width(arg2, &width);
+					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: get_utf8_size  = %d", arg2, size);
-				tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_width = %d", arg2, width);
-				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);
-			}
-			else
-			{
-				show_error(ses, LIST_COMMAND, "#INFO {%s} - NO MATCH FOUND.", arg1);
-			}
+					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: get_utf8_size  = %d", arg2, size);
+					tintin_printf2(ses, "#INFO UNICODE: %s: get_utf8_width = %d", arg2, width);
+					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);
+				}
+				break;
+		}
+		if (*gtd->is_result == 0)
+		{
+			show_error(ses, LIST_COMMAND, "#INFO {%s} - NO MATCH FOUND.", arg1);
 		}
 		}
 	}
 	}
 	return ses;
 	return ses;

+ 10 - 7
src/dict.c

@@ -29,8 +29,8 @@
 
 
 struct dictionary_data
 struct dictionary_data
 {
 {
-	unsigned int  * wordindex[26];
-	int             listsize[26];
+	unsigned int * wordindex[26];
+	unsigned int   listsize[26];
 };
 };
 
 
 struct dictionary_data *dictionary;
 struct dictionary_data *dictionary;
@@ -83,11 +83,12 @@ void dictionary_init()
 		}
 		}
 		while (*pta);
 		while (*pta);
 	}
 	}
-
-//	for (hash = 0 ; hash < 26 ; hash++)
-//	{
-//		printf("hash %2d = %d\n", hash, dictionary->listsize[hash]);
-//	}
+/*
+	for (hash = 0 ; hash < 26 ; hash++)
+	{
+		printf("hash %c = %d\n", 'A' + hash, dictionary->listsize[hash]);
+	}
+*/
 }
 }
 
 
 int dictionary_search(int hash, char *key)
 int dictionary_search(int hash, char *key)
@@ -190,6 +191,8 @@ DO_COMMAND(do_dictionary)
 	{
 	{
 		show_message(ses, LIST_COMMAND, "#SYNTAX: #DICTIONARY {WORD}");
 		show_message(ses, LIST_COMMAND, "#SYNTAX: #DICTIONARY {WORD}");
 
 
+		wordlist[0][0] = 0;
+
 		return ses;
 		return ses;
 	}
 	}
 
 

+ 22 - 5
src/draw.c

@@ -70,6 +70,7 @@ static int  draw_cnt;
 #define DRAW_FLAG_RALIGN              BV38
 #define DRAW_FLAG_RALIGN              BV38
 #define DRAW_FLAG_TALIGN              BV39
 #define DRAW_FLAG_TALIGN              BV39
 #define DRAW_FLAG_UALIGN              BV40
 #define DRAW_FLAG_UALIGN              BV40
+#define DRAW_FLAG_BALIGN              BV41
 
 
 #define DRAW_FLAG_APPENDIX            DRAW_FLAG_CIRCLED|DRAW_FLAG_CORNERED|DRAW_FLAG_CROSSED|DRAW_FLAG_JEWELED|DRAW_FLAG_PRUNED|DRAW_FLAG_ROUNDED|DRAW_FLAG_TEED
 #define DRAW_FLAG_APPENDIX            DRAW_FLAG_CIRCLED|DRAW_FLAG_CORNERED|DRAW_FLAG_CROSSED|DRAW_FLAG_JEWELED|DRAW_FLAG_PRUNED|DRAW_FLAG_ROUNDED|DRAW_FLAG_TEED
 
 
@@ -198,7 +199,11 @@ DO_COMMAND(do_draw)
 				}
 				}
 				continue;
 				continue;
 			case CTRL_B:
 			case CTRL_B:
-				if (is_abbrev(arg1, "BLANKED"))
+				if (is_abbrev(arg1, "BALIGN"))
+				{
+					SET_BIT(flags, DRAW_FLAG_BALIGN);
+				}
+				else if (is_abbrev(arg1, "BLANKED"))
 				{
 				{
 					SET_BIT(flags, DRAW_FLAG_BLANKED);
 					SET_BIT(flags, DRAW_FLAG_BLANKED);
 				}
 				}
@@ -1714,7 +1719,7 @@ DO_DRAW(draw_hbar)
 
 
 	if (bar <= 0)
 	if (bar <= 0)
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#DRAW HBAR %d %d %d %d: DRAWING WIDTH (%d) MUST BE GREATER THAN 0.", top_row, top_col, bot_row, bot_col, bar);
+		show_error(ses, LIST_COMMAND, "#DRAW BAR %d %d %d %d: DRAWING WIDTH (%d) MUST BE GREATER THAN 0.", top_row, top_col, bot_row, bot_col, bar);
 
 
 		return;
 		return;
 	}
 	}
@@ -1732,9 +1737,11 @@ DO_DRAW(draw_hbar)
 
 
 	nest = buf;
 	nest = buf;
 	nest = get_arg_in_braces(ses, nest, arg1, GET_ALL);
 	nest = get_arg_in_braces(ses, nest, arg1, GET_ALL);
-	if (*nest == COMMAND_SEPARATOR) nest++;
+	if (*nest == COMMAND_SEPARATOR)
+		nest++;
 	nest = get_arg_in_braces(ses, nest, arg2, GET_ALL);
 	nest = get_arg_in_braces(ses, nest, arg2, GET_ALL);
-	if (*nest == COMMAND_SEPARATOR) nest++;
+	if (*nest == COMMAND_SEPARATOR)
+		nest++;
 	nest = get_arg_in_braces(ses, nest, arg3, GET_ALL);
 	nest = get_arg_in_braces(ses, nest, arg3, GET_ALL);
 
 
 	min = get_number(ses, arg1);
 	min = get_number(ses, arg1);
@@ -1742,7 +1749,7 @@ DO_DRAW(draw_hbar)
 
 
 	if (max <= 0)
 	if (max <= 0)
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#DRAW HBAR {%d;%d;%s}: MAX MUST BE GREATER THAN 0.", min, max, arg3);
+		show_error(ses, LIST_COMMAND, "#DRAW BAR {%s;%s;%s}: MAX (%Lg) MUST BE GREATER THAN 0.", arg1, arg2, arg3, max);
 
 
 		return;
 		return;
 	}
 	}
@@ -2441,6 +2448,16 @@ DO_DRAW(draw_text)
 
 
 	txt = buf1;
 	txt = buf1;
 
 
+	if (HAS_BIT(flags, DRAW_FLAG_BALIGN))
+	{
+		str_fix(buf1);
+
+		while (height < rows)
+		{
+			str_ins(&buf1, 0, "\n");
+			height++;
+		}
+	}
 
 
 	if (HAS_BIT(flags, DRAW_FLAG_TALIGN))
 	if (HAS_BIT(flags, DRAW_FLAG_TALIGN))
 	{
 	{

+ 7 - 0
src/edit.c

@@ -269,6 +269,13 @@ DO_EDIT(edit_suspend)
 {
 {
 	struct edit_data *edit = gtd->ses->input->edit;
 	struct edit_data *edit = gtd->ses->input->edit;
 
 
+	if (!HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_EDIT))
+	{
+		tintin_printf2(gtd->ses, "edit_suspend: not currently editing");
+
+		return ses;
+	}
+
 	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_EDIT);
 	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_EDIT);
 
 
 	str_cpy(&edit->line[edit->update]->str, gtd->ses->input->buf);
 	str_cpy(&edit->line[edit->update]->str, gtd->ses->input->buf);

+ 29 - 26
src/gui.h

@@ -613,33 +613,36 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "\n"
 "\n"
 "	gui_reload;\n"
 "	gui_reload;\n"
 "\n"
 "\n"
-"	#if {$gui[cols] > 75}\n"
+"	#line verbose\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"
+"		#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"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
 "\n"
 "\n"

+ 114 - 96
src/help.c

@@ -127,20 +127,20 @@ DO_COMMAND(do_help)
 
 
 			if (HAS_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING))
 			if (HAS_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING))
 			{
 			{
-				sprintf(tmp, "%.*s\e]68;6;;%s\a\e[4m%s%s\e[24m", 15 - (int) strlen(help_table[cnt].name), "                ", help_table[cnt].name, color, help_table[cnt].name);
+				sprintf(tmp, "%.*s\e]68;6;;%s\a\e[4m%s%s\e[24m", 16 - (int) strlen(help_table[cnt].name), "                ", help_table[cnt].name, color, help_table[cnt].name);
 			}
 			}
 			else
 			else
 			{
 			{
-				sprintf(tmp, "%s%15s", color, help_table[cnt].name);
+				sprintf(tmp, "%s%16s", color, help_table[cnt].name);
 			}
 			}
 
 
-			if (strip_vt102_strlen(ses, buf) + 15 > ses->wrap)
+			if (strip_vt102_strlen(ses, buf) + 16 > ses->wrap)
 			{
 			{
 				print_lines(ses, SUB_COL, "<088>%s<088>\n", buf);
 				print_lines(ses, SUB_COL, "<088>%s<088>\n", buf);
 
 
 				*buf = 0;
 				*buf = 0;
 			}
 			}
-			cat_sprintf(buf, "%s ", tmp);
+			cat_sprintf(buf, "%s", tmp);
 		}
 		}
 
 
 		if (*buf)
 		if (*buf)
@@ -292,12 +292,6 @@ DO_COMMAND(do_help)
 	return ses;
 	return ses;
 }
 }
 
 
-
-
-/*
-	This help table is a mess, but I got better things to do - Igor
-*/
-
 struct help_type help_table[] =
 struct help_type help_table[] =
 {
 {
 	{
 	{
@@ -986,6 +980,7 @@ struct help_type help_table[] =
 		"         You can further prefix the option as following:\n"
 		"         You can further prefix the option as following:\n"
 		"\n"
 		"\n"
 		"         ASCII      will draw in ASCII mode.\n"
 		"         ASCII      will draw in ASCII mode.\n"
+		"         BALIGN     will bottom align text.\n"
 		"         BLANKED    will blank the lines and corners.\n"
 		"         BLANKED    will blank the lines and corners.\n"
 		"         BOTTOM     will draw on the bottom side if possible.\n"
 		"         BOTTOM     will draw on the bottom side if possible.\n"
 		"         BOXED      will draw a box along the square.\n"
 		"         BOXED      will draw a box along the square.\n"
@@ -1026,7 +1021,7 @@ struct help_type help_table[] =
 		"         The following types are available.\n"
 		"         The following types are available.\n"
 		"\n"
 		"\n"
 		"         <278>[HORIZONTAL] <178>BAR<278> {<MIN>;<MAX>;[COLOR]}\n"
 		"         <278>[HORIZONTAL] <178>BAR<278> {<MIN>;<MAX>;[COLOR]}\n"
-		"         <278> will draw a bar.\n"
+		"         <278> will draw a bar, use two 256 color codes for a color gradient.\n"
 		"         <278>[ASCII|UNICODE|HUGE] <178>BOX<278> {[TEXT1]} {[TEXT2]}\n"
 		"         <278>[ASCII|UNICODE|HUGE] <178>BOX<278> {[TEXT1]} {[TEXT2]}\n"
 		"         <278>  will draw a box.\n"
 		"         <278>  will draw a box.\n"
 		"         <278>[BOXED|FOREGROUND] <178>BUFFER\n"
 		"         <278>[BOXED|FOREGROUND] <178>BUFFER\n"
@@ -1071,7 +1066,7 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<178>Example<278>: #echo {The current date is %t.} {%Y-%m-%d %H:%M:%S}\n"
 		"<178>Example<278>: #echo {The current date is %t.} {%Y-%m-%d %H:%M:%S}\n"
 		"         #echo {[%38s][%-38s]} {Hello World} {Hello World}\n"
 		"         #echo {[%38s][%-38s]} {Hello World} {Hello World}\n"
-		"         #echo {{this is %s on the top row} {-1}} {printed}\n",
+		"         #echo {{this is %s on the top row} {1}} {printed}\n",
 		
 		
 		"buffer format grep showme"
 		"buffer format grep showme"
 	},
 	},
@@ -1290,6 +1285,7 @@ struct help_type help_table[] =
 		"         \\x7B  send the '{' character.\n"
 		"         \\x7B  send the '{' character.\n"
 		"         \\x7D  send the '}' character.\n"
 		"         \\x7D  send the '}' character.\n"
 		"         \\u    print a 16 bit unicode character, \\uFFFD for example.\n"
 		"         \\u    print a 16 bit unicode character, \\uFFFD for example.\n"
+		"         \\u{}  print a 8-21 bit unicode character, \\u{2AF21} for example.\n"
 		"         \\U    print a 21 bit unicode character, \\U02AF21 for example.\n"
 		"         \\U    print a 21 bit unicode character, \\U02AF21 for example.\n"
 		"         \\v    send a vertical tab\n"
 		"         \\v    send a vertical tab\n"
 		"\n"
 		"\n"
@@ -1416,6 +1412,38 @@ struct help_type help_table[] =
 		"         <178>PORT LOG MESSAGE       <278>%0 name %1 ip %2 port %3 data %4 plain data\n"
 		"         <178>PORT LOG MESSAGE       <278>%0 name %1 ip %2 port %3 data %4 plain data\n"
 		"         <178>PORT RECEIVED MESSAGE  <278>%0 name %1 ip %2 port %3 data %4 plain data\n"
 		"         <178>PORT RECEIVED MESSAGE  <278>%0 name %1 ip %2 port %3 data %4 plain data\n"
 		"\n"
 		"\n"
+		"         <128>SCAN EVENTS<278>\n"
+		"\n"
+		"         SCAN CSV HEADER        %0 all args %1 arg1 %2 arg2 .. %99 arg99\n"
+		"         SCAN CSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
+		"         SCAN TSV HEADER        %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
+		"         SCAN TSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
+		"\n"
+		"         <128>SCREEN EVENTS<278>\n"
+		"\n"
+		"         <178>SCREEN FOCUS\n"
+		"         <278>  %0 focus (0 or 1)\n"
+		"\n"
+		"         SCREEN LOCATION        %0 rows %1 cols  %2 height %3 width\n"
+		"\n"
+		"         <178>SCREEN MOUSE LOCATION\n"
+		"         <278>  %0 row  %1 col  %2 -row  %3 -col  %4 pix row  %5 pix col\n"
+		"         <278>  %6 -pix row  %7 -pix col  %8 location\n"
+		"\n"
+		"         SCREEN RESIZE          %0 rows %1 cols %2 height %3 width\n"
+		"         SCREEN SPLIT           %0 top row %1 top col %2 bot row %3 bot col\n"
+		"         SCREEN UNSPLIT         %0 top row %1 top col %2 bot row %3 bot col\n"
+		"\n"
+		"         <128>SESSION EVENTS<278>\n"
+		"\n"
+		"         SESSION ACTIVATED      %0 name\n"
+		"         SESSION CONNECTED      %0 name %1 host %2 ip %3 port\n"
+		"         SESSION CREATED        %0 name %1 host %2 ip %3 port\n"
+		"         SESSION DEACTIVATED    %0 name\n"
+		"         SESSION DISCONNECTED   %0 name %1 host %2 ip %3 port\n"
+		"         SESSION TIMED OUT      %0 name %1 host %2 ip %3 port\n"
+		"\n"
+		"\n"
 		"         <128>SYSTEM EVENTS<278>\n"
 		"         <128>SYSTEM EVENTS<278>\n"
 		"\n"
 		"\n"
 		"         DAEMON ATTACHED        %0 file %1 pid\n"
 		"         DAEMON ATTACHED        %0 file %1 pid\n"
@@ -1431,7 +1459,7 @@ struct help_type help_table[] =
 		"         SYSTEM CRASH           %0 message\n"
 		"         SYSTEM CRASH           %0 message\n"
 		"         SYSTEM ERROR           %0 name %1 system msg %2 error %3 error msg\n"
 		"         SYSTEM ERROR           %0 name %1 system msg %2 error %3 error msg\n"
 		"         UNKNOWN COMMAND        %0 raw text\n"
 		"         UNKNOWN COMMAND        %0 raw text\n"
-
+		"         SIGUSR                 %0 signal\n"
 		"\n"
 		"\n"
 		"         <128>TELNET EVENTS\n"
 		"         <128>TELNET EVENTS\n"
 		"\n"
 		"\n"
@@ -1454,37 +1482,7 @@ struct help_type help_table[] =
 		"         <278>  %0 year  %1 month  %2 day of week  %3 day of month  %4 hour\n"
 		"         <278>  %0 year  %1 month  %2 day of week  %3 day of month  %4 hour\n"
 		"         <278>  %5 minute  %6 second\n"
 		"         <278>  %5 minute  %6 second\n"
 		"\n"
 		"\n"
-		"         <128>SCAN EVENTS<278>\n"
-		"\n"
-		"         SCAN CSV HEADER        %0 all args %1 arg1 %2 arg2 .. %99 arg99\n"
-		"         SCAN CSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
-		"         SCAN TSV HEADER        %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
-		"         SCAN TSV LINE          %0 all args %1 arg1 %2 arg3 .. %99 arg99\n"
-		"\n"
-		"         <128>SCREEN EVENTS<278>\n"
-		"\n"
-		"         <178>SCREEN FOCUS\n"
-		"         <278>  %0 focus (0 or 1)\n"
-		"\n"
-		"         SCREEN LOCATION        %0 rows %1 cols  %2 height %3 width\n"
-		"\n"
-		"         <178>SCREEN MOUSE LOCATION\n"
-		"         <278>  %0 row  %1 col  %2 -row  %3 -col  %4 pix row  %5 pix col\n"
-		"         <278>  %6 -pix row  %7 -pix col  %8 location\n"
-		"\n"
-		"         SCREEN RESIZE          %0 rows %1 cols %2 height %3 width\n"
-		"         SCREEN SPLIT           %0 top row %1 top col %2 bot row %3 bot col\n"
-		"         SCREEN UNSPLIT         %0 top row %1 top col %2 bot row %3 bot col\n"
-		"\n"
-		"         <128>SESSION EVENTS<278>\n"
-		"\n"
-		"         SESSION ACTIVATED      %0 name\n"
-		"         SESSION CONNECTED      %0 name %1 host %2 ip %3 port\n"
-		"         SESSION CREATED        %0 name %1 host %2 ip %3 port\n"
-		"         SESSION DEACTIVATED    %0 name\n"
-		"         SESSION DISCONNECTED   %0 name %1 host %2 ip %3 port\n"
-		"         SESSION TIMED OUT      %0 name %1 host %2 ip %3 port\n"
-		"\n"
+
 		"         <128>VARIABLE EVENTS<278>\n"
 		"         <128>VARIABLE EVENTS<278>\n"
 		"\n"
 		"\n"
 		"         VARIABLE UPDATE <VAR>  %0 name %1 new value %2 path\n"
 		"         VARIABLE UPDATE <VAR>  %0 name %1 new value %2 path\n"
@@ -1551,7 +1549,6 @@ struct help_type help_table[] =
 		"                                         optional {{string}{width}} syntax\n"
 		"                                         optional {{string}{width}} syntax\n"
 		"         #format {test} {%x}      {hex}  print corresponding charset character\n"
 		"         #format {test} {%x}      {hex}  print corresponding charset character\n"
 		"         #format {test} {%A}     {char}  store corresponding character value\n"
 		"         #format {test} {%A}     {char}  store corresponding character value\n"
-		"         #format {test} {%C}   {number}  store number in chronological notation\n"
 		"         #format {test} {%D}      {hex}  convert hex to decimal in {test}\n"
 		"         #format {test} {%D}      {hex}  convert hex to decimal in {test}\n"
 		"         #format {hash} {%H}   {string}  store a 64 bit string hash in {hash}\n"
 		"         #format {hash} {%H}   {string}  store a 64 bit string hash in {hash}\n"
 		"         #format {test} {%L}   {string}  store the string length in {test}\n"
 		"         #format {test} {%L}   {string}  store the string length in {test}\n"
@@ -1762,23 +1759,28 @@ struct help_type help_table[] =
 	{
 	{
 		"IF",
 		"IF",
 		TOKEN_TYPE_COMMAND,
 		TOKEN_TYPE_COMMAND,
-		"<178>Command<278>: #if <178>{<278>conditional<178>} {<278>commands if true<178>} {<278>commands if false<178>}<278>\n"
+		"<178>Command<278>: #if <178>{<278>conditional<178>} {<278>commands if true<178>}<278>\n"
 		"\n"
 		"\n"
-		"         The 'if' command is one of the most powerful commands added since\n"
-		"         TINTIN III. It works similar to an 'if' statement in other languages,\n"
-		"         and is strictly based on the way C handles its conditional statements.\n"
-		"         When an 'if' command is encountered, the conditional statement is\n"
+		"         The #if command is one of the most powerful commands added since\n"
+		"         TINTIN III. It works similar to an if statement in other languages,\n"
+		"         and is based on the way C handles its conditional statements.\n"
+		"         When an #if command is encountered, the conditional statement is\n"
 		"         evaluated, and if TRUE (any non-zero result) the commands are executed.\n"
 		"         evaluated, and if TRUE (any non-zero result) the commands are executed.\n"
 		"\n"
 		"\n"
-		"         The 'if' statement is only evaluated if it is read, so you must nest\n"
-		"         the 'if' statement inside another statement (most likely an 'action'\n"
+		"         The if statement is only evaluated if it is read, so you must nest\n"
+		"         the if statement inside another statement (most likely an #action\n"
 		"         command). The conditional is evaluated exactly the same as in the\n"
 		"         command). The conditional is evaluated exactly the same as in the\n"
-		"         'math' command only instead of storing the result, the result is used\n"
+		"         #math command, only instead of storing the result, the result is used\n"
 		"         to determine whether to execute the commands.\n"
 		"         to determine whether to execute the commands.\n"
 		"\n"
 		"\n"
-		"<178>Example<278>: #action {%0 gives you %1 gold coins.} {#if {%1>5000} {thank %0}}\n"
+		"         To handle the case where an if statement is false it can be followed\n"
+		"         by the #else command.\n"
+		"\n"
+		"<178>Example<278>: #action {%0 gives you %1 gold coins.} {#if {%1 > 5000} {thank %0}}\n"
 		"         If someone gives you more than 5000 coins, thank them.\n"
 		"         If someone gives you more than 5000 coins, thank them.\n"
 		"\n"
 		"\n"
+		"<178>Example<278>: #alias {k} {#if {\"%0\" == \"\"} {kill $target};#else {kill %0}}\n"
+		"\n"
 		"<178>Comment<278>: See '#help math', for more information.\n",
 		"<178>Comment<278>: See '#help math', for more information.\n",
 		
 		
 		"case default else elseif switch regexp"
 		"case default else elseif switch regexp"
@@ -2069,12 +2071,16 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"         By providing the name of a list and the LIST option it shows all\n"
 		"         By providing the name of a list and the LIST option it shows all\n"
 		"         triggers/variables associated with that list. With the SAVE option\n"
 		"         triggers/variables associated with that list. With the SAVE option\n"
-		"         This data is written to the info variable.\n"
+		"         this data is written to the info variable.\n"
 		"\n"
 		"\n"
 		"         #info cpu will show information about tintin's cpu usage.\n"
 		"         #info cpu will show information about tintin's cpu usage.\n"
+		"         #info environ will show the environment variables.\n"
+		"         #info input will show information about the input line.\n"
 		"         #info mccp will show information about data compression.\n"
 		"         #info mccp will show information about data compression.\n"
+		"         #info memory will show information about the memory stack.\n"
 		"         #info stack will show the low level debugging stack.\n"
 		"         #info stack will show the low level debugging stack.\n"
-		"         #info session will show some session information.\n"
+		"         #info session will show information on the session.\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 unicode will show information on the provided character.\n",
 		"         #info unicode will show information on the provided character.\n",
 
 
@@ -2632,7 +2638,8 @@ struct help_type help_table[] =
 		"         <278>  Sets displaying center of the map viewer, default is 0 0 0.\n"
 		"         <278>  Sets displaying center of the map viewer, default is 0 0 0.\n"
 		"\n"
 		"\n"
 		"         <178>#map color <field> [value]\n"
 		"         <178>#map color <field> [value]\n"
-		"         <278>  Sets the map color for the given color field.\n"
+		"         <278>  Sets the map color for the given color field. Use #map color reset\n"
+		"         <278>  to restore colors to default.\n"
 		"\n"
 		"\n"
 		"         <178>#map create <size>\n"
 		"         <178>#map create <size>\n"
 		"         <278>  Creates a new map and room 1. The default size is 50000 rooms.\n"
 		"         <278>  Creates a new map and room 1. The default size is 50000 rooms.\n"
@@ -3043,31 +3050,33 @@ struct help_type help_table[] =
 		"         ------------------------------------------------\n"
 		"         ------------------------------------------------\n"
 		"         !               0            logical not\n"
 		"         !               0            logical not\n"
 		"         ~               0            bitwise not\n"
 		"         ~               0            bitwise not\n"
-		"         *               1            integer multiply\n"
-		"         **              1            integer power\n"
-		"         /               1            integer divide\n"
-		"         //              1            integer sqrt // 2 or cbrt // 3\n"
-		"         %               1            integer modulo\n"
-		"         d               1            integer random dice roll\n"
-		"         +               2            integer addition\n"
-		"         -               2            integer subtraction\n"
-		"         <<              3            bitwise shift\n"
-		"         >>              3            bitwise shift\n"
-		"         ..              3            bitwise ellipsis\n"
-		"         >               4            logical greater than\n"
-		"         >=              4            logical greater than or equal\n"
-		"         <               4            logical less than\n"
-		"         <=              4            logical less than or equal\n"
-		"         ==              5            logical equal (can use regex)\n"
-		"         ===             5            logical equal (never regex)\n"
-		"         !=              5            logical not equal (can use regex)\n"
-		"         !==             5            logical not equal (never regex)\n"
-		"          &              6            bitwise and\n"
-		"          ^              7            bitwise xor\n"
-		"          |              8            bitwise or\n"
-		"         &&              9            logical and\n"
-		"         ^^             10            logical xor\n"
-		"         ||             11            logical or\n"
+		"         d               1            integer random dice\n"
+		"         *               2            integer multiply\n"
+		"         **              2            integer power\n"
+		"         /               2            integer divide\n"
+		"         //              2            integer sqrt // 2 or cbrt // 3\n"
+		"         %               2            integer modulo\n"
+		"         +               3            integer addition\n"
+		"         -               3            integer subtraction\n"
+		"         <<              4            bitwise shift\n"
+		"         >>              4            bitwise shift\n"
+		"         ..              4            bitwise ellipsis\n"
+		"         >               5            logical greater than\n"
+		"         >=              5            logical greater than or equal\n"
+		"         <               5            logical less than\n"
+		"         <=              5            logical less than or equal\n"
+		"         ==              6            logical equal (can use regex)\n"
+		"         ===             6            logical equal (never regex)\n"
+		"         !=              6            logical not equal (can use regex)\n"
+		"         !==             6            logical not equal (never regex)\n"
+		"          &              7            bitwise and\n"
+		"          ^              8            bitwise xor\n"
+		"          |              9            bitwise or\n"
+		"         &&             10            logical and\n"
+		"         ^^             11            logical xor\n"
+		"         ||             12            logical or\n"
+		"         ?              13            logical ternary if (unfinished code)\n"
+		"         :              14            logical ternary else \n"
 		"\n"
 		"\n"
 		"         True is any non-zero number, and False is zero.  Parentheses () have\n"
 		"         True is any non-zero number, and False is zero.  Parentheses () have\n"
 		"         highest precedence, so inside the () is always evaluated first.\n"
 		"         highest precedence, so inside the () is always evaluated first.\n"
@@ -3282,7 +3291,7 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"         This would make you start a reply when clicking on a tell.\n"
 		"         This would make you start a reply when clicking on a tell.\n"
 		"\n"
 		"\n"
-		"Website: https://tintin.mudhalla.net/protocols/mslp\n",
+		"<178>Website<278>: https://tintin.mudhalla.net/protocols/mslp\n",
 
 
 		"event port"
 		"event port"
 	},
 	},
@@ -3633,7 +3642,7 @@ struct help_type help_table[] =
 		"         Prompt is a feature for split window mode, which will capture a line\n"
 		"         Prompt is a feature for split window mode, which will capture a line\n"
 		"         received from the server and display it on the status bar of your\n"
 		"         received from the server and display it on the status bar of your\n"
 		"         split screen terminal. You would define <text> and <new text> the\n"
 		"         split screen terminal. You would define <text> and <new text> the\n"
-		"         same way as with a substitution.\n"
+		"         same way as you would with #substitute.\n"
 		"\n"
 		"\n"
 		"         The row number is optional and useful if you use a non standard split\n"
 		"         The row number is optional and useful if you use a non standard split\n"
 		"         mode. A positive row number draws #row lines from the top while a\n"
 		"         mode. A positive row number draws #row lines from the top while a\n"
@@ -3644,8 +3653,8 @@ struct help_type help_table[] =
 		"         The col number is optional and can be used to set the column index.\n"
 		"         The col number is optional and can be used to set the column index.\n"
 		"         A positive col number draws the given number of columns from the left,\n"
 		"         A positive col number draws the given number of columns from the left,\n"
 		"         while a negative col number draws from the right. If you leave the\n"
 		"         while a negative col number draws from the right. If you leave the\n"
-		"         column argument empty tintin will clear the row before printing at\n"
-		"         the start of the row.\n"
+		"         col number empty tintin will clear the row before printing at the\n"
+		"         start of the row.\n"
 		"\n"
 		"\n"
 		"         The #show command takes a row and col argument as well so it's also\n"
 		"         The #show command takes a row and col argument as well so it's also\n"
 		"         possible to place text on your split lines using #show.\n"
 		"         possible to place text on your split lines using #show.\n"
@@ -3701,19 +3710,22 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"         Of the following the (lazy) match is available at %1-%99 + 1\n"
 		"         Of the following the (lazy) match is available at %1-%99 + 1\n"
 		"\n"
 		"\n"
-		"      %a match zero to any number of characters including newlines.\n"
-		"      %A match zero to any number of newlines.\n"
 		"      %d match zero to any number of digits.\n"
 		"      %d match zero to any number of digits.\n"
 		"      %D match zero to any number of non digits.\n"
 		"      %D match zero to any number of non digits.\n"
-		"      %p match zero to any number of printable characters.\n"
-		"      %P match zero to any number of non printable characters.\n"
 		"      %s match zero to any number of spaces.\n"
 		"      %s match zero to any number of spaces.\n"
 		"      %S match zero to any number of non spaces.\n"
 		"      %S match zero to any number of non spaces.\n"
-		"      %u match zero to any number of unicode characters.\n"
-		"      %U match zero to any number of non unicode characters.\n"
 		"      %w match zero to any number of word characters.\n"
 		"      %w match zero to any number of word characters.\n"
 		"      %W match zero to any number of non word characters.\n"
 		"      %W match zero to any number of non word characters.\n"
 		"\n"
 		"\n"
+		"      Experimental (subject to change) matches are:\n"
+		"\n"
+		"      %a match zero to any number of characters including newlines.\n"
+		"      %A match zero to any number of newlines.\n"
+		"      %p match zero to any number of printable characters.\n"
+		"      %P match zero to any number of non printable characters.\n"
+		"      %u match zero to any number of unicode characters.\n"
+		"      %U match zero to any number of non unicode characters.\n"
+		"\n"
 		"      If you want to match 1 digit use %+1d, if you want to match between 3\n"
 		"      If you want to match 1 digit use %+1d, if you want to match between 3\n"
 		"      and 5 spaces use %+3..5s, if you want to match 0 or more word\n"
 		"      and 5 spaces use %+3..5s, if you want to match 0 or more word\n"
 		"      characters use %+0..w, etc.\n"
 		"      characters use %+0..w, etc.\n"
@@ -3735,7 +3747,7 @@ struct help_type help_table[] =
 		"\n"
 		"\n"
 		"<178>Comment<278>: Like an alias or function #regex has its own scope.\n",
 		"<178>Comment<278>: Like an alias or function #regex has its own scope.\n",
 
 
-		"replace"
+		"pcre replace"
 	},
 	},
 
 
 	{
 	{
@@ -3954,7 +3966,7 @@ struct help_type help_table[] =
 		"         treats the generated echos as commands if no variable is provided.\n"
 		"         treats the generated echos as commands if no variable is provided.\n"
 		"\n"
 		"\n"
 		"         This is useful for running php, perl, ruby, and python scripts. You\n"
 		"         This is useful for running php, perl, ruby, and python scripts. You\n"
-		"         can run these scrips either from file or from within tintin if the\n"
+		"         can run these scripts either from file or from within tintin if the\n"
 		"         scripting language allows this.\n"
 		"         scripting language allows this.\n"
 		"\n"
 		"\n"
 		"         If you provide a variable the output of the script is stored as a list.\n"
 		"         If you provide a variable the output of the script is stored as a list.\n"
@@ -4067,14 +4079,19 @@ struct help_type help_table[] =
 	{
 	{
 		"SNOOP",
 		"SNOOP",
 		TOKEN_TYPE_COMMAND,
 		TOKEN_TYPE_COMMAND,
-		"<178>Command<278>: #snoop <178>{<278>session name<178>} <178>{<278>on<178>|<278>off<178>}<278>\n"
+		"<178>Command<278>: #snoop <178>{<278>session name<178>} <178>{<278>on<178>|<278>off<178>|<278>scroll<178>}<278>\n"
 		"\n"
 		"\n"
 		"         If there are multiple sessions active, this command allows you to\n"
 		"         If there are multiple sessions active, this command allows you to\n"
 		"         monitor what is going on in the sessions that are not currently active.\n"
 		"         monitor what is going on in the sessions that are not currently active.\n"
 		"         The line of text from other sessions will be prefixed by the session's\n"
 		"         The line of text from other sessions will be prefixed by the session's\n"
 		"         name.\n"
 		"         name.\n"
 		"\n"
 		"\n"
-		"         You can toggle off snoop mode by executing #snoop a second time.\n",
+		"         You can toggle off snoop mode by executing #snoop a second time.\n"
+		"\n"
+		"         By using the scroll argument you will snoop the session's scroll\n"
+		"         region which will overwrite the display of whichever session is active.\n"
+		"         You can change the size and location of a session's scroll region by\n"
+		"         using the #split and #screen scrollregion commands.\n",
 
 
 		"all port run session sessionname ssl zap"
 		"all port run session sessionname ssl zap"
 	},
 	},
@@ -4483,3 +4500,4 @@ struct help_type help_table[] =
 		""
 		""
 	}
 	}
 };
 };
+

+ 5 - 5
src/history.c

@@ -119,7 +119,7 @@ struct session *repeat_history(struct session *ses, char *line)
 
 
 DO_HISTORY(history_character)
 DO_HISTORY(history_character)
 {
 {
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 
 
 	gtd->repeat_char = *arg1;
 	gtd->repeat_char = *arg1;
 
 
@@ -217,7 +217,7 @@ DO_HISTORY(history_get)
 
 
 DO_HISTORY(history_list)
 DO_HISTORY(history_list)
 {
 {
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
 
 
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
@@ -235,7 +235,7 @@ DO_HISTORY(history_read)
 	struct listroot *root = ses->list[LIST_HISTORY];
 	struct listroot *root = ses->list[LIST_HISTORY];
 	FILE *file;
 	FILE *file;
 
 
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 
 
 	file = fopen(arg1, "r");
 	file = fopen(arg1, "r");
 
 
@@ -269,7 +269,7 @@ DO_HISTORY(history_read)
 
 
 DO_HISTORY(history_size)
 DO_HISTORY(history_size)
 {
 {
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 
 
 	if (atoi(arg1) < 1 || atoi(arg1) > 100000)
 	if (atoi(arg1) < 1 || atoi(arg1) > 100000)
 	{
 	{
@@ -288,7 +288,7 @@ DO_HISTORY(history_write)
 	FILE *file;
 	FILE *file;
 	int i;
 	int i;
 
 
-	arg = get_arg_in_braces(ses, arg, arg1, GET_ONE);
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 
 
 	file = fopen(arg1, "w");
 	file = fopen(arg1, "w");
 
 

+ 33 - 5
src/main.c

@@ -63,14 +63,22 @@ void ttou_handler(int signal)
 	syserr_printf(gtd->ses, "ttou_handler");
 	syserr_printf(gtd->ses, "ttou_handler");
 }
 }
 
 
+void usr_handler(int signal)
+{
+	check_all_events(gts, EVENT_FLAG_SYSTEM, 0, 1, "SIGUSR", signal == SIGUSR1 ? "1" : "2");
+}
+
 /*
 /*
 	when the screen size changes, take note of it
 	when the screen size changes, take note of it
 */
 */
 
 
 void winch_handler(int signal)
 void winch_handler(int signal)
 {
 {
-	struct session *ses;
+	SET_BIT(gtd->flags, TINTIN_FLAG_WINCHUPDATE);
 
 
+	gtd->time_session = gtd->time;
+/*
+	struct session *ses;
 	init_terminal_size(gts);
 	init_terminal_size(gts);
 
 
 	for (ses = gts->next ; ses ; ses = ses->next)
 	for (ses = gts->next ; ses ; ses = ses->next)
@@ -84,6 +92,7 @@ void winch_handler(int signal)
 	}
 	}
 
 
 	winch_daemon();
 	winch_daemon();
+*/
 }
 }
 
 
 
 
@@ -99,7 +108,7 @@ void child_handler(int signal)
 
 
 //	syserr_fatal(signal, "child_handler");
 //	syserr_fatal(signal, "child_handler");
 }
 }
-
+/*
 void interrupt_handler(int signal)
 void interrupt_handler(int signal)
 {
 {
 	if (gtd->ses->connect_retry > utime())
 	if (gtd->ses->connect_retry > utime())
@@ -108,7 +117,7 @@ void interrupt_handler(int signal)
 	}
 	}
 	else if (HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_SGA) && !HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO))
 	else if (HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_SGA) && !HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO))
 	{
 	{
-		socket_printf(gtd->ses, 1, "%c", 4);
+		socket_printf(gtd->ses, 1, "\004");
 	}
 	}
 	else if (gtd->attach_sock)
 	else if (gtd->attach_sock)
 	{
 	{
@@ -121,7 +130,7 @@ void interrupt_handler(int signal)
 		cursor_delete_or_exit(gtd->ses, "");
 		cursor_delete_or_exit(gtd->ses, "");
 	}
 	}
 }
 }
-
+*/
 void suspend_handler(int signal)
 void suspend_handler(int signal)
 {
 {
 	show_message(gtd->ses, LIST_COMMAND, "#SIGNAL: SIGTSTP");
 	show_message(gtd->ses, LIST_COMMAND, "#SIGNAL: SIGTSTP");
@@ -219,6 +228,16 @@ int main(int argc, char **argv)
 		syserr_fatal(-1, "signal SIGTTOU");
 		syserr_fatal(-1, "signal SIGTTOU");
 	}
 	}
 */
 */
+	if (signal(SIGUSR1, usr_handler) == BADSIG)
+	{
+		syserr_fatal(-1, "signal SIGUSR1");
+	}
+
+	if (signal(SIGUSR2, usr_handler) == BADSIG)
+	{
+		syserr_fatal(-1, "signal SIGUSR1");
+	}
+
 	if (signal(SIGWINCH, winch_handler) == BADSIG)
 	if (signal(SIGWINCH, winch_handler) == BADSIG)
 	{
 	{
 		syserr_fatal(-1, "signal SIGWINCH");
 		syserr_fatal(-1, "signal SIGWINCH");
@@ -533,8 +552,8 @@ void init_tintin(int greeting)
 
 
 	gtd->banner_list    = init_list(gts, LIST_CONFIG, 32);
 	gtd->banner_list    = init_list(gts, LIST_CONFIG, 32);
 
 
-	gts->split          = calloc(1, sizeof(struct split_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->input          = calloc(1, sizeof(struct input_data));
 	gts->input          = calloc(1, sizeof(struct input_data));
 
 
 	init_local(gts);
 	init_local(gts);
@@ -787,6 +806,15 @@ void syserr_fatal(int signal, char *msg)
 		exit(-1);
 		exit(-1);
 	}
 	}
 
 
+	if (signal == SIGHUP)
+	{
+		crashed--;
+
+		check_all_events(gts, SUB_SEC|EVENT_FLAG_SYSTEM, 0, 0, "SIGHUB");
+
+		crashed++;
+	}
+
 	if (signal <= 0)
 	if (signal <= 0)
 	{
 	{
 		sprintf(errstr, "(error %d: %s", errno, strerror(errno));
 		sprintf(errstr, "(error %d: %s", errno, strerror(errno));

+ 44 - 17
src/mapper.c

@@ -3569,16 +3569,23 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 
 
 	arg = sub_arg_in_braces(ses, tmp, buf, GET_ALL, SUB_VAR|SUB_FUN); // name
 	arg = sub_arg_in_braces(ses, tmp, buf, GET_ALL, SUB_VAR|SUB_FUN); // name
 
 
+	ses->map->search->min = ses->map->search->max = ses->map->search->vnum = 0;
+
 	if (is_math(ses, buf))
 	if (is_math(ses, buf))
 	{
 	{
-		ses->map->search->vnum = (int) get_number(ses, buf);
-	}
-	else
-	{
-		ses->map->search->vnum = 0;
+		if (strstr(buf, ".."))
+		{
+			get_ellipsis(ses, ses->map->size, buf, &ses->map->search->min, &ses->map->search->max);
+			ses->map->search->min++;
+			ses->map->search->max++;
+		}
+		else
+		{
+			ses->map->search->vnum = (int) get_number(ses, buf);
+		}
 	}
 	}
 
 
-	if (ses->map->search->vnum)
+	if (ses->map->search->vnum || ses->map->search->min || ses->map->search->max)
 	{
 	{
 		pop_call();
 		pop_call();
 		return;
 		return;
@@ -3859,6 +3866,11 @@ int match_room(struct session *ses, int vnum, struct search_data *search)
 		return room->vnum == search->vnum;
 		return room->vnum == search->vnum;
 	}
 	}
 
 
+	if (search->min || search->max)
+	{
+		return room->vnum >= search->min && room->vnum <= search->max;
+	}
+
 	if (search->id)
 	if (search->id)
 	{
 	{
 		return !strcmp(room->id, search->id);
 		return !strcmp(room->id, search->id);
@@ -3995,7 +4007,9 @@ int find_location(struct session *ses, char *arg)
 		return find_exit(ses, ses->map->in_room, arg)->vnum;
 		return find_exit(ses, ses->map->in_room, arg)->vnum;
 	}
 	}
 
 
-	if (is_math(ses, arg))
+	sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
+
+	if (is_math(ses, arg1))
 	{
 	{
 		arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
@@ -4223,8 +4237,11 @@ int check_global(struct session *ses, int room)
 
 
 int tunnel_void(struct session *ses, int from, int room, int dir)
 int tunnel_void(struct session *ses, int from, int room, int dir)
 {
 {
+	push_call("tunnel_void(%p,%d,%d,%d)",ses,from,room,dir);
+
 	if (!HAS_BIT(ses->map->room_list[room]->flags, ROOM_FLAG_VOID))
 	if (!HAS_BIT(ses->map->room_list[room]->flags, ROOM_FLAG_VOID))
 	{
 	{
+		pop_call();
 		return room;
 		return room;
 	}
 	}
 
 
@@ -4234,19 +4251,28 @@ int tunnel_void(struct session *ses, int from, int room, int dir)
 
 
 		if (exit)
 		if (exit)
 		{
 		{
+			pop_call();
 			return tunnel_void(ses, room, exit->vnum, exit->dir);
 			return tunnel_void(ses, room, exit->vnum, exit->dir);
 		}
 		}
+		pop_call();
 		return room;
 		return room;
 	}
 	}
 
 
 	if (ses->map->room_list[room]->f_exit->vnum != from)
 	if (ses->map->room_list[room]->f_exit->vnum != from)
 	{
 	{
+		pop_call();
 		return tunnel_void(ses, room, ses->map->room_list[room]->f_exit->vnum, ses->map->room_list[room]->f_exit->dir);
 		return tunnel_void(ses, room, ses->map->room_list[room]->f_exit->vnum, ses->map->room_list[room]->f_exit->dir);
 	}
 	}
-	else
+
+	if (ses->map->room_list[room]->l_exit->vnum != from)
 	{
 	{
+		pop_call();
 		return tunnel_void(ses, room, ses->map->room_list[room]->l_exit->vnum, ses->map->room_list[room]->l_exit->dir);
 		return tunnel_void(ses, room, ses->map->room_list[room]->l_exit->vnum, ses->map->room_list[room]->l_exit->dir);
 	}
 	}
+	show_error(ses, LIST_COMMAND, "\e[1;31mtunnel_void(%p,%d,%d,%d) NO VALID EXITS FOUND.",ses,from,room,dir);
+
+	pop_call();
+	return room;
 }
 }
 
 
 // shortest_path() utilities
 // shortest_path() utilities
@@ -4946,8 +4972,6 @@ void map_mouse_handler(struct session *ses, char *arg1, char *arg2, int row, int
 				  "w", "RL", "RC", "RR",  "e", "e",
 				  "w", "RL", "RC", "RR",  "e", "e",
 				 "sw",  "d",  "s", "16", "se", "18" };
 				 "sw",  "d",  "s", "16", "se", "18" };
 
 
-//		tintin_printf2(ses, "\e[1;32mdebug: y=%d x=%d mod(y)=%d mod(x)=%d", y / 3, y / 6, y % 3, x % 6);
-
 		strcpy(exit, grid[URANGE(0, y % 3 * 6 + x % 6, 17)]);
 		strcpy(exit, grid[URANGE(0, y % 3 * 6 + x % 6, 17)]);
 
 
 		y /= 3;
 		y /= 3;
@@ -4986,8 +5010,6 @@ void map_mouse_handler(struct session *ses, char *arg1, char *arg2, int row, int
 				break;
 				break;
 		}
 		}
 
 
-//		tintin_printf2(ses, "\e[1;32mdebug: y=%d x=%d y_mod=%d x_mod=%d y+x=%d y=%d x=%d", y, x, y_mod, x_mod, 5*y_mod+x_mod, y, x);
-
 		max_y = 2 + (rows + 2) / 2;
 		max_y = 2 + (rows + 2) / 2;
 		max_x = 2 + (cols + 4) / 5;
 		max_x = 2 + (cols + 4) / 5;
 	}
 	}
@@ -5030,7 +5052,7 @@ void map_mouse_handler(struct session *ses, char *arg1, char *arg2, int row, int
 
 
 	if (arg1 && arg2)
 	if (arg1 && arg2)
 	{
 	{
-		check_all_events(ses, EVENT_FLAG_MAP, 2, 6, "MAP REGION %s %s", arg1, arg2, ntos(row), ntos(col), ntos(rev_row), ntos(rev_col), ntos(vnum), exit);
+		check_all_events(ses, EVENT_FLAG_MOUSE, 2, 6, "MAP REGION %s %s", arg1, arg2, ntos(row), ntos(col), ntos(rev_row), ntos(rev_col), ntos(vnum), exit);
 	}
 	}
 
 
 	if (vnum)
 	if (vnum)
@@ -5080,6 +5102,13 @@ DO_MAP(map_at)
 	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_NONE);
 	arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_NONE);
 
 
+	if (ses->map->at_room)
+	{
+		show_error(ses, LIST_COMMAND, "#MAP AT: Nested #map at call from room {%d}.", ses->map->in_room);
+
+		return;
+	}
+
 	new_room = find_room(ses, arg1);
 	new_room = find_room(ses, arg1);
 
 
 	ses->map->at_room = ses->map->in_room;
 	ses->map->at_room = ses->map->in_room;
@@ -5095,6 +5124,8 @@ DO_MAP(map_at)
 		{
 		{
 			show_message(ses, LIST_COMMAND, "#MAP AT: Couldn't find room or exit {%s}.", arg1);
 			show_message(ses, LIST_COMMAND, "#MAP AT: Couldn't find room or exit {%s}.", arg1);
 
 
+			ses->map->at_room = 0;
+
 			return;
 			return;
 		}
 		}
 	}
 	}
@@ -7216,12 +7247,8 @@ DO_MAP(map_move)
 {
 {
 	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);
 
 
-//	tintin_printf2(ses, "debug: %s vs %s", arg, arg1);
-
 	arg = substitute_speedwalk(ses, arg1, arg2);
 	arg = substitute_speedwalk(ses, arg1, arg2);
 
 
-//	tintin_printf2(ses, "debug: %s vs %s", arg, arg2);
-
 	ses->map->nofollow++;
 	ses->map->nofollow++;
 
 
 	while (*arg)
 	while (*arg)

Fișier diff suprimat deoarece este prea mare
+ 377 - 347
src/math.c


+ 1 - 12
src/misc.c

@@ -278,22 +278,11 @@ struct interval_type cp949_to_unicode_table[] =
 
 
 DO_COMMAND(do_test)
 DO_COMMAND(do_test)
 {
 {
-	int i;
-
 	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);
 
 
 	if (!strcmp(arg1, "bla"))
 	if (!strcmp(arg1, "bla"))
 	{
 	{
-		int size = sizeof(cp949_to_unicode_table) / sizeof(struct interval_type);
-
-		printf("size: %d\n", size);
-
-		for (i = 0 ; i < size ; i++)
-		{
-			execute(ses, "#variable keys[%d] %d", cp949_to_unicode_table[i].head, cp949_to_unicode_table[i].tail);
-//			command(ses, do_line, "log cp949_to_unicode_keys %d,", cp949_to_unicode_table[i].head);
-//			command(ses, do_line, "log cp949_to_unicode_vals %d,", cp949_to_unicode_table[i].tail);
-		}
+		printf("%d", ~1 + 2);
 	}
 	}
 
 
 	if (!strcmp(arg1, "rain"))
 	if (!strcmp(arg1, "rain"))

+ 16 - 4
src/nest.c

@@ -326,7 +326,8 @@ int get_nest_size(struct listroot *root, char *variable)
 
 
 					if (root->used)
 					if (root->used)
 					{
 					{
-						range = get_ellipsis(root, name, &min, &max);
+						range = get_ellipsis(root->ses, root->used, name, &min, &max);
+
 
 
 						return range + 1;
 						return range + 1;
 					}
 					}
@@ -407,7 +408,7 @@ int get_nest_size_index(struct listroot *root, char *variable, char **result)
 
 
 					if (root->used)
 					if (root->used)
 					{
 					{
-						range = get_ellipsis(root, name, &min, &max);
+						range = get_ellipsis(root->ses, root->used, name, &min, &max);
 
 
 						return range + 1;
 						return range + 1;
 					}
 					}
@@ -493,7 +494,9 @@ int get_nest_size_key(struct listroot *root, char *variable, char **result)
 
 
 					if (root->used)
 					if (root->used)
 					{
 					{
-						range = get_ellipsis(root, name, &min, &max);
+						range = get_ellipsis(root->ses, root->used, name, &min, &max);
+
+//						tintin_printf2(root->ses, "debug: %d %d %d\n", min, max, range);
 
 
 						if (min < max)
 						if (min < max)
 						{
 						{
@@ -598,7 +601,7 @@ int get_nest_size_val(struct listroot *root, char *variable, char **result)
 
 
 					if (root->used)
 					if (root->used)
 					{
 					{
-						range = get_ellipsis(root, name, &min, &max);
+						range = get_ellipsis(root->ses, root->used, name, &min, &max);
 
 
 						if (min < max)
 						if (min < max)
 						{
 						{
@@ -974,7 +977,10 @@ struct listnode *set_nest_node_ses(struct session *ses, char *arg1, char *format
 
 
 	if (HAS_BIT(root->ses->event_flags, EVENT_FLAG_VARIABLE))
 	if (HAS_BIT(root->ses->event_flags, EVENT_FLAG_VARIABLE))
 	{
 	{
+		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);
 
 
@@ -1063,7 +1069,10 @@ struct listnode *add_nest_node_ses(struct session *ses, char *arg1, char *format
 
 
 	if (HAS_BIT(root->ses->event_flags, EVENT_FLAG_VARIABLE))
 	if (HAS_BIT(root->ses->event_flags, EVENT_FLAG_VARIABLE))
 	{
 	{
+		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);
 
 
@@ -1147,7 +1156,10 @@ struct listnode *set_nest_node(struct listroot *root, char *arg1, char *format,
 
 
 	if (HAS_BIT(root->ses->event_flags, EVENT_FLAG_VARIABLE))
 	if (HAS_BIT(root->ses->event_flags, EVENT_FLAG_VARIABLE))
 	{
 	{
+		arg = get_arg_to_brackets(root->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 - 1
src/port.c

@@ -74,7 +74,7 @@ DO_COMMAND(do_port)
 
 
 		arg = sub_arg_in_braces(ses, arg, arg2, port_table[cnt].rval, SUB_VAR|SUB_FUN);
 		arg = sub_arg_in_braces(ses, arg, arg2, port_table[cnt].rval, SUB_VAR|SUB_FUN);
 
 
-		ses = port_table[cnt].fun(ses, arg1, arg2, arg);
+		ses = port_table[cnt].fun(ses, arg, arg1, arg2);
 
 
 		return ses;
 		return ses;
 	}
 	}

+ 3 - 3
src/regex.c

@@ -308,10 +308,10 @@ int get_regex_range(char *in, char *out, int *var, int *arg)
 				pto += sprintf(pto, "([\\x00-\\x7F\\xFF]");
 				pto += sprintf(pto, "([\\x00-\\x7F\\xFF]");
 				break;
 				break;
 			case 'w':
 			case 'w':
-				pto += sprintf(pto, "([a-zA-Z]");
+				pto += sprintf(pto, "([a-zA-Z0-9_]");
 				break;
 				break;
 			case 'W':
 			case 'W':
-				pto += sprintf(pto, "([^a-zA-Z]");
+				pto += sprintf(pto, "([^a-zA-Z0-9_]");
 				break;
 				break;
 
 
 			default:
 			default:
@@ -1230,7 +1230,7 @@ void tintin_macro_compile(char *input, char *output)
 					case 'U':
 					case 'U':
 						if (pti[2] && pti[3] && pti[4] && pti[5] && pti[6] && pti[7])
 						if (pti[2] && pti[3] && pti[4] && pti[5] && pti[6] && pti[7])
 						{
 						{
-							pto += unicode_21_bit(&pti[2], pto);
+							pto += unicode_21_bit(pti + 2, pto);
 							pti += 8;
 							pti += 8;
 						}
 						}
 						else
 						else

+ 18 - 7
src/scan.c

@@ -62,7 +62,7 @@ struct scan_type scan_table[] =
 {
 {
 	{       "ABORT",            scan_abort,   SCAN_FLAG_NONE,                "Abort a scan currently in progress."},
 	{       "ABORT",            scan_abort,   SCAN_FLAG_NONE,                "Abort a scan currently in progress."},
 	{       "CSV",              scan_csv,     SCAN_FLAG_FILE|SCAN_FLAG_SCAN, "Scan a comma separated value file." },
 	{       "CSV",              scan_csv,     SCAN_FLAG_FILE|SCAN_FLAG_SCAN, "Scan a comma separated value file." },
-	{       "DIR",              scan_dir,     SCAN_FLAG_FILE,                "Scan a directory to a variable."    },
+	{       "DIR",              scan_dir,     SCAN_FLAG_NONE,                "Scan a directory to a variable."    },
 	{       "FILE",             scan_file,    SCAN_FLAG_FILE,                "Scan a file all at once."           },
 	{       "FILE",             scan_file,    SCAN_FLAG_FILE,                "Scan a file all at once."           },
 	{       "FORWARD",          scan_forward, SCAN_FLAG_FILE,                "Scan a file and send each line."    },
 	{       "FORWARD",          scan_forward, SCAN_FLAG_FILE,                "Scan a file and send each line."    },
 	{       "TSV",              scan_tsv,     SCAN_FLAG_FILE|SCAN_FLAG_SCAN, "Scan a tab separated value file."   },
 	{       "TSV",              scan_tsv,     SCAN_FLAG_FILE|SCAN_FLAG_SCAN, "Scan a tab separated value file."   },
@@ -303,7 +303,7 @@ DO_SCAN(scan_csv)
 
 
 DO_SCAN(scan_dir)
 DO_SCAN(scan_dir)
 {
 {
-	char filename[PATH_SIZE];
+	char cwd[PATH_SIZE], filename[PATH_SIZE * 2];
 	struct dirent **dirlist;
 	struct dirent **dirlist;
 	struct stat info;
 	struct stat info;
 	int size, index;
 	int size, index;
@@ -319,14 +319,25 @@ DO_SCAN(scan_dir)
 
 
 	set_nest_node_ses(ses, arg2, "");
 	set_nest_node_ses(ses, arg2, "");
 
 
+	if (*arg1 == 0)
+	{
+		if (getcwd(cwd, PATH_MAX) == NULL)
+		{
+			syserr_printf(ses, "scan_dir: getcwd:");
+
+			cwd[0] = 0;
+		}
+		arg1 = cwd;
+	}
+
 	size = scandir(arg1, &dirlist, 0, NULL);
 	size = scandir(arg1, &dirlist, 0, NULL);
 
 
 	if (size == -1)
 	if (size == -1)
 	{
 	{
 		if (stat(arg1, &info) == -1)
 		if (stat(arg1, &info) == -1)
 		{
 		{
-			syserr_printf(ses, "scan_dir: stat:");
-			
+			syserr_printf(ses, "scan_dir: stat(%s): error:", arg1);
+
 			return ses;
 			return ses;
 		}
 		}
 
 
@@ -353,9 +364,9 @@ DO_SCAN(scan_dir)
 
 
 		if (stat(filename, &info) == -1)
 		if (stat(filename, &info) == -1)
 		{
 		{
-			syserr_printf(ses, "scan_dir: stat:");
-			
-			return ses;
+			syserr_printf(ses, "scan_dir: stat(%s): error:", filename);
+
+			continue;
 		}
 		}
 
 
 		add_nest_node_ses(ses, arg2, "{%s}{{FILE}{%d}{MODE}{%u}{SIZE}{%u}{TIME}{%lld}}",
 		add_nest_node_ses(ses, arg2, "{%s}{{FILE}{%d}{MODE}{%u}{SIZE}{%u}{TIME}{%lld}}",

+ 21 - 1
src/screen.c

@@ -1702,7 +1702,7 @@ void fill_split_region(struct session *ses, char *arg)
 
 
 DO_SCREEN(screen_info)
 DO_SCREEN(screen_info)
 {
 {
-	int lvl;
+	int lvl, cnt, max;
 
 
 	if (is_abbrev(arg1, "SAVE"))
 	if (is_abbrev(arg1, "SAVE"))
 	{
 	{
@@ -1780,7 +1780,27 @@ DO_SCREEN(screen_info)
 		tintin_printf2(ses, "SPLIT mode detected.");
 		tintin_printf2(ses, "SPLIT mode detected.");
 	}
 	}
 
 
+	for (cnt = max = 0 ; cnt < gtd->screen->max_row ; cnt++)
+	{
+		max += str_len(gtd->screen->line[cnt]->str);
+	}
+	tintin_printf2(ses, "gtd->screen->line[%4d]:  %4d", gtd->screen->max_row, max);
+
+	for (cnt = max = 0 ; cnt < gtd->screen->max_row ; cnt++)
+	{
+		max += str_len(gtd->screen->grid[cnt]->str);
+	}
+	tintin_printf2(ses, "gtd->screen->grid[%4d]:  %4d", gtd->screen->max_row, max);
+/*
+	char buf[BUFFER_SIZE];
+
+	for (cnt = 0 ; cnt < 12 && cnt < gtd->screen->max_row ; cnt++)
+	{
+		convert_meta(gtd->screen->grid[cnt]->str, buf, 0);
 
 
+		tintin_printf2(ses, "%2d, %s", cnt, buf);
+	}
+*/
 	return;
 	return;
 }
 }
 
 

+ 50 - 25
src/session.c

@@ -72,7 +72,15 @@ DO_COMMAND(do_session)
 
 
 		for (sesptr = gts->next ; sesptr ; sesptr = sesptr->next)
 		for (sesptr = gts->next ; sesptr ; sesptr = sesptr->next)
 		{
 		{
-			show_session(ses, sesptr);
+			tintin_printf2(ses, "%-10s %18s:%-5s %5s %6s %10s %7s %5s",
+				sesptr->name,
+				sesptr->session_host,
+				sesptr->session_port,
+				sesptr == gtd->ses ? "(ats)" : "",
+				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)" : "",
+				HAS_BIT(sesptr->flags, SES_FLAG_SNOOP|SES_FLAG_SNOOPSCROLL) ? "(snoop)" : "",
+				sesptr->logfile ? "(log)" : "");
 		}
 		}
 	}
 	}
 	else if (*arg1 && *arg == 0)
 	else if (*arg1 && *arg == 0)
@@ -126,6 +134,13 @@ DO_COMMAND(do_session)
 			}
 			}
 		}
 		}
 
 
+		sesptr = find_session(arg1);
+
+		if (sesptr)
+		{
+			return activate_session(sesptr);
+		}
+
 		tintin_puts2(ses, "#THAT SESSION IS NOT DEFINED.");
 		tintin_puts2(ses, "#THAT SESSION IS NOT DEFINED.");
 	}
 	}
 	else
 	else
@@ -180,12 +195,43 @@ DO_COMMAND(do_snoop)
 	else if (is_abbrev(arg2, "OFF"))
 	else if (is_abbrev(arg2, "OFF"))
 	{
 	{
 		show_message(ses, LIST_COMMAND, "#SNOOP: NO LONGER SNOOPING SESSION '%s'", sesptr->name);
 		show_message(ses, LIST_COMMAND, "#SNOOP: NO LONGER SNOOPING SESSION '%s'", sesptr->name);
-
 		DEL_BIT(sesptr->flags, SES_FLAG_SNOOP);
 		DEL_BIT(sesptr->flags, SES_FLAG_SNOOP);
 	}
 	}
+	else if (is_abbrev(arg2, "SCROLL"))
+	{
+		arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
+
+		if (*arg2 == 0)
+		{
+			if (HAS_BIT(sesptr->flags, SES_FLAG_SNOOPSCROLL))
+			{
+				show_message(ses, LIST_COMMAND, "#SNOOP: NO LONGER SNOOPING SCROLL REGION OF SESSION '%s'", sesptr->name);
+			}
+			else
+			{
+				show_message(ses, LIST_COMMAND, "#SNOOP: SNOOPING SCROLL REGION OF SESSION '%s'", sesptr->name);
+			}
+			TOG_BIT(sesptr->flags, SES_FLAG_SNOOPSCROLL);
+		}
+		else if (is_abbrev(arg2, "ON"))
+		{
+			show_message(ses, LIST_COMMAND, "#SNOOP: SNOOPING SCROLL REGION OF SESSION '%s'", sesptr->name);
+
+			SET_BIT(sesptr->flags, SES_FLAG_SNOOPSCROLL);
+		}
+		else if (is_abbrev(arg2, "OFF"))
+		{
+			show_message(ses, LIST_COMMAND, "#SNOOP: NO LONGER SNOOPING SCROLL REGION OF SESSION '%s'", sesptr->name);
+			DEL_BIT(sesptr->flags, SES_FLAG_SNOOPSCROLL);
+		}
+		else
+		{
+			show_error(ses, LIST_COMMAND, "#SYNTAX: #SNOOP {session} {SCROLL} {ON|OFF}");
+		}
+	}
 	else
 	else
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #SNOOP {session} {ON|OFF}");
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #SNOOP {session} {ON|OFF|SCROLL}");
 	}
 	}
 	return ses;
 	return ses;
 }
 }
@@ -244,27 +290,6 @@ DO_COMMAND(do_zap)
 	return ses;
 	return ses;
 }
 }
 
 
-
-void show_session(struct session *ses, struct session *ptr)
-{
-	char temp[BUFFER_SIZE];
-
-	sprintf(temp, "%-10s %18s:%-5s %5s %6s",
-		ptr->name,
-		ptr->session_host,
-		ptr->session_port,
-		ptr == gtd->ses ? "(ats)" : "",
-		ptr->ssl ? "(ssl)" : ptr->port ? "(port)" : HAS_BIT(ptr->flags, SES_FLAG_RUN) ? " (run)" : "");
-
-	cat_sprintf(temp, " %10s", ptr->mccp2 && ptr->mccp3 ? "(mccp 2+3)" : ptr->mccp2 ? "(mccp 2)" : ptr->mccp3 ? "(mccp 3)" : "");
-
-	cat_sprintf(temp, " %7s", HAS_BIT(ptr->flags, SES_FLAG_SNOOP) ? "(snoop)" : "");
-
-	cat_sprintf(temp, " %5s", ptr->logfile ? "(log)" : "");
-
-	tintin_puts2(ses, temp);
-}
-
 struct session *find_session(char *name)
 struct session *find_session(char *name)
 {
 {
 	struct session *ses;
 	struct session *ses;
@@ -433,7 +458,7 @@ 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));
+	newses->scroll        = calloc(1, sizeof(struct scroll_data));
 	init_buffer(newses, gts->scroll->size);
 	init_buffer(newses, gts->scroll->size);
 
 
 	newses->input         = calloc(1, sizeof(struct input_data));
 	newses->input         = calloc(1, sizeof(struct input_data));

+ 3 - 2
src/split.c

@@ -247,6 +247,7 @@ void dirty_screen(struct session *ses)
 	if (IS_SPLIT(ses) && ses == gtd->ses)
 	if (IS_SPLIT(ses) && ses == gtd->ses)
 	{
 	{
 		init_pos(ses, ses->input->top_row, ses->input->top_col);
 		init_pos(ses, ses->input->top_row, ses->input->top_col);
+		cursor_redraw_input(ses, "");
 	}
 	}
 
 
 	pop_call();
 	pop_call();
@@ -302,7 +303,7 @@ void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 		return;
 		return;
 	}
 	}
 
 
-	if (row != gtd->screen->rows && inside_scroll_region(ses, row, col))
+	if (row > ses->input->top_row && inside_scroll_region(ses, row, col))
 	{
 	{
 		show_error(ses, LIST_PROMPT, "#ERROR: PROMPT ROW IS INSIDE THE SCROLLING REGION: {%s} {%s} [%d].", prompt, row_str, row);
 		show_error(ses, LIST_PROMPT, "#ERROR: PROMPT ROW IS INSIDE THE SCROLLING REGION: {%s} {%s} [%d].", prompt, row_str, row);
 
 
@@ -331,7 +332,7 @@ void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 
 
 	save_pos(ses);
 	save_pos(ses);
 
 
-	if (row == gtd->screen->rows)
+	if (row == ses->input->top_row)
 	{
 	{
 		gtd->ses->input->str_off = width + 1;
 		gtd->ses->input->str_off = width + 1;
 
 

+ 64 - 1
src/string.c

@@ -255,6 +255,65 @@ int raw_len_str_min(struct session *ses, char *str, int start, int end)
 	return ret_cnt;
 	return ret_cnt;
 }
 }
 
 
+// like str_min but also grab tailing colors
+
+int raw_len_str_opt(struct session *ses, char *str, int start, int end)
+{
+	int raw_cnt, str_cnt, ret_cnt, width, tmp_cnt, raw_len;
+
+	raw_cnt = 0;
+	str_cnt = 0;
+	ret_cnt = 0;
+	raw_len = strlen(str);
+
+	while (raw_cnt < raw_len)
+	{
+		tmp_cnt = skip_vt102_codes(&str[raw_cnt]);
+
+		if (tmp_cnt)
+		{
+			raw_cnt += tmp_cnt;
+
+			if (str_cnt >= start)
+			{
+				ret_cnt += tmp_cnt;
+			}
+			continue;
+		}
+
+		if (str_cnt >= end)
+		{
+			break;
+		}
+
+		if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && is_utf8_head(&str[raw_cnt]))
+		{    
+			tmp_cnt = get_utf8_width(&str[raw_cnt], &width);
+
+			if (str_cnt >= start)
+			{
+				ret_cnt += tmp_cnt;
+			}
+			raw_cnt += tmp_cnt;
+		}
+		else
+		{
+			if (str_cnt >= start)
+			{
+				ret_cnt++;
+			}
+			raw_cnt++;
+			width = 1;
+		}
+		if (end >= 0 && str_cnt + width > end)
+		{
+			break;
+		}
+		str_cnt += width;
+	}
+	return ret_cnt;
+}
+
 int raw_len_raw(struct session *ses, char *str, int start, int end)
 int raw_len_raw(struct session *ses, char *str, int start, int end)
 {
 {
 	if (end == -1)
 	if (end == -1)
@@ -290,8 +349,10 @@ char *str_ins_str(struct session *ses, char **str, char *ins, int str_start, int
 	ins_raw_len = raw_len_str(ses, ins, 0, str_end - str_start);
 	ins_raw_len = raw_len_str(ses, ins, 0, str_end - str_start);
 
 
 	raw_start = raw_len_str_min(ses, *str, 0, str_start);
 	raw_start = raw_len_str_min(ses, *str, 0, str_start);
+
 	raw_len   = str_len(*str);
 	raw_len   = str_len(*str);
-	raw_end   = raw_len_str_min(ses, *str, 0, str_end);
+//	raw_end   = raw_len_str_min(ses, *str, 0, str_end);
+	raw_end   = raw_len_str_opt(ses, *str, 0, str_end);
 
 
 	tmp = (*str)[raw_end];
 	tmp = (*str)[raw_end];
 
 
@@ -301,6 +362,8 @@ char *str_ins_str(struct session *ses, char **str, char *ins, int str_start, int
 
 
 	(*str)[raw_end] = tmp;
 	(*str)[raw_end] = tmp;
 
 
+//	*old = 0;
+
 	col_len = strlen(old);
 	col_len = strlen(old);
 
 
 	str_resize(str, ins_raw_len + col_len + 1);
 	str_resize(str, ins_raw_len + col_len + 1);

+ 42 - 18
src/substitute.c

@@ -1991,25 +1991,49 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 						case 'x':
 						case 'x':
 							if (pti[1] && pti[2])
 							if (pti[1] && pti[2])
 							{
 							{
-								if (pti[1] == '0' && pti[2] == '0' && pti[3] == 0)
-								{
-									pti += 2;
-									DEL_BIT(flags, SUB_EOL);
-									DEL_BIT(flags, SUB_LNF);
-								}
-								else
-								{
-									pti++;
-									*pto++ = hex_number_8bit(pti);
-									pti++;
-								}
+								*pto++ = hex_number_8bit(pti + 1);
+								pti += 2;
 							}
 							}
 							break;
 							break;
 
 
 						case 'u':
 						case 'u':
-							if (pti[1] && pti[2] && pti[3] && pti[4])
+							if (pti[1] == '{')
+							{
+								if (pti[2] && pti[3] && pti[4])
+								{
+									if (pti[4] == '}')
+									{
+										pto += unicode_8_bit(pti + 2, pto);
+										pti += 4;
+									}
+									else if (pti[5] == '}')
+									{
+										pto += unicode_12_bit(pti + 2, pto);
+										pti += 5;
+									}
+									else if (pti[5] && pti[6])
+									{
+										if (pti[6] == '}')
+										{
+											pto += unicode_16_bit(pti + 2, pto);
+											pti += 6;
+										}
+										else if (pti[7] == '}')
+										{
+											pto += unicode_20_bit(pti + 2, pto);
+											pti += 7;
+										}
+										else if (pti[7] && pti[8] == '}')
+										{
+											pto += unicode_21_bit(pti + 2, pto);
+											pti += 8;
+										}
+									}
+								}
+							}
+							else if (pti[1] && pti[2] && pti[3] && pti[4])
 							{
 							{
-								pto += unicode_16_bit(&pti[1], pto);
+								pto += unicode_16_bit(pti + 1, pto);
 								pti += 4;
 								pti += 4;
 							}
 							}
 							break;
 							break;
@@ -2017,7 +2041,7 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 						case 'U':
 						case 'U':
 							if (pti[1] && pti[2] && pti[3] && pti[4] && pti[5] && pti[6])
 							if (pti[1] && pti[2] && pti[3] && pti[4] && pti[5] && pti[6])
 							{
 							{
-								pto += unicode_21_bit(&pti[1], pto);
+								pto += unicode_21_bit(pti + 1, pto);
 								pti += 6;
 								pti += 6;
 							}
 							}
 							break;
 							break;
@@ -2029,14 +2053,14 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 						case '0':
 						case '0':
 							if (pti[1] == 0)
 							if (pti[1] == 0)
 							{
 							{
+								*pto++ = 0;
 								DEL_BIT(flags, SUB_EOL);
 								DEL_BIT(flags, SUB_EOL);
 								DEL_BIT(flags, SUB_LNF);
 								DEL_BIT(flags, SUB_LNF);
 							}
 							}
 							else if (pti[1] && pti[2])
 							else if (pti[1] && pti[2])
 							{
 							{
-								pti++;
-								*pto++ = oct_number(pti);
-								pti++;
+								*pto++ = oct_number(pti + 1);
+								pti += 2;
 							}
 							}
 							break;
 							break;
 
 

+ 4 - 2
src/tables.c

@@ -36,7 +36,7 @@ struct list_type list_table[LIST_MAX] =
 	{    "CLASS",             "CLASSES",            SORT_PRIORITY,    2, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_INHERIT                                 },
 	{    "CLASS",             "CLASSES",            SORT_PRIORITY,    2, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_INHERIT                                 },
 	{    "COMMAND",           "COMMANDS",           SORT_APPEND,      1, 0, 0, LIST_FLAG_MESSAGE                                                                  },
 	{    "COMMAND",           "COMMANDS",           SORT_APPEND,      1, 0, 0, LIST_FLAG_MESSAGE                                                                  },
 	{    "CONFIG",            "CONFIGS",            SORT_ALPHA,       2, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "CONFIG",            "CONFIGS",            SORT_ALPHA,       2, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
-	{    "DELAY",             "DELAYS",             SORT_STABLE,       2, 2, 3, LIST_FLAG_MESSAGE|LIST_FLAG_READ                                                   },
+	{    "DELAY",             "DELAYS",             SORT_STABLE,      2, 2, 3, LIST_FLAG_MESSAGE|LIST_FLAG_READ                                                   },
 	{    "EVENT",             "EVENTS",             SORT_ALPHA,       2, 2, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "EVENT",             "EVENTS",             SORT_ALPHA,       2, 2, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "FUNCTION",          "FUNCTIONS",          SORT_ALPHA,       2, 2, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "FUNCTION",          "FUNCTIONS",          SORT_ALPHA,       2, 2, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "GAG",               "GAGS",               SORT_ALPHA,       1, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "GAG",               "GAGS",               SORT_ALPHA,       1, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
@@ -1084,6 +1084,8 @@ struct event_type event_table[] =
 	{    "SESSION DISCONNECTED",                   0, EVENT_FLAG_SESSION,  "SESSION",   "a session disconnects"      },
 	{    "SESSION DISCONNECTED",                   0, EVENT_FLAG_SESSION,  "SESSION",   "a session disconnects"      },
 	{    "SESSION TIMED OUT",                      0, EVENT_FLAG_SESSION,  "SESSION",   "a session doesn't connect"  },
 	{    "SESSION TIMED OUT",                      0, EVENT_FLAG_SESSION,  "SESSION",   "a session doesn't connect"  },
 	{    "SHORT-CLICKED",                          0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is short-clicked"     },
 	{    "SHORT-CLICKED",                          0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is short-clicked"     },
+	{    "SIGHUB",                                 0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "Terminal has closed"        },
+	{    "SIGUSR",                                 0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "Raised SIGUSR1 or SIGUSR2"  },
 	{    "SWIPED",                                 0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse swipe"                },
 	{    "SWIPED",                                 0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse swipe"                },
 	{    "SYSTEM CRASH",                           0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "system crash"               },
 	{    "SYSTEM CRASH",                           0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "system crash"               },
 	{    "SYSTEM ERROR",                           0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "system errors"              },
 	{    "SYSTEM ERROR",                           0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "system errors"              },
@@ -1157,7 +1159,7 @@ struct line_type line_table[] =
 
 
 struct log_type log_table[] =
 struct log_type log_table[] =
 {
 {
-	{    "APPEND",            log_append,          "Start logging, appending to give file."         },
+	{    "APPEND",            log_append,          "Start logging, appending to given file."        },
 	{    "INFO",              log_info,            "Some logging related info."                     },
 	{    "INFO",              log_info,            "Some logging related info."                     },
 	{    "OFF",               log_off,             "Stop logging."                                  },
 	{    "OFF",               log_off,             "Stop logging."                                  },
 	{    "OVERWRITE",         log_overwrite,       "Start logging, overwriting the given file."     },
 	{    "OVERWRITE",         log_overwrite,       "Start logging, overwriting the given file."     },

+ 2 - 0
src/text.c

@@ -220,6 +220,8 @@ int word_wrap(struct session *ses, char *textin, char *textout, int flags, int *
 		{
 		{
 			cur_height++;
 			cur_height++;
 
 
+//			printf("cur_col %d tab %d wrap %d pti %d\n", ses->cur_col, tab, wrap, *pti);
+
 			if (HAS_BIT(ses->config_flags, CONFIG_FLAG_WORDWRAP))
 			if (HAS_BIT(ses->config_flags, CONFIG_FLAG_WORDWRAP))
 			{
 			{
 				if (ses->cur_col - cur_space >= 15 || wrap <= 20 || !SCROLL(ses))
 				if (ses->cur_col - cur_space >= 15 || wrap <= 20 || !SCROLL(ses))

+ 18 - 18
src/tintin.h

@@ -134,7 +134,6 @@
 #define SORT_ALNUM                       2
 #define SORT_ALNUM                       2
 #define SORT_STABLE                      3
 #define SORT_STABLE                      3
 #define SORT_APPEND                      4
 #define SORT_APPEND                      4
-#define SORT_DELAY                       5
 
 
 #define SEEK_MATCH                       0
 #define SEEK_MATCH                       0
 #define SEEK_REPLACE                     1
 #define SEEK_REPLACE                     1
@@ -208,7 +207,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.10 "
+#define CLIENT_VERSION           "2.02.11 "
 
 
 
 
 #define XT_E                            0x27
 #define XT_E                            0x27
@@ -381,6 +380,7 @@ enum operators
 #define BV38 (1LL << 37)
 #define BV38 (1LL << 37)
 #define BV39 (1LL << 38)
 #define BV39 (1LL << 38)
 #define BV40 (1LL << 39)
 #define BV40 (1LL << 39)
+#define BV41 (1LL << 40)
 
 
 
 
 #define BUFFER_FLAG_GREP                  BV01
 #define BUFFER_FLAG_GREP                  BV01
@@ -609,7 +609,7 @@ enum operators
 #define TINTIN_FLAG_HIDDENCURSOR      BV11
 #define TINTIN_FLAG_HIDDENCURSOR      BV11
 #define TINTIN_FLAG_LOCAL             BV12
 #define TINTIN_FLAG_LOCAL             BV12
 #define TINTIN_FLAG_PRESERVEMACRO     BV13
 #define TINTIN_FLAG_PRESERVEMACRO     BV13
-
+#define TINTIN_FLAG_WINCHUPDATE       BV14
 
 
 #define CONFIG_FLAG_AUTOPATCH         BV01
 #define CONFIG_FLAG_AUTOPATCH         BV01
 #define CONFIG_FLAG_AUTOPROMPT        BV02
 #define CONFIG_FLAG_AUTOPROMPT        BV02
@@ -642,8 +642,9 @@ enum operators
 #define SES_FLAG_SCANABORT            BV10
 #define SES_FLAG_SCANABORT            BV10
 #define SES_FLAG_SCROLLSPLIT          BV11
 #define SES_FLAG_SCROLLSPLIT          BV11
 #define SES_FLAG_SNOOP                BV12
 #define SES_FLAG_SNOOP                BV12
-#define SES_FLAG_SPLIT                BV13
-#define SES_FLAG_UPDATEVTMAP          BV14
+#define SES_FLAG_SNOOPSCROLL          BV13
+#define SES_FLAG_SPLIT                BV14
+#define SES_FLAG_UPDATEVTMAP          BV15
 
 
 
 
 #define TELOPT_FLAG_TELNET            BV01
 #define TELOPT_FLAG_TELNET            BV01
@@ -1289,7 +1290,6 @@ struct split_data
 	int                     bot_col;
 	int                     bot_col;
 };
 };
 
 
-
 struct scroll_data
 struct scroll_data
 {
 {
 	struct buffer_data   ** buffer;
 	struct buffer_data   ** buffer;
@@ -1475,6 +1475,8 @@ struct exit_data
 struct search_data
 struct search_data
 {
 {
 	int                     vnum;
 	int                     vnum;
+	int                     min;
+	int                     max;
 	unsigned short          stamp;
 	unsigned short          stamp;
 	char                  * arg;
 	char                  * arg;
 	pcre                  * name;
 	pcre                  * name;
@@ -1602,7 +1604,7 @@ struct window_data
 #define DO_LOG(log)                        void log (struct session *ses, char *arg, char *arg1, char *arg2)
 #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 *arg1, char *arg2, char *arg)
+#define DO_PORT(port)          struct session *port (struct session *ses, char *arg, char *arg1, char *arg2)
 
 
 
 
 /*
 /*
@@ -1624,7 +1626,7 @@ typedef struct session *LINE    (struct session *ses, char *arg, char *arg1, cha
 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);
 typedef void            PATH    (struct session *ses, char *arg);
 typedef void            PATH    (struct session *ses, char *arg);
-typedef struct session *PORT    (struct session *ses, char *arg1, char *arg2, char *arg);
+typedef struct session *PORT    (struct session *ses, char *arg, char *arg1, char *arg2);
 
 
 
 
 /*
 /*
@@ -1964,6 +1966,9 @@ extern DO_COMMAND(do_cursor);
 
 
 int inputline_cur_row(void);
 int inputline_cur_row(void);
 int inputline_cur_col(void);
 int inputline_cur_col(void);
+int inputline_cur_off(void);
+int inputline_cur_str_len(void);
+int inputline_max_str_len(void);
 int inputline_max_row(void);
 int inputline_max_row(void);
 int inputline_editor(void);
 int inputline_editor(void);
 int inputline_rows(struct session *ses);
 int inputline_rows(struct session *ses);
@@ -2110,23 +2115,16 @@ extern DO_MAP(map_write);
 #ifndef __TT_MATH_H__
 #ifndef __TT_MATH_H__
 #define __TT_MATH_H__
 #define __TT_MATH_H__
 
 
+extern long double mathexp(struct session *ses, char *str, char *result, int seed);
 extern int is_math(struct session *ses, char *str);
 extern int is_math(struct session *ses, char *str);
-extern int get_ellipsis(struct listroot *root, char *name, int *min, int *max);
+extern int get_ellipsis(struct session *ses, unsigned int size, char *name, int *min, int *max);
 extern long double get_number(struct session *ses, char *str);
 extern long double get_number(struct session *ses, char *str);
 extern unsigned long long get_ulong(struct session *ses, char *str);
 extern unsigned long long get_ulong(struct session *ses, char *str);
 extern long double get_double(struct session *ses, char *str);
 extern long double get_double(struct session *ses, char *str);
 extern void get_number_string(struct session *ses, char *str, char *result);
 extern void get_number_string(struct session *ses, char *str, char *result);
 extern long double mathswitch(struct session *ses, char *left, char *right);
 extern long double mathswitch(struct session *ses, char *left, char *right);
-extern void mathexp(struct session *ses, char *str, char *result, int seed);
-extern int mathexp_tokenize(struct session *ses, char *str, int seed, int debug);
-extern void mathexp_level(struct session *ses, struct link_data *node);
-extern void mathexp_compute(struct session *ses, struct link_data *node);
-extern long double tinternary(char *arg1, char *arg2);
 extern long double tintoi(char *str);
 extern long double tintoi(char *str);
 extern unsigned long long tintou(char *str);
 extern unsigned long long tintou(char *str);
-extern long double tincmp(char *left, char *right);
-extern long double tineval(struct session *ses, char *left, char *right);
-extern long double tindice(struct session *ses, char *left, char *right);
 
 
 
 
 #endif
 #endif
@@ -2697,7 +2695,6 @@ extern DO_COMMAND(do_snoop);
 extern DO_COMMAND(do_zap);
 extern DO_COMMAND(do_zap);
 
 
 extern struct session *session_command(char *arg, struct session *ses);
 extern struct session *session_command(char *arg, struct session *ses);
-extern void show_session(struct session *ses, struct session *ptr);
 extern struct session *find_session(char *name);
 extern struct session *find_session(char *name);
 extern struct session *newactive_session(void);
 extern struct session *newactive_session(void);
 extern struct session *activate_session(struct session *ses);
 extern struct session *activate_session(struct session *ses);
@@ -2955,7 +2952,10 @@ extern unsigned long long hex_number_64bit(char *str);
 extern unsigned int hex_number_32bit(char *str);
 extern unsigned int hex_number_32bit(char *str);
 extern int hex_number_8bit(char *str);
 extern int hex_number_8bit(char *str);
 extern int oct_number(char *str);
 extern int oct_number(char *str);
+extern int unicode_8_bit(char *str, char *out);
+extern int unicode_12_bit(char *str, char *out);
 extern int unicode_16_bit(char *str, char *out);
 extern int unicode_16_bit(char *str, char *out);
+extern int unicode_20_bit(char *str, char *out);
 extern int unicode_21_bit(char *str, char *out);
 extern int unicode_21_bit(char *str, char *out);
 extern unsigned long long utime(void);
 extern unsigned long long utime(void);
 extern time_t get_time(struct session *ses, char *str);
 extern time_t get_time(struct session *ses, char *str);

+ 2 - 0
src/tokenize.c

@@ -289,6 +289,8 @@ void handleswitchtoken(struct session *ses, struct scriptnode *token)
 {
 {
 	char arg[BUFFER_SIZE];
 	char arg[BUFFER_SIZE];
 
 
+//	substitute(ses, token->str, arg, SUB_VAR|SUB_FUN);
+
 	mathexp(ses, token->str, arg, 0);
 	mathexp(ses, token->str, arg, 0);
 
 
 	RESTRING(token->data->str, arg);
 	RESTRING(token->data->str, arg);

+ 2 - 2
src/trigger.c

@@ -244,7 +244,7 @@ DO_COMMAND(do_button)
 	struct listnode *node;
 	struct listnode *node;
 	int index;
 	int index;
 
 
-	arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
+	arg = get_arg_in_braces(ses, arg, arg1, GET_ALL);
 	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
 	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
 	arg = get_arg_in_braces(ses, arg, arg3, GET_ALL);
 	arg = get_arg_in_braces(ses, arg, arg3, GET_ALL);
 
 
@@ -272,7 +272,7 @@ DO_COMMAND(do_button)
 
 
 		for (index = 0 ; index < 4 ; index++)
 		for (index = 0 ; index < 4 ; index++)
 		{
 		{
-			arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
+			arg = sub_arg_in_braces(ses, arg, arg2, GET_ONE, SUB_VAR|SUB_FUN);
 
 
 			node->val16[index] = (short) get_number(ses, arg2);
 			node->val16[index] = (short) get_number(ses, arg2);
 
 

+ 29 - 0
src/update.c

@@ -374,6 +374,24 @@ void update_sessions(void)
 		sleep = 0;
 		sleep = 0;
 	}
 	}
 
 
+	if (HAS_BIT(gtd->flags, TINTIN_FLAG_WINCHUPDATE))
+	{
+		DEL_BIT(gtd->flags, TINTIN_FLAG_WINCHUPDATE);
+
+		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();
+	}
+
 	if (gts->next)
 	if (gts->next)
 	{
 	{
 		FD_ZERO(&read_fd);
 		FD_ZERO(&read_fd);
@@ -474,6 +492,17 @@ void update_sessions(void)
 				}
 				}
 				else
 				else
 				{
 				{
+					if (HAS_BIT(ses->flags, SES_FLAG_SNOOPSCROLL))
+					{
+						if (HAS_BIT(ses->scroll->flags, SCROLL_FLAG_RESIZE))
+						{
+							buffer_refresh(ses, "", "", "");
+						}
+						else
+						{
+							print_scroll_region(ses);
+						}
+					}
 					buffer_end(ses, "", "", "");
 					buffer_end(ses, "", "", "");
 				}
 				}
 
 

+ 83 - 129
src/utils.c

@@ -83,30 +83,14 @@ int hex_number_8bit(char *str)
 {
 {
 	int value = 0;
 	int value = 0;
 
 
-	if (str)
+	if (*str)
 	{
 	{
-		if (is_digit(*str))
-		{
-			value += 16 * (*str - '0');
-		}
-		else
-		{
-			value += 16 * (toupper((int) *str) - 'A' + 10);
-		}
-		str++;
+		value += 16 * hex_digit(str++);
 	}
 	}
 
 
-	if (str)
+	if (*str)
 	{
 	{
-		if (is_digit(*str))
-		{
-			value += *str - '0';
-		}
-		else
-		{
-			value += toupper((int) *str) - 'A' + 10;
-		}
-		str++;
+		value += hex_digit(str++);
 	}
 	}
 
 
 	return value;
 	return value;
@@ -116,7 +100,7 @@ int oct_number(char *str)
 {
 {
 	int value = 0;
 	int value = 0;
 
 
-	if (str)
+	if (*str)
 	{
 	{
 		if (is_digit(*str))
 		if (is_digit(*str))
 		{
 		{
@@ -125,7 +109,7 @@ int oct_number(char *str)
 		str++;
 		str++;
 	}
 	}
 
 
-	if (str)
+	if (*str)
 	{
 	{
 		if (is_digit(*str))
 		if (is_digit(*str))
 		{
 		{
@@ -137,64 +121,63 @@ int oct_number(char *str)
 	return value;
 	return value;
 }
 }
 
 
-int unicode_16_bit(char *str, char *out)
+int unicode_8_bit(char *str, char *out)
 {
 {
 	int val = 0;
 	int val = 0;
 	unsigned char *pto = (unsigned char *) out;
 	unsigned char *pto = (unsigned char *) out;
 
 
-	val += 4096 * hex_digit(str);
+	val += 16 * hex_digit(str++);
+	val += hex_digit(str++);
 
 
-/*
-	if (is_digit(*str))
+	if (val < 128)
 	{
 	{
-		val += 4096 * (*str - '0');
+		*pto++ = val;
+		*pto++ = 0;
+		return 1;
 	}
 	}
 	else
 	else
 	{
 	{
-		val += 4096 * (toupper((int) *str) - 'A' + 10);
+		*pto++ = 192 + val / 64;
+		*pto++ = 128 + val % 64;
+		*pto++ = 0;
+		return 2;
 	}
 	}
-*/
-	str++;
+}
 
 
-	val += 256 * hex_digit(str);
+int unicode_12_bit(char *str, char *out)
+{
+	int val = 0;
+	unsigned char *pto = (unsigned char *) out;
 
 
-/*
-	if (is_digit(*str))
-	{
-		val += 256 * (*str - '0');
-	}
-	else
-	{
-		val += 256 * (toupper((int) *str) - 'A' + 10);
-	}
-*/
-	str++;
+	val += 256 * hex_digit(str++);
+	val += 16 * hex_digit(str++);
+	val += hex_digit(str++);
 
 
-	val += 16 * hex_digit(str);
-/*
-	if (is_digit(*str))
+	if (val < 128)
 	{
 	{
-		val += 16 * (*str - '0');
+		*pto++ = val;
+		*pto++ = 0;
+		return 1;
 	}
 	}
 	else
 	else
 	{
 	{
-		val += 16 * (toupper((int) *str) - 'A' + 10);
+		*pto++ = 192 + val / 64;
+		*pto++ = 128 + val % 64;
+		*pto++ = 0;
+		return 2;
 	}
 	}
-*/
-	str++;
+}
 
 
-	val += hex_digit(str);
-/*
-	if (is_digit(*str))
-	{
-		val += (*str - '0');
-	}
-	else
-	{
-		val += (toupper((int) *str) - 'A' + 10);
-	}
-*/
-	str++;
+
+int unicode_16_bit(char *str, char *out)
+{
+	int val = 0;
+	unsigned char *pto = (unsigned char *) out;
+
+	val += 4096 * hex_digit(str++);
+	val += 256 * hex_digit(str++);
+	val += 16 * hex_digit(str++);
+	val += hex_digit(str++);
 
 
 	if (val < 128)
 	if (val < 128)
 	{
 	{
@@ -219,88 +202,59 @@ int unicode_16_bit(char *str, char *out)
 	}
 	}
 }
 }
 
 
-int unicode_21_bit(char *str, char *out)
+int unicode_20_bit(char *str, char *out)
 {
 {
 	int val = 0;
 	int val = 0;
 	unsigned char *pto = (unsigned char *) out;
 	unsigned char *pto = (unsigned char *) out;
 
 
-	if (str)
-	{
-		if (is_digit(*str))
-		{
-			val += 1048576 * (*str - '0');
-		}
-		else
-		{
-			val += 1048576 * (toupper((int) *str) - 'A' + 10);
-		}
-		str++;
-	}
+	val += 65536 * hex_digit(str++);
+	val += 4096 * hex_digit(str++);
+	val += 256 * hex_digit(str++);
+	val += 16 * hex_digit(str++);
+	val += hex_digit(str++);
 
 
-	if (str)
+	if (val < 128)
 	{
 	{
-		if (is_digit(*str))
-		{
-			val += 65536 * (*str - '0');
-		}
-		else
-		{
-			val += 65536 * (toupper((int) *str) - 'A' + 10);
-		}
-		str++;
+		*pto++ = val;
+		return 1;
 	}
 	}
-
-	if (str)
+	else if (val < 4096)
 	{
 	{
-		if (is_digit(*str))
-		{
-			val += 4096 * (*str - '0');
-		}
-		else
-		{
-			val += 4096 * (toupper((int) *str) - 'A' + 10);
-		}
-		str++;
+		*pto++ = 192 + val / 64;
+		*pto++ = 128 + val % 64;
+		*pto++ = 0;
+		return 2;
 	}
 	}
-
-	if (str)
+	else if (val < 65536)
 	{
 	{
-		if (is_digit(*str))
-		{
-			val += 256 * (*str - '0');
-		}
-		else
-		{
-			val += 256 * (toupper((int) *str) - 'A' + 10);
-		}
-		str++;
+		*pto++ = 224 + val / 4096;
+		*pto++ = 128 + val / 64 % 64;
+		*pto++ = 128 + val % 64;
+		*pto++ = 0;
+		return 3;
 	}
 	}
-
-	if (str)
+	else
 	{
 	{
-		if (is_digit(*str))
-		{
-			val += 16 * (*str - '0');
-		}
-		else
-		{
-			val += 16 * (toupper((int) *str) - 'A' + 10);
-		}
-		str++;
+		*pto++ = 240 + val / 262144;
+		*pto++ = 128 + val / 4096 % 64;
+		*pto++ = 128 + val / 64 % 64;
+	        *pto++ = 128 + val % 64;
+		*pto++ = 0;
+	        return 4;
 	}
 	}
+}
 
 
-	if (str)
-	{
-		if (is_digit(*str))
-		{
-			val += (*str - '0');
-		}
-		else
-		{
-			val += (toupper((int) *str) - 'A' + 10);
-		}
-		str++;
-	}
+int unicode_21_bit(char *str, char *out)
+{
+	int val = 0;
+	unsigned char *pto = (unsigned char *) out;
+
+	val += 1048576 * hex_digit(str++);
+	val += 65536 * hex_digit(str++);
+	val += 4096 * hex_digit(str++);
+	val += 256 * hex_digit(str++);
+	val += 16 * hex_digit(str++);
+	val += hex_digit(str++);
 
 
 	if (val < 128)
 	if (val < 128)
 	{
 	{

+ 15 - 5
src/variable.c

@@ -695,7 +695,7 @@ void thousandgroupingstring(struct session *ses, char *str)
 
 
 	get_number_string(ses, str, strold);
 	get_number_string(ses, str, strold);
 
 
-	cnt1 = strlen(strold);
+	cnt1 = strlen(strold) - 1;
 	cnt2 = BUFFER_SIZE / 2;
 	cnt2 = BUFFER_SIZE / 2;
 	cnt4 = strchr(strold, '.') ? 1 : 0;
 	cnt4 = strchr(strold, '.') ? 1 : 0;
 
 
@@ -724,6 +724,7 @@ void thousandgroupingstring(struct session *ses, char *str)
 	return;
 	return;
 }
 }
 
 
+/*
 void chronosgroupingstring(struct session *ses, char *str)
 void chronosgroupingstring(struct session *ses, char *str)
 {
 {
 	char *sign = "-";
 	char *sign = "-";
@@ -763,6 +764,7 @@ void chronosgroupingstring(struct session *ses, char *str)
 		sprintf(str, "%s%d:%02d", sign, minutes, seconds);
 		sprintf(str, "%s%d:%02d", sign, minutes, seconds);
 	}
 	}
 }
 }
+*/
 
 
 void metricgroupingstring(struct session *ses, char *str)
 void metricgroupingstring(struct session *ses, char *str)
 {
 {
@@ -885,7 +887,8 @@ void wrapstring(struct session *ses, char *str, char *wrap)
 	arg1 = str_alloc_stack(0);
 	arg1 = str_alloc_stack(0);
 	arg2 = str_alloc_stack(0);
 	arg2 = str_alloc_stack(0);
 
 
-	arg = sub_arg_in_braces(ses, str, arg1, GET_ALL, SUB_COL|SUB_LIT|SUB_ESC);
+//	arg = sub_arg_in_braces(ses, str, arg1, GET_ALL, SUB_COL|SUB_LIT|SUB_ESC);
+	arg = sub_arg_in_braces(ses, str, arg1, GET_ALL, SUB_COL|SUB_ESC);
 
 
 	if (*arg == COMMAND_SEPARATOR)
 	if (*arg == COMMAND_SEPARATOR)
 	{
 	{
@@ -1440,7 +1443,8 @@ void format_string(struct session *ses, char *format, char *arg, char *out)
 						break;
 						break;
 
 
 					case 'C':
 					case 'C':
-						chronosgroupingstring(ses, arglist[i]);
+						tintin_printf2(ses, "\e[1;31m#echo/#format %%C please use #screen {get} {cols} to get screen width.");
+//						chronosgroupingstring(ses, arglist[i]);
 						break;
 						break;
 
 
 					case 'D':
 					case 'D':
@@ -1465,8 +1469,14 @@ void format_string(struct session *ses, char *format, char *arg, char *out)
 						break;
 						break;
 
 
 					case 'R':
 					case 'R':
-						tintin_printf2(ses, "\e[1;31m#echo/#format %%R please use #screen {get} {rows} to get screen height.");
-						sprintf(arglist[i], "%d", gtd->screen->rows);
+						if (*arglist[i] == 0)
+						{
+							sprintf(arglist[i], "%d", gtd->screen->rows);
+						}
+						else
+						{
+							sprintf(arglist[i], "%d", get_row_index_arg(ses, arglist[i]));
+						}
 						break;
 						break;
 
 
 					case 'S':
 					case 'S':

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff