Scandum 4 gadi atpakaļ
vecāks
revīzija
4518ea51fc
40 mainītis faili ar 1423 papildinājumiem un 769 dzēšanām
  1. 118 73
      SCRIPTS
  2. 97 3
      TODO
  3. 85 53
      docs/help.html
  4. 61 0
      mods/igr.mods
  5. 0 3
      src/Makefile.in
  6. 13 13
      src/banner.c
  7. 5 2
      src/buffer.c
  8. 43 159
      src/config.c
  9. 2 2
      src/cursor.c
  10. 64 20
      src/data.c
  11. 9 39
      src/dict.c
  12. 1 0
      src/dict.h
  13. 169 76
      src/draw.c
  14. 3 3
      src/event.c
  15. 3 3
      src/files.c
  16. 73 46
      src/help.c
  17. 4 4
      src/history.c
  18. 1 1
      src/input.c
  19. 46 2
      src/list.c
  20. 15 3
      src/log.c
  21. 1 0
      src/main.c
  22. 14 12
      src/mapper.c
  23. 40 7
      src/math.c
  24. 8 0
      src/misc.c
  25. 4 4
      src/net.c
  26. 41 13
      src/path.c
  27. 19 0
      src/regex.c
  28. 11 10
      src/session.c
  29. 2 2
      src/split.c
  30. 179 3
      src/substitute.c
  31. 24 4
      src/tables.c
  32. 30 79
      src/telopt_client.c
  33. 11 36
      src/terminal.c
  34. 35 20
      src/tintin.h
  35. 16 8
      src/trigger.c
  36. 4 4
      src/update.c
  37. 155 42
      src/utf8.c
  38. 2 6
      src/utils.c
  39. 3 3
      src/variable.c
  40. 12 11
      src/vt102.c

+ 118 - 73
SCRIPTS

@@ -151,6 +151,27 @@
 }
 {60}
 
+#alias {ticklist}
+{
+	#info tickers save;
+
+	#echo {<128>%+20s %+20s %+20s} {Name} {Interval} {Remaining};
+
+	#draw Yellow scroll line 1 1 1 62;
+
+	#format utime %U;
+
+	#loop 1 &info[TICKERS][] index
+	{
+		#math uval $info[TICKERS][+$index][arg3] * 1000000;
+
+		#echo {%+20s %+20s %+20m}
+			{$info[TICKERS][+$index][arg1]}
+			{$info[TICKERS][+$index][arg3]}
+			{($uval - ($utime - $info[TICKERS][+$index][arg4]) % $uval) / 1000000.00}
+	}
+}
+
 #nop -------------------------------------------------------------------------
 #nop Execute speedwalks with .
 #nop -------------------------------------------------------------------------
@@ -321,27 +342,27 @@
 
 #function spellcheck
 {
-        #format result %S %1;
-        #if {$result == 0}
-        {
-                #var result %1
-        };
-        #else
-        {
-                #var result <118>%1<900>
-        };
-        #list speedread ins -1 {$result}
+	#format result %S %1;
+	#if {$result == 0}
+	{
+		#var result %1
+	};
+	#else
+	{
+		#var result <118>%1<900>
+	};
+	#list speedread ins -1 {$result}
 }
 
 #substitute {{\b[a-zA-Z]+\b}} {@spellcheck{%1}}
 
 #tick {speedread}
 {
-        #if {&{speedread[]}}
-        {
-                #draw tile -2 1 -2 20 {$speedread[1]};
-                #list speedread delete 1
-        }
+	#if {&{speedread[]}}
+	{
+		#draw tile -2 1 -2 20 {$speedread[1]};
+		#list speedread delete 1
+	}
 }
 {0.1}
 
@@ -448,33 +469,33 @@
 #nop Move down by pressing arrow left + right simultaniously.
 #nop -------------------------------------------------------------------------
 
-#macro {\e[1;5A} {#cursor preserve;#delay {move} {#cursor reset_macro;n} {0.05}}
-#macro {\e[1;5C} {#cursor preserve;#delay {move} {#cursor reset_macro;e} {0.05}}
-#macro {\e[1;5B} {#cursor preserve;#delay {move} {#cursor reset_macro;s} {0.05}}
-#macro {\e[1;5D} {#cursor preserve;#delay {move} {#cursor reset_macro;w} {0.05}}
+#macro {\e[1;5A} {#cursor macro preserve;#delay {move} {#cursor macro reset;n} {0.05}}
+#macro {\e[1;5C} {#cursor macro preserve;#delay {move} {#cursor macro reset;e} {0.05}}
+#macro {\e[1;5B} {#cursor macro preserve;#delay {move} {#cursor macro reset;s} {0.05}}
+#macro {\e[1;5D} {#cursor macro preserve;#delay {move} {#cursor macro reset;w} {0.05}}
 
-#macro {\e[1;5A\e[1;5A} {#undelay {move};#cursor reset_macro;n;n}
-#macro {\e[1;5C\e[1;5C} {#undelay {move};#cursor reset_macro;e;e}
-#macro {\e[1;5B\e[1;5B} {#undelay {move};#cursor reset_macro;s;s}
-#macro {\e[1;5D\e[1;5D} {#undelay {move};#cursor reset_macro;w;w}
+#macro {\e[1;5A\e[1;5A} {#undelay {move};#cursor macro reset;n;n}
+#macro {\e[1;5C\e[1;5C} {#undelay {move};#cursor macro reset;e;e}
+#macro {\e[1;5B\e[1;5B} {#undelay {move};#cursor macro reset;s;s}
+#macro {\e[1;5D\e[1;5D} {#undelay {move};#cursor macro reset;w;w}
 
-#macro {\e[1;5A\e[1;5B} {#undelay {move};#cursor reset_macro;u}
-#macro {\e[1;5B\e[1;5A} {#undelay {move};#cursor reset_macro;u}
+#macro {\e[1;5A\e[1;5B} {#undelay {move};#cursor macro reset;u}
+#macro {\e[1;5B\e[1;5A} {#undelay {move};#cursor macro reset;u}
 
-#macro {\e[1;5C\e[1;5D} {#undelay {move};#cursor reset_macro;d}
-#macro {\e[1;5D\e[1;5C} {#undelay {move};#cursor reset_macro;d}
+#macro {\e[1;5C\e[1;5D} {#undelay {move};#cursor macro reset;d}
+#macro {\e[1;5D\e[1;5C} {#undelay {move};#cursor macro reset;d}
 
-#macro {\e[1;5A\e[1;5C} {#undelay {move};#cursor reset_macro;ne}
-#macro {\e[1;5C\e[1;5A} {#undelay {move};#cursor reset_macro;ne}
+#macro {\e[1;5A\e[1;5C} {#undelay {move};#cursor macro reset;ne}
+#macro {\e[1;5C\e[1;5A} {#undelay {move};#cursor macro reset;ne}
 
-#macro {\e[1;5B\e[1;5C} {#undelay {move};#cursor reset_macro;se}
-#macro {\e[1;5C\e[1;5B} {#undelay {move};#cursor reset_macro;se}
+#macro {\e[1;5B\e[1;5C} {#undelay {move};#cursor macro reset;se}
+#macro {\e[1;5C\e[1;5B} {#undelay {move};#cursor macro reset;se}
 
-#macro {\e[1;5D\e[1;5B} {#undelay {move};#cursor reset_macro;sw}
-#macro {\e[1;5B\e[1;5D} {#undelay {move};#cursor reset_macro;sw}
+#macro {\e[1;5D\e[1;5B} {#undelay {move};#cursor macro reset;sw}
+#macro {\e[1;5B\e[1;5D} {#undelay {move};#cursor macro reset;sw}
 
-#macro {\e[1;5D\e[1;5A} {#undelay {move};#cursor reset_macro;nw}
-#macro {\e[1;5A\e[1;5D} {#undelay {move};#cursor reset_macro;nw}
+#macro {\e[1;5D\e[1;5A} {#undelay {move};#cursor macro reset;nw}
+#macro {\e[1;5A\e[1;5D} {#undelay {move};#cursor macro reset;nw}
 
 #nop -------------------------------------------------------------------------
 #nop Place tells in the top 5 lines of the screen
@@ -717,13 +738,13 @@
 
 #alias {display}
 {
-        #var out {};
+	#var out {};
 
-        #loop 1 &players[] cnt
-        {
-            #var out[$cnt] {$cnt;$players[+$cnt][name];$players[+$cnt][age];$players[+$cnt][level]};
-        };
-        #draw scroll grid table 1 1 2+&players[]*2 80 $out[%*]
+	#loop 1 &players[] cnt
+	{
+	    #var out[$cnt] {$cnt;$players[+$cnt][name];$players[+$cnt][age];$players[+$cnt][level]};
+	};
+	#draw scroll grid table 1 1 2+&players[]*2 80 $out[%*]
 }
 
 #alias {test1}
@@ -798,22 +819,22 @@
 {
     #if {$SCROLL[MODE] == 0}
     {
-        #if {%0 < $ROWS / 2}
-        {
-            #var SCROLL[MODE] 1;
-            #var SCROLL[OLD_ROW] $SCROLL[BOT_ROW];
-            #math SCROLL[BOT_ROW] $SCROLL[OLD_ROW] / 2;
-            #var BUFFER {};
-            #screen scroll $SCROLL[TOP_ROW] $SCROLL[TOP_COL] $SCROLL[BOT_ROW] $SCROLL[BOT_COL];
-
-            #draw red teed line $SCROLL[BOT_ROW]+1 $SCROLL[TOP_COL] $SCROLL[BOT_ROW]+1 $SCROLL[BOT_COL];
-
-            #screen clear square $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL];
-        };
+	#if {%0 < $ROWS / 2}
+	{
+	    #var SCROLL[MODE] 1;
+	    #var SCROLL[OLD_ROW] $SCROLL[BOT_ROW];
+	    #math SCROLL[BOT_ROW] $SCROLL[OLD_ROW] / 2;
+	    #var BUFFER {};
+	    #screen scroll $SCROLL[TOP_ROW] $SCROLL[TOP_COL] $SCROLL[BOT_ROW] $SCROLL[BOT_COL];
+
+	    #draw red teed line $SCROLL[BOT_ROW]+1 $SCROLL[TOP_COL] $SCROLL[BOT_ROW]+1 $SCROLL[BOT_COL];
+
+	    #screen clear square $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL];
+	};
     };
     #if {$SCROLL[MODE] == 1}
     {
-        #buffer up 1
+	#buffer up 1
     }
 }
 
@@ -821,21 +842,21 @@
 {
     #if {$SCROLL[MODE] == 1}
     {
-        #if {%0 < $ROWS / 2}
-        {
-            #buffer down 1;
+	#if {%0 < $ROWS / 2}
+	{
+	    #buffer down 1;
 
-            #buffer info save SCROLL[INFO];
+	    #buffer info save SCROLL[INFO];
 
-            #if {$SCROLL[INFO][LINE] == -1}
-            {
-                #var SCROLL[MODE] 0;
-                #var SCROLL[BOT_ROW] $SCROLL[OLD_ROW];
+	    #if {$SCROLL[INFO][LINE] == -1}
+	    {
+		#var SCROLL[MODE] 0;
+		#var SCROLL[BOT_ROW] $SCROLL[OLD_ROW];
 
-                #split 0 1;
-                #buffer end;
-            }
-        }
+		#split 0 1;
+		#buffer end;
+	    }
+	}
     }
 }
 
@@ -843,20 +864,44 @@
 {
     #if {$SCROLL[MODE] == 1}
     {
-        #if {&BUFFER[] > $ROWS}
-        {
-            #list BUFFER del 1
-        };
-        #list BUFFER add {%0};
+	#if {&BUFFER[] > $ROWS}
+	{
+	    #list BUFFER del 1
+	};
+	#list BUFFER add {%0};
 
-        #draw tile $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL] $BUFFER[%*];
+	#draw tile $SCROLL[BOT_ROW]+2 $SCROLL[TOP_COL] $SCROLL[OLD_ROW] $SCROLL[BOT_COL] $BUFFER[%*];
     }
 }
 
 #nop -------------------------------------------------------------------------
-#nop 
+#nop This is a script to connect to Gemstone 4.
+#nop Visit play.net/gs4, login, and hit the 'GO PLAY' button.
+#nop Select the Storm Front radio button and hit the 'GO PLAY' button.
+#nop Save the .sal file to your script directory and name it gemstone.sal.
+#nop Use the 'gemstone' alias to connect.
 #nop -------------------------------------------------------------------------
 
+#alias {gemstone}
+{
+    #var gemstone {};
+
+    #line oneshot #action {^GAMEHOST=%*} {#var gemstone[host] %%1};
+    #line oneshot #action {^GAMEPORT=%*} {#var gemstone[port] %%1};
+    #line oneshot #action {^KEY=%*} {#var gemstone[key] %%1};
+
+    #scan txt gemstone.sal;
+
+    #if {&gemstone[] != 3}
+    {
+        #showme Failed to load gemstone.sal file.;
+        #return
+    };
+    #ses gemstone $gemstone[host] $gemstone[port];
+    #send {$gemstone[key]};
+    #send {>/FE:JAVA}
+}
+
 #nop -------------------------------------------------------------------------
 #nop 
 #nop -------------------------------------------------------------------------

+ 97 - 3
TODO

@@ -1,11 +1,84 @@
-* BUGS
+  - double check packet patch code, gagging patched line? Echo command?
 
-  - Look into escaped color codes in zmp, possibly msdp
+  - look into large variable handling, foreach, once again
 
-  - See about making @$var{} work.
 
+  - 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}
+
+----------------
+
+  - 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 #event {SESSION CONNECTED} {5.1} option.
+
+  - allow using #snoop to print to the foreground in provided square?
+
+  - #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 the option to use + ? . and * as variable exit fields. 
+
+  - 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)
+
+  - 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}{}
+
   - finish BUFFER_SIZE replacement.
 
   - WSL faq: #system cmd.exe /c start notepad
@@ -25,8 +98,12 @@
 
   - 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
 
+  - #path get position saves as 1 if no path is loaded. 
+
   - Finish port proxy support: resizing, input, security
 
   - look into transparent drawing
@@ -51,6 +128,22 @@
   - tabbing on directory structure.
   - tabbing on dictionary
 
+#0  0x00005555555a5418 in tunnel_void (ses=0x555558a97b00, from=8004, room=1931506785, dir=1684955508) at mapper.c:4220
+#1  0x00005555555a599d in searchgrid_find (ses=0x555558a97b00, from=153, search=0x555558d8f850) at mapper.c:4336
+#2  0x00005555555afb44 in map_list (ses=0x555558a97b00, arg=0x5555572e1b95 "{} {} {} {$roomarea} {variable} {area_mapped}",
+    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.
   - finish landmarks
   - map sandbox mode support (flags to disable saving?)
@@ -71,6 +164,7 @@
   - more data to #map list saving, and maybe easier sorting of tables.
   - event for failed #map move.
   - look into #send triggering follow map.
+  - add {roomdata} search to #map list
 
   - truncate prompt longer than split.
 

+ 85 - 53
docs/help.html

@@ -175,9 +175,10 @@ a:active {color:#b06}
 
 </span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #break
 
-         The break command can be used inside the #foreach, #loop, #parse,
-         #while and #switch statements. When #break is found, tintin will stop
-         executing the statement it is currently in and move on to the next.
+         The break command can be used inside the #else, #elseif, #if, #foreach,
+         #loop, #parse, #switch, and #while statements. When #break is found,
+         tintin will stop executing the statement it is currently in and move on
+         to the next.
 
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #while {1} {#math cnt &dollar;cnt + 1;#if {&dollar;cnt == 20} {#break}}
 
@@ -360,8 +361,9 @@ a:active {color:#b06}
 &bsol;        An input line starting with a backslash is send verbatim if you are
          connected to a server. This character can be configured with
          #config, and is itself send verbatim when the verbatim config mode
+         is enabled.
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#IS'>is</a>, <a href='#ENABLED.'>enabled.</a>, <a href='#COLORS'>colors</a>, <a href='#ESCAPE'>escape</a>, <a href='#FUNCTION'>function</a>, <a href='#MATHEMATICS'>mathematics</a>, <a href='#PCRE'>pcre</a> and <a href='#VARIABLE'>variable</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#COLORS'>colors</a>, <a href='#ESCAPE'>escape</a>, <a href='#FUNCTION'>function</a>, <a href='#MATHEMATICS'>mathematics</a>, <a href='#PCRE'>pcre</a> and <a href='#VARIABLE'>variable</a>.
 <a name='CHAT'></a>
 
 </span><span style='color:#5F5'>         CHAT
@@ -680,12 +682,12 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 </span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #delay </span><span style='color:#FFF'>{</span><span style='color:#AAA'>name</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>command</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>seconds</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
 
          Delay allows you to have tintin wait the given amount of seconds
-         before executing the given command. tintin won't wait before
-         executing following input commands if any.
+         before executing the given command.
 
-         Floating point precision for milliseconds is possible.
+         Nanosecond floating point precision is allowed. Delays will fire in
+         0.01 second intervals.
 
-</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #show first;#delay {1} {#show last}
+</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #delay {1} {#show last};#show first
          This will print 'first', and 'last' around one second later.
 
 </span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: If you want to remove a delay with the #undelay command you can add
@@ -698,13 +700,13 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
 </span><span style='color:#5F5'>         DRAW
 
-</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #draw </span><span style='color:#FFF'>[</span><span style='color:#AAA'>color</span><span style='color:#FFF'>] [</span><span style='color:#AAA'>options</span><span style='color:#FFF'>] &lt;</span><span style='color:#AAA'>type</span><span style='color:#FFF'>&gt; &lt;</span><span style='color:#AAA'>square</span><span style='color:#FFF'>&gt; {</span><span style='color:#AAA'>text</span><span style='color:#FFF'>}
+</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #draw </span><span style='color:#FFF'>[</span><span style='color:#AAA'>line color</span><span style='color:#FFF'>] [</span><span style='color:#AAA'>options</span><span style='color:#FFF'>] &lt;</span><span style='color:#AAA'>type</span><span style='color:#FFF'>&gt; &lt;</span><span style='color:#AAA'>square</span><span style='color:#FFF'>&gt; {</span><span style='color:#AAA'>text</span><span style='color:#FFF'>}
 </span><span style='color:#AAA'>
          The draw commands allows you to draw various types of lines and shapes
-         on the screen. Common options and types with a brief description are
-         provided when you type #draw without an argument.
+         on the screen. The types with a brief description are provided when you
+         type #draw without an argument.
 
-         The square arguments should exists of two coordinates defining the
+         The &lt;square&gt; arguments should exists of two coordinates defining the
          upper left and bottom right corner using row, col, row, col syntax.
 
          The square arguments can be negative, in which case the coordinates
@@ -758,24 +760,26 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
          The following types are available.
 
-         </span><span style='color:#FFF'>[ASCII|UNICODE|HUGE] BOX {[TEXT1]} {[TEXT2]}
-         </span><span style='color:#AAA'>  will draw a box.
-         </span><span style='color:#FFF'>[BOXED|FOREGROUND] BUFFER
+         [HORIZONTAL] </span><span style='color:#FFF'>BAR</span><span style='color:#AAA'> {&lt;MIN&gt;;&lt;MAX&gt;;[COLOR]}
+          will draw a bar.
+         [ASCII|UNICODE|HUGE] </span><span style='color:#FFF'>BOX</span><span style='color:#AAA'> {[TEXT1]} {[TEXT2]}
+           will draw a box.
+         [BOXED|FOREGROUND] </span><span style='color:#FFF'>BUFFER
          </span><span style='color:#AAA'>  will draw the scrollback buffer.
-         </span><span style='color:#FFF'>[BLANKED|CIRCLED|CROSSED|JEWELED|ROUNDED|TEED|PRUNED] CORNER
+         [BLANKED|CIRCLED|CROSSED|JEWELED|ROUNDED|TEED|PRUNED] </span><span style='color:#FFF'>CORNER
          </span><span style='color:#AAA'>  will draw a corner.
-         </span><span style='color:#FFF'>[BLANKED|HORIZONTAL|NUMBERED|TUBED|VERTICAL] LINE {[TEXT]}
-         </span><span style='color:#AAA'>  will draw a line.
-         </span><span style='color:#FFF'>[BOXED] MAP
+         [BLANKED|HORIZONTAL|NUMBERED|TUBED|VERTICAL] </span><span style='color:#FFF'>LINE</span><span style='color:#AAA'> {[TEXT]}
+           will draw a line.
+         [BOXED] </span><span style='color:#FFF'>MAP
          </span><span style='color:#AAA'>  will draw the map
-         </span><span style='color:#FFF'>RAIN {&lt;VARIABLE&gt;} {[SPAWN]} {[FADE]} {[LEGEND]}
-         </span><span style='color:#AAA'>  will draw digital rain.
-         </span><span style='color:#FFF'>[JOINTED|TOP|LEFT|BOTTOM|RIGHT] SIDE
+         </span><span style='color:#FFF'>RAIN</span><span style='color:#AAA'> {&lt;VARIABLE&gt;} {[SPAWN]} {[FADE]} {[LEGEND]}
+           will draw digital rain.
+         [JOINTED|TOP|LEFT|BOTTOM|RIGHT] </span><span style='color:#FFF'>SIDE
          </span><span style='color:#AAA'>  will draw one or more sides of a box.
-         </span><span style='color:#FFF'>[GRID] TABLE {[LIST1]} {[LIST2]}
-         </span><span style='color:#AAA'> will draw a table.
-         </span><span style='color:#FFF'>[HUGE] TILE {[TEXT1]} {[TEXT2]}
-         </span><span style='color:#AAA'>  will draw a tile
+         [GRID] </span><span style='color:#FFF'>TABLE</span><span style='color:#AAA'> {[LIST1]} {[LIST2]}
+          will draw a table.
+         [CURSIVE|FAT|HUGE|SANSSERIF] </span><span style='color:#FFF'>TILE</span><span style='color:#AAA'> {[TEXT1]} {[TEXT2]}
+           will draw a tile
 
          All draw types take an optional text argument as long as a valid
          square with enough space has been defined. Text is automatically
@@ -1020,7 +1024,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
 </span><span style='color:#5F5'>         EVENT
 
-</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #event </span><span style='color:#FFF'>{</span><span style='color:#AAA'>event type</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
+</span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #event </span><span style='color:#FFF'>{</span><span style='color:#AAA'>event type</span><span style='color:#FFF'>}</span><span style='color:#AAA'> </span><span style='color:#FFF'>{</span><span style='color:#AAA'>commands</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
 
          Events allow you to create triggers for predetermined client events.
 
@@ -1029,7 +1033,8 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          events. Use #info {events} {on} to see events get thrown.
 
          Events, like triggers in general, are case sensitive and event names
-         must be defined using all upper case letters.
+         must be defined using all upper case letters. Only one event can be
+         defined for each event type.
 
          To enable mouse events use #config mouse_tracking on, to see mouse
          events use #config mouse_tracking info.
@@ -1108,6 +1113,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          </span><span style='color:#AAA'>  Mouse events can be prefixed with MAP to only trigger when the mouse
            event occurs inside the VT100 map region.
 
+
          </span><span style='color:#FFF'>SWIPED [DIR]
          </span><span style='color:#AAA'>  %0 dir  %1 button  %2 row  %3 col  %4 -row  %5 -col
                               %6 row  %7 col  %8 -row  %9 -col %10 rows %11 cols
@@ -1152,7 +1158,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
          </span><span style='color:#FFF'>IAC &lt;EVENT&gt;
          </span><span style='color:#AAA'>  IAC TELNET events are made visable using #config telnet info.
 
-         </span><span style='color:#FFF'>IAC SB GMCP [MODULE]   %0 module    %1 data  %1 plain data
+         </span><span style='color:#FFF'>IAC SB GMCP [MODULE]   %0 module    %1 data  %2 plain data
          IAC SB MSSP            %0 variable  %1 data
          IAC SB MSDP            %0 variable  %1 data  %2 plain data
          IAC SB MSDP [VAR]      %0 variable  %1 data  %2 plain data
@@ -1177,7 +1183,9 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
          </span><span style='color:#5F5'>SCREEN EVENTS</span><span style='color:#AAA'>
 
-         SCREEN FOCUS           %0 focus (0 or 1)
+         </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
@@ -1199,8 +1207,8 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
          </span><span style='color:#5F5'>VARIABLE EVENTS</span><span style='color:#AAA'>
 
-         VARIABLE UPDATE [VAR]  %0 name %1 new value
-         VARIABLE UPDATED [VAR] %0 name %1 new value
+         VARIABLE UPDATE &lt;VAR&gt;  %0 name %1 new value %2 path
+         VARIABLE UPDATED &lt;VAR&gt; %0 name %1 new value %2 path
 
          </span><span style='color:#5F5'>VT100 EVENTS</span><span style='color:#AAA'>
 
@@ -1332,7 +1340,7 @@ Related</span><span style='color:#AAA'>: <a href='#PORT'>port</a>
 
 </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.04b                    </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'>                                                                  </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'>#
@@ -1936,9 +1944,10 @@ Terminal -&gt; Window Settings -&gt; Emulation.
          #list {var} {delete} {index} {number}  Delete the item at {index},
                                                 the {number} is optional.
          #list {var} {explode}                  Turn list into a character list
-         #list {var} {index}                    Index a list table for sorting
+         #list {var} {indexate}                 Index a list table for sorting
          #list {var} {insert} {index} {string}  Insert {string} at given index
-         #list {var} {find} {string} {variable} Return the found index
+         #list {var} {filter} {keep} {remove}   Filter with keep / remove regex
+         #list {var} {find} {regex} {variable}  Return the found index
          #list {var} {get} {index} {variable}   Copy an item to {variable}
          #list {var} {order} {string}           Insert item in numerical order
          #list {var} {shuffle}                  Shuffle the list
@@ -2256,6 +2265,8 @@ Terminal -&gt; Window Settings -&gt; Emulation.
 
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #alias {swap} {#local x %0;#replace x {e} {u};#show &dollar;x}
 
+</span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: You can remove a local variable with the #unlocal command.
+
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#FORMAT'>format</a>, <a href='#FUNCTION'>function</a>, <a href='#MATH'>math</a>, <a href='#REPLACE'>replace</a>, <a href='#SCRIPT'>script</a> and <a href='#VARIABLE'>variable</a>.
 <a name='LOG'></a>
 
@@ -2499,11 +2510,10 @@ Terminal -&gt; Window Settings -&gt; Emulation.
            variable name.
 
          </span><span style='color:#FFF'>#map move &lt;direction&gt;
-         </span><span style='color:#AAA'>  This does the same as an actual movement
-           command, updating your location on the map and creating new
-           rooms. Useful when you are following someone and want the map
-           to follow. You will need to create actions using '#map move',
-           for this to work.
+         </span><span style='color:#AAA'>  This does the same as an actual movement command, updating your
+           location on the map and creating new rooms. Useful when you are
+           following someone and want the map to follow along. You will need
+           to create actions using '#map move', for this to work.
 
          </span><span style='color:#FFF'>#map offset &lt;row&gt; &lt;col&gt; &lt;row&gt; &lt;col&gt;
          </span><span style='color:#AAA'>  Define the offset of the vtmap as a square. Without an argument
@@ -2616,7 +2626,7 @@ Terminal -&gt; Window Settings -&gt; Emulation.
          </span><span style='color:#AAA'>  Will save the map, if you want to save a map to a .tin file
            you must provide the {force} argument.
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#PATH'>path</a> and <a href='#PATHDIR'>pathdir</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#PATH'>path</a>, <a href='#PATHDIR'>pathdir</a> and <a href='#SPEEDWALK'>speedwalk</a>.
 <a name='MAPPING'></a>
 
 </span><span style='color:#5F5'>         MAPPING
@@ -3027,7 +3037,7 @@ Website: https://tintin.mudhalla.net/protocols/mslp
 
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #path ins {unlock n;open n} {unlock s;open s}
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#MAP'>map</a> and <a href='#PATHDIR'>pathdir</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#MAP'>map</a>, <a href='#PATHDIR'>pathdir</a> and <a href='#SPEEDWALK'>speedwalk</a>.
 <a name='PATHDIR'></a>
 
 </span><span style='color:#5F5'>         PATHDIR
@@ -3363,7 +3373,8 @@ Example: #action {~&bsol;e[1;37m%1} {#var roomname %1}
          The expression can contain escapes, and if you want to match a literal
          &bsol; character you'll have to use &bsol;&bsol; to match a single backslash.
 
-         Variables are stored in &amp;1 to &amp;99 with &amp;0 holding the matched substring.
+         Variables are stored in &amp;1 to &amp;99 with &amp;0 holding the matched
+         substring.
 
        ^ force match of start of line.
        &dollar; force match of end of line.
@@ -3410,7 +3421,9 @@ Example: #action {~&bsol;e[1;37m%1} {#var roomname %1}
 
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #regexp {bli bla blo} {bli {.*} blo} {#show &amp;1}
 
-</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='#IF'>if</a> and <a href='#SWITCH'>switch</a>.
+</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>
 <a name='REPEAT'></a>
 
 </span><span style='color:#5F5'>         REPEAT
@@ -3429,10 +3442,13 @@ easiest way to accomplish that.
 
 </span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #replace </span><span style='color:#FFF'>{</span><span style='color:#AAA'>variable</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>oldtext</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>newtext</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
 
-         Searches the variable text replacing each occurrence of 'oldtext' with
-         'newtext'. The 'newtext' argument can be a regular expression.
+         Searches the given variable, replacing each occurrence of 'oldtext'
+         with 'newtext'. The 'oldtext' argument is a regular expression.
+
+         Variables are stored in &amp;1 to &amp;99 with &amp;0 holding the entire matched
+         substring.
 
-         Variables are stored in &amp;1 to &amp;99 with &amp;0 holding the matched substring.
+</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #function rnd #math result 1d9;#replace test {%.} {@rnd{}}
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CAT'>cat</a>, <a href='#FORMAT'>format</a>, <a href='#FUNCTION'>function</a>, <a href='#LOCAL'>local</a>, <a href='#MATH'>math</a>, <a href='#SCRIPT'>script</a> and <a href='#VARIABLE'>variable</a>.
 <a name='RETURN'></a>
@@ -3733,9 +3749,10 @@ session one will remain the active session.
 
 </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'>
 
-         If there are multiple sessions active, this command allows you to monitor
-         what is going on in the sessions that are not currently active.  The
-         line of text from other sessions will be prefixed by the session's name.
+         If there are multiple sessions active, this command allows you to
+         monitor what is going on in the sessions that are not currently active.
+         The line of text from other sessions will be prefixed by the session's
+         name.
 
          You can toggle off snoop mode by executing #snoop a second time.
 
@@ -3744,6 +3761,7 @@ session one will remain the active session.
 
 </span><span style='color:#5F5'>         SPEEDWALK
 
+         SPEEDWALK V1
 </span><span style='color:#AAA'>
          Speedwalking allows you to enter multiple directions without using
          semicolons. Directions should be prefixed with a number and will be
@@ -3754,9 +3772,21 @@ session one will remain the active session.
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: Without speedwalk, you have to type:
          </span><span style='color:#FFF'>s;s;w;w;w;w;w;s;s;s;w;w;w;n;n;w
          </span><span style='color:#AAA'>With speedwalk, you only have to type:
-         </span><span style='color:#FFF'>2s5w3s3w2n1w
+         </span><span style='color:#FFF'>2s5w3s3w2nw
+
+         </span><span style='color:#5F5'>SPEEDWALK V2
+</span><span style='color:#AAA'>
+         Modern MUDs have increasingly adopted the use of diagonal exits, like
+         ne, nw, sw, and se. To make accomodations for this the #map and #path
+         command no longer interpret nesw as a speedwalk and require this to
+         be written as 1n1e1s1w, which then allows 2ne2e to execute ne;ne;e;e.
+
+         Speedwalks entered on the input line continue to use the v1 system.
+
+</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #path unzip 3n1e2nw
+</span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #map move 3ne1d
 
-Related</span><span style='color:#AAA'>: <a href='#ALIAS'>alias</a>, <a href='#CURSOR'>cursor</a>, <a href='#HISTORY'>history</a>, <a href='#KEYPAD'>keypad</a>, <a href='#MACRO'>macro</a> and <a href='#TAB'>tab</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#ALIAS'>alias</a>, <a href='#CURSOR'>cursor</a>, <a href='#HISTORY'>history</a>, <a href='#KEYPAD'>keypad</a>, <a href='#MACRO'>macro</a> and <a href='#TAB'>tab</a>.
 <a name='SPLIT'></a>
 
 </span><span style='color:#5F5'>         SPLIT
@@ -3963,7 +3993,9 @@ Related</span><span style='color:#AAA'>: <a href='#ALL'>all</a>, <a href='#PORT'
 
 </span><span style='color:#FFF'>Command</span><span style='color:#AAA'>: #ticker </span><span style='color:#FFF'>{</span><span style='color:#AAA'>name</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>commands</span><span style='color:#FFF'>} {</span><span style='color:#AAA'>interval in seconds</span><span style='color:#FFF'>}</span><span style='color:#AAA'>
 
-         Executes given command every # of seconds.
+         Executes given command every # of seconds. Floating point precision
+         for the interval is allowed. A ticker cannot fire more often than
+         10 times per second.
 
 </span><span style='color:#FFF'>Comment</span><span style='color:#AAA'>: Tickers don't work in the startup session.
 

+ 61 - 0
mods/igr.mods

@@ -1,3 +1,64 @@
+Nov 2020        2.02.06
+
+------------------------------------------------------------------------------
+
+split.c         Now allowing #showme {text} {-1} to place text on the input
+                line without #split being enabled.
+
+trigger.c       Changed #tick to lazily get the second argument.
+
+files.c         Added the READ FILE [NAME] event, triggers after a file has
+                been read. %0 holds the file name.
+
+draw.c          Added color gradient support to #draw bar. To use it you
+                must specify two 256 color foreground codes for the color
+                field and based on the min;max value it will pick a color
+                somewhere in between.
+
+		#loop 1 9 i #draw <DDF> scroll bar 1 1 1 40 {$i;9;<faa><afa>}
+
+draw.c          Added the BAR drawing type. Currently only horizontal bars
+                are supported, but for forward compatibility you should draw
+                bars using #draw horizontal bar {square} {<min>;<max>;[color]}
+                The width of the bar will be that of the square coordinate.
+
+trigger.c       Added support for 10 digit precision delays. The main
+                utility of this is execution order.
+
+                #delay 0.00003 #show A;#delay 0.00002 #show B
+
+                Since delays are processed in 0.01 second intervals these will
+                both trigger within 0.01 seconds, but the display order will
+                be: B A rathern than A B.
+
+path.c          Added MAPPING and RUNNING to #path get.
+
+                MAPPING returns 1 when path mapping, otherwise 0.
+                RUNNING returns the delay until the next run, otherwise 0.00.
+
+                #path get <variable> without an argument will store the
+                length, position, mapping, and running values in a table.
+
+trigger.c       Storing the creation time of tickers and delays in arg4, can
+                be obtained using #info tickers/delays save.
+
+substitute.c    Added support to call @function{} as @{function}{}.
+
+event.c         The SCREEN FOCUS event no longer requires #config mouse to
+                be enabled.
+
+math.c          % in #math now supports floating point modulo operations.
+
+data.c          #info will save #info variables to $info[VARIABLES] rather
+                than $info[VARIABLE]. Same for other lists.
+
+list.c          Added #list {var} filter {keep} {remove}. Keep and remove
+                must be a regex pattern, the keep regex is ignored if {} is
+                used, the remove regex is optional. #list indexate must be
+                used to filter tables.
+
+utf8.c          Added #config charset cp949 for Korean.
+
 Oct 2020        2.02.05
 ------------------------------------------------------------------------------
 

+ 0 - 3
src/Makefile.in

@@ -90,9 +90,6 @@ Makefile: Makefile.in
 install: tt++
 	-mkdir -p $(bindir)
 	cp -f tt++ $(bindir)
-#	-mkdir -p $(docdir)
-#	cp ../docs/* ../[A-Z][A-Z]* $(docdir)
-
 
 # Autocompile all .c files into .o files using this rule:
 %.o: %.c $(HEADERS)

+ 13 - 13
src/banner.c

@@ -106,25 +106,25 @@ void banner_init(struct session *ses, char *arg1)
 
 	banner_website(ses, "Lost Souls", "http://lostsouls.org", arg1);
 	banner_address(ses, "Lost Souls", "ls lostsouls.org 23", arg1);
-	banner_expires(ses, "Lost Souls", "2025", arg1);
+	banner_expires(ses, "Lost Souls", "2026", arg1);
 
 
 	banner_create(ses, "Legends of Kallisti", arg1);
 
 	banner_desc(ses, "Legends of Kallisti",
-		"One of the longest running, most feature rich MUDs in the world with decades of\n"
-		"development. Kallisti boasts a massive original world, great atmosphere of long\n"
-		"time players, excellent combat system including group formations, ranged combat,\n"
-		"optional PK and arena PvP, extensive character customization options, player\n"
-		"lineages, clans, customizable player houses, item crafting, extensively\n"
-		"customizable UI, Mud Sound Protocol (MSP), MSDP, and so much more.\n"
-		"\n"
-		"This is an a amazing game that you could literally play for a decade and still\n"
+		"One of the longest running, most feature rich MUDs in the world with decades\n"
+		"of development. Kallisti boasts a massive original world, great atmosphere of\n"
+		"players, excellent combat system including group formations, ranged combat,\n"
+		"optional PK and arena PvP, extensive character customization, player lineages,\n"
+		"clans, customizable player houses, item crafting, extensively customizable UI,\n"
+		"Mud Sound Protocol, extensive blind player support, MSDP, and so much more.\n"
+		"\n"
+		"This is an amazing game that you could literally play for a decade and still\n"
 		"discover more - you won't be disappointed!", arg1);
 
 	banner_website(ses, "Legends of Kallisti", "http://www.KallistiMUD.com", arg1);
 	banner_address(ses, "Legends of Kallisti", "LoK kallistimud.com 4000", arg1);
-	banner_expires(ses, "Legends of Kallisti", "2025", arg1);
+	banner_expires(ses, "Legends of Kallisti", "2026", arg1);
 
 
 	banner_create(ses, "3Kingdoms", arg1);
@@ -142,7 +142,7 @@ void banner_init(struct session *ses, char *arg1)
 
 	banner_website(ses, "3Kingdoms", "http://3k.org", arg1);
 	banner_address(ses, "3Kingdoms", "3K 3k.org 3000", arg1);
-	banner_expires(ses, "3Kingdoms", "2025", arg1);
+	banner_expires(ses, "3Kingdoms", "2026", arg1);
 
 
 	banner_create(ses, "New World Ateraan", arg1);
@@ -159,7 +159,7 @@ void banner_init(struct session *ses, char *arg1)
 
 	banner_website(ses, "New World Ateraan", "http://www.ateraan.com", arg1);
 	banner_address(ses, "New World Ateraan", "nwa ateraan.com 4002", arg1);
-	banner_expires(ses, "New World Ateraan", "2025", arg1);
+	banner_expires(ses, "New World Ateraan", "2026", arg1);
 
 
 	banner_create(ses, "Realm of Utopian Dreams (RUD)", arg1);
@@ -176,7 +176,7 @@ void banner_init(struct session *ses, char *arg1)
 
 	banner_website(ses, "Realm of Utopian Dreams (RUD)", "http://rudmud.com", arg1);
 	banner_address(ses, "Realm of Utopian Dreams (RUD)", "rud rudmud.com 1701", arg1);
-	banner_expires(ses, "Realm of Utopian Dreams (RUD)", "2025", arg1);
+	banner_expires(ses, "Realm of Utopian Dreams (RUD)", "2026", arg1);
 
 	banner_create(ses, "Carrion Fields", arg1);
 

+ 5 - 2
src/buffer.c

@@ -830,7 +830,10 @@ DO_BUFFER(buffer_lock)
 
 	if (!strcasecmp(arg1, "ON"))
 	{
-		ses->scroll->line = ses->scroll->used + 1;
+		if (ses->scroll->line == -1)
+		{
+			ses->scroll->line = ses->scroll->used - 1;
+		}
 	}
 	else if (!strcasecmp(arg1, "OFF"))
 	{
@@ -840,7 +843,7 @@ DO_BUFFER(buffer_lock)
 	{
 		if (ses->scroll->line == -1)
 		{
-			ses->scroll->line = ses->scroll->used + 1;
+			ses->scroll->line = ses->scroll->used - 1;
 		}
 		else
 		{

+ 43 - 159
src/config.c

@@ -182,104 +182,47 @@ DO_CONFIG(config_charset)
 				DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
 			}
 		}
-		else if (is_abbrev(arg2, "ASCII"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-		}
-		else if (is_abbrev(arg2, "BIG-5"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_BIG5);
-		}
-		else if (is_abbrev(arg2, "GBK-1"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_GBK1);
-		}
-		else if (is_abbrev(arg2, "UTF-8"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_UTF8);
-		}
-		else if (is_abbrev(arg2, "BIG5TOUTF8") || is_abbrev(arg2, "BIG2UTF"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_UTF8|CHARSET_FLAG_BIG5TOUTF8);
-		}
-		else if (is_abbrev(arg2, "CP1251TOUTF8"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_UTF8|CHARSET_FLAG_CP1251TOUTF8);
-		}
-		else if (is_abbrev(arg2, "FANSI"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_UTF8|CHARSET_FLAG_FANSITOUTF8);
-		}
-		else if (is_abbrev(arg2, "GBK1TOUTF8"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_UTF8|CHARSET_FLAG_GBK1TOUTF8);
-		}
-		else if (is_abbrev(arg2, "ISO1TOUTF8"))
-		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO1TOUTF8);
-		}
-		else if (is_abbrev(arg2, "ISO2TOUTF8"))
+		else
 		{
+			for (index = 0 ; *charset_table[index].name ; index++)
+			{
+				if (is_abbrev(arg2, charset_table[index].name))
+				{
+					break;
+				}
+			}
+
+			if (*charset_table[index].name == 0)
+			{
+				show_error(ses, LIST_CONFIG, "#SYNTAX: #CONFIG {CHARSET} <AUTO|ASCII|BIG-5|BIG5TOUTF8|CP1251TOUTF8|CP949|CP949TOUTF8|FANSI|GBK-1|GBK1TOUTF8|ISO1TOUTF8|ISO2TOUTF8|KOI8TOUTF8|UTF-8>");
+
+				return NULL;
+			}
+
 			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO2TOUTF8);
+
+			SET_BIT(ses->charset, charset_table[index].flags);
 		}
-		else if (is_abbrev(arg2, "KOI8TOUTF8"))
+	}
+	else
+	{
+		for (index = 0 ; *charset_table[index].name ; index++)
 		{
-			DEL_BIT(ses->charset, CHARSET_FLAG_ALL);
-			SET_BIT(ses->charset, CHARSET_FLAG_UTF8|CHARSET_FLAG_KOI8TOUTF8);
+			if (ses->charset == charset_table[index].flags)
+			{
+				break;
+			}
 		}
-		else
+
+		if (*charset_table[index].name == 0)
 		{
-			show_error(ses, LIST_CONFIG, "#SYNTAX: #CONFIG {%s} <AUTO|ASCII|BIG-5|BIG5TOUTF8|CP1251TOUTF8|FANSI|GBK-1|GBK1TOUTF8|ISO1TOUTF8|ISO2TOUTF8|KOI8TOUTF8|UTF-8>", config_table[index].name);
+			show_error(ses, LIST_CONFIG, "#CONFIG CHARSET: INVALID FLAG: %d", ses->charset);
 
 			return NULL;
 		}
 	}
 
-	switch (HAS_BIT(ses->charset, CHARSET_FLAG_ALL))
-	{
-		case CHARSET_FLAG_BIG5:
-			strcpy(arg2, "BIG-5");
-			break;
-		case CHARSET_FLAG_GBK1:
-			strcpy(arg2, "GBK-1");
-			break;
-		case CHARSET_FLAG_UTF8:
-			strcpy(arg2, "UTF-8");
-			break;
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_BIG5TOUTF8:
-			strcpy(arg2, "BIG5TOUTF8");
-			break;
-	        case CHARSET_FLAG_UTF8|CHARSET_FLAG_CP1251TOUTF8:
-	        	strcpy(arg2, "CP1251TOUTF8");
-	        	break;
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_FANSITOUTF8:
-			strcpy(arg2, "FANSI");
-			break;
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_GBK1TOUTF8:
-			strcpy(arg2, "GBK1TOUTF8");
-			break;
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_KOI8TOUTF8:
-			strcpy(arg2, "KOI8TOUTF8");
-			break;
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO1TOUTF8:
-			strcpy(arg2, "ISO1TOUTF8");
-			break;
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO2TOUTF8:
-			strcpy(arg2, "ISO2TOUTF8");
-			break;
-		default:
-			strcpy(arg2, "ASCII");
-			break;
-	}
+	strcpy(arg2, charset_table[index].name);
 
 	return ses;
 }
@@ -316,6 +259,11 @@ DO_CONFIG(config_colormode)
 		{
 			ses->color = 0;
 		}
+		else if (is_abbrev(arg2, "REVERSE"))
+		{
+			ses->color = 0;
+			printf("\e[30m");
+		}
 		else if (is_abbrev(arg2, "ANSI"))
 		{
 			ses->color = 16;
@@ -617,14 +565,14 @@ DO_CONFIG(config_mousetracking)
 		DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);
 		DEL_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
 
-		if (is_member(arg2, "INFO"))
+		if (is_member(arg2, "DEBUG"))
 		{
-			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
+			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
 			SET_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
 		}
-		if (is_member(arg2, "DEBUG"))
+		if (is_member(arg2, "INFO"))
 		{
-			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
+			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
 			SET_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
 		}
 		if (is_member(arg2, "ON"))
@@ -639,14 +587,7 @@ DO_CONFIG(config_mousetracking)
 
 		if (is_abbrev(arg2, "OFF"))
 		{
-			if (HAS_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING))
-			{
-				DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
-				DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
-				DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);
-				DEL_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
-				print_stdout(0, 0, "\e[?1000l\e[?1002l\e[?1004l\e[?1006l\e[?1016l");
-			}
+			print_stdout(0, 0, "\e[?1000l\e[?1002l\e[?1006l\e[?1016l");
 		}
 		else
 		{
@@ -654,11 +595,11 @@ DO_CONFIG(config_mousetracking)
 			{
 				if (HAS_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS))
 				{
-					print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1004h\e[?1016h");
+					print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1016h");
 				}
 				else
 				{
-					print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1004h\e[?1006h");
+					print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1006h");
 				}
 			}
 			else
@@ -668,63 +609,6 @@ DO_CONFIG(config_mousetracking)
 				return NULL;
 			}
 		}
-/*
-		if (is_abbrev(arg2, "ON"))
-		{
-			DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
-			DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
-			DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);
-			SET_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
-			print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1004h\e[?1006h");
-		}
-		else if (is_abbrev(arg2, "PIXELS"))
-		{
-			DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
-			DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
-			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);
-			SET_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
-		
-			print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1004h\e[?1016h");
-		}
-		else if (is_abbrev(arg2, "OFF"))
-		{
-			if (HAS_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING))
-			{
-				DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
-				DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
-				DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEPIXELS);
-				DEL_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
-				print_stdout(0, 0, "\e[?1000l\e[?1002l\e[?1004l\e[?1006l");
-			}
-		}
-		else if (is_abbrev(arg2, "DEBUG"))
-		{
-			DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
-			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
-			SET_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
-			print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1004h\e[?1006h");
-		}
-		else if (is_abbrev(arg2, "DEBUG INFO"))
-		{
-			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
-			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
-			SET_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
-			print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1004h\e[?1006h");
-		}
-		else if (is_abbrev(arg2, "INFO"))
-		{
-			DEL_BIT(ses->config_flags, CONFIG_FLAG_MOUSEDEBUG);
-			SET_BIT(ses->config_flags, CONFIG_FLAG_MOUSEINFO);
-			SET_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING);
-			print_stdout(0, 0, "\e[?1000h\e[?1002h\e[?1004h\e[?1006h");
-		}
-		else
-		{
-			show_error(ses, LIST_CONFIG, "#SYNTAX: #CONFIG {%s} <ON|OFF|DEBUG|INFO|DEBUG INFO>", config_table[index].name);
-
-			return NULL;
-		}
-*/
 	}
 
 	if (HAS_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING))
@@ -819,7 +703,7 @@ DO_CONFIG(config_randomseed)
 	{
 		if (is_abbrev(arg2, "AUTO"))
 		{
-			seed_rand(ses, utime());
+			seed_rand(ses, ++gtd->utime);
 		}
 		else if (is_number(arg2))
 		{

+ 2 - 2
src/cursor.c

@@ -702,14 +702,14 @@ DO_CURSOR(cursor_check_line_modified)
 
 	if (gtd->ses->input->raw_len != str_len(gtd->ses->input->buf))
 	{
-		tintin_printf2(ses, "\e[1;31merror: cursor_check_line_modified: raw: %d vs %d", gtd->ses->input->raw_len, str_len(gtd->ses->input->buf));
+		tintin_printf2(ses, "\e[1;31merror: cursor_check_line_modified1: raw: %d vs %d", gtd->ses->input->raw_len, str_len(gtd->ses->input->buf));
 	}
 
 	strip_vt102_width(gtd->ses, gtd->ses->input->buf, &width);
 
 	if (gtd->ses->input->str_len != width)
 	{
-		tintin_printf2(ses, "\e[1;31merror: cursor_check_line_modified: str: %d vs %d", gtd->ses->input->str_len, width);
+		tintin_printf2(ses, "\e[1;31merror: cursor_check_line_modified2: str: %d vs %d", gtd->ses->input->str_len, width);
 	}
 
 	if (gtd->ses->input->str_pos > gtd->ses->input->str_len)

+ 64 - 20
src/data.c

@@ -53,7 +53,7 @@ void kill_list(struct listroot *root)
 	{
 		delete_index_list(root, root->used - 1);
 	}
-//	root->update = 0;
+	root->update = 0;
 }
 
 void free_list(struct listroot *root)
@@ -173,7 +173,7 @@ struct listnode *create_node_list(struct listroot *root, char *arg1, char *arg2,
 			break;
 
 		case LIST_TICKER:
-			node->val64 = gtd->utime + (long long) get_number(root->ses, node->arg3) * 1000000LL;
+			node->val64 = gtd->utime + (long long) tintoi(arg3) * 1000000.0;
 
 			if (node->val64 < gtd->utime_next_tick)
 			{
@@ -241,7 +241,7 @@ struct listnode *update_node_list(struct listroot *root, char *arg1, char *arg2,
 		switch (root->type)
 		{
 			case LIST_TICKER:
-				node->val64 = gtd->utime + (long long) get_number(root->ses, node->arg3) * 1000000LL;
+				node->val64 = gtd->utime + (long long) tintoi(arg3) * 1000000;
 
 				if (node->val64 < gtd->utime_next_tick)
 				{
@@ -286,6 +286,7 @@ struct listnode *update_node_list(struct listroot *root, char *arg1, char *arg2,
 
 			case SORT_ALPHA:
 			case SORT_ALNUM:
+			case SORT_STABLE:
 				break;
 
 			default:
@@ -413,6 +414,7 @@ struct listnode *search_node_list(struct listroot *root, char *text)
 	switch (list_table[root->type].mode)
 	{
 		case SORT_ALPHA:
+		case SORT_STABLE:
 			index = bsearch_alpha_list(root, text, 0);
 			break;
 
@@ -444,6 +446,7 @@ int search_index_list(struct listroot *root, char *text, char *priority)
 	switch (list_table[root->type].mode)
 	{
 		case SORT_ALPHA:
+		case SORT_STABLE:
 			return bsearch_alpha_list(root, text, 0);
 		
 		case SORT_ALNUM:
@@ -472,23 +475,62 @@ int locate_index_list(struct listroot *root, char *text, char *priority)
 	switch (list_table[root->type].mode)
 	{
 		case SORT_ALPHA:
-			return bsearch_alpha_list(root, text, 1);
+			return bsearch_alpha_list(root, text, SEEK_REPLACE);
+
+		case SORT_STABLE:
+			return bsearch_alpha_list(root, text, SEEK_APPEND);
 
 		case SORT_ALNUM:
-			return bsearch_alnum_list(root, text, 1);
+			return bsearch_alnum_list(root, text, SEEK_REPLACE);
 
 		case SORT_DELAY:
-			return bsearch_priority_list(root, text, text, 1);
+			return bsearch_priority_list(root, text, text, SEEK_REPLACE);
 
 		case SORT_PRIORITY:
-			return bsearch_priority_list(root, text, priority, 1);
+			return bsearch_priority_list(root, text, priority, SEEK_REPLACE);
 
 		default:
 			return root->used;
 	}
 }
 
+int bsearch_alpha_list(struct listroot *root, char *text, int seek)
+{
+	int bot, mid, top;
+
+	if (root->used == 0)
+	{
+		return seek ? 0 : -1;
+	}
+
+	bot = 0;
+	top = root->used;
+
+	while (top > 1)
+	{
+		mid = top / 2;
+
+		if (strcmp(text, root->list[bot + mid]->arg1) >= 0)
+		{
+			bot += mid;
+		}
+		top -= mid;
+	}
 
+	if (strcmp(text, root->list[bot]->arg1) == 0)
+	{
+		return bot + (seek == SEEK_APPEND);
+	}
+
+	if (seek)
+	{
+		return bot += strcmp(text, root->list[bot]->arg1) > 0;
+	}
+
+	return -1;
+}
+
+/*
 int bsearch_alpha_list(struct listroot *root, char *text, int seek)
 {
 	int bot, top, val, srt;
@@ -524,7 +566,7 @@ int bsearch_alpha_list(struct listroot *root, char *text, int seek)
 	}
 	return -1;
 }
-
+*/
 
 int bsearch_alnum_list(struct listroot *root, char *text, int seek)
 {
@@ -776,6 +818,7 @@ int show_node_with_wild(struct session *ses, char *text, struct listroot *root)
 	switch (list_table[root->type].mode)
 	{
 		case SORT_ALPHA:
+		case SORT_STABLE:
 			index = bsearch_alpha_list(root, text, 0);
 			break;
 
@@ -885,6 +928,7 @@ int delete_node_with_wild(struct session *ses, int type, char *text)
 	switch (list_table[type].mode)
 	{
 		case SORT_ALPHA:
+		case SORT_STABLE:
 			index = bsearch_alpha_list(root, arg1, 0);
 			break;
 
@@ -1022,7 +1066,7 @@ DO_COMMAND(do_message)
 				continue;
 			}
 
-			if (!is_abbrev(arg1, list_table[index].name) && !is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
+			if (!is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
 			{
 				continue;
 			}
@@ -1045,7 +1089,7 @@ DO_COMMAND(do_message)
 				
 				return ses;
 			}
-			show_message(ses, LIST_COMMAND, "#OK: #%s MESSAGES HAVE BEEN SET TO: %s.", list_table[index].name, HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ? "ON" : "OFF");
+			show_message(ses, LIST_COMMAND, "#OK: #MESSAGE STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_MESSAGE) ? "ON" : "OFF");
 
 			found = TRUE;
 		}
@@ -1089,7 +1133,7 @@ DO_COMMAND(do_ignore)
 				continue;
 			}
 
-			if (!is_abbrev(arg1, list_table[index].name) && !is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
+			if (!is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
 			{
 				continue;
 			}
@@ -1112,7 +1156,7 @@ DO_COMMAND(do_ignore)
 				
 				return ses;
 			}
-			show_message(ses, LIST_COMMAND, "#OK: #%s IGNORE STATUS HAS BEEN SET TO: %s.", list_table[index].name, HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE) ? "ON" : "OFF");
+			show_message(ses, LIST_COMMAND, "#OK: #IGNORE STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, HAS_BIT(ses->list[index]->flags, LIST_FLAG_IGNORE) ? "ON" : "OFF");
 
 			found = TRUE;
 		}
@@ -1156,7 +1200,7 @@ DO_COMMAND(do_debug)
 				continue;
 			}
 
-			if (!is_abbrev(arg1, list_table[index].name) && !is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
+			if (!is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
 			{
 				continue;
 			}
@@ -1184,7 +1228,7 @@ DO_COMMAND(do_debug)
 				
 				return ses;
 			}
-			show_message(ses, LIST_COMMAND, "#OK: #%s DEBUG STATUS HAS BEEN SET TO: %s.", list_table[index].name, is_abbrev(arg2, "LOG") ? "LOG" : HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG) ? "ON" : "OFF");
+			show_message(ses, LIST_COMMAND, "#OK: #DEBUG STATUS FOR %s HAS BEEN SET TO: %s.", list_table[index].name_multi, is_abbrev(arg2, "LOG") ? "LOG" : HAS_BIT(ses->list[index]->flags, LIST_FLAG_DEBUG) ? "ON" : "OFF");
 
 			found = TRUE;
 		}
@@ -1235,7 +1279,7 @@ DO_COMMAND(do_info)
 				continue;
 			}
 
-			if (!is_abbrev(arg1, list_table[index].name) && !is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
+			if (!is_abbrev(arg1, list_table[index].name_multi) && strcasecmp(arg1, "ALL"))
 			{
 				continue;
 			}
@@ -1260,22 +1304,22 @@ DO_COMMAND(do_info)
 				{
 					for (cnt = 0 ; cnt < root->used ; cnt++)
 					{
-						tintin_printf2(ses, "#INFO %s %4d {arg1}{%s} {arg2}{%s} {arg3}{%s} {arg4}{%s} {class}{%s} {shots}{%u}", list_table[index].name, cnt+1, root->list[cnt]->arg1, root->list[cnt]->arg2, root->list[cnt]->arg3, root->list[cnt]->arg4, root->list[cnt]->group, root->list[cnt]->shots);
+						tintin_printf2(ses, "#INFO %s %4d {arg1}{%s} {arg2}{%s} {arg3}{%s} {arg4}{%s} {class}{%s} {shots}{%u}", list_table[index].name_multi, cnt+1, root->list[cnt]->arg1, root->list[cnt]->arg2, root->list[cnt]->arg3, root->list[cnt]->arg4, root->list[cnt]->group, root->list[cnt]->shots);
 					}
 				}
 				else if (is_abbrev(arg2, "SAVE"))
 				{
-					sprintf(name, "info[%s]", list_table[index].name);
+					sprintf(name, "info[%s]", list_table[index].name_multi);
 
 					set_nest_node_ses(ses, name, "");
 
 					for (cnt = 0 ; cnt < root->used ; cnt++)
 					{
-						sprintf(name, "info[%s][%d]", list_table[index].name, cnt + 1);
+						sprintf(name, "info[%s][%d]", list_table[index].name_multi, cnt + 1);
 
 						set_nest_node_ses(ses, name, "{arg1}{%s}{arg2}{%s}{arg3}{%s}{arg4}{%s}{class}{%s}{nest}{%d}{shots}{%u}", root->list[cnt]->arg1, root->list[cnt]->arg2, root->list[cnt]->arg3, root->list[cnt]->arg4, root->list[cnt]->group, root->list[cnt]->root ? root->list[cnt]->root->used : 0, root->list[cnt]->shots);
 					}
-					show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[%s]}", list_table[index].name);
+					show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[%s]}", list_table[index].name_multi);
 				}
 				else
 				{
@@ -1283,7 +1327,7 @@ DO_COMMAND(do_info)
 				}
 				return ses;
 			}
-			show_message(ses, LIST_COMMAND, "#OK: #%s INFO STATUS HAS BEEN SET TO: %s.", list_table[index].name, 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");
 
 			found = TRUE;
 		}

+ 9 - 39
src/dict.c

@@ -92,55 +92,25 @@ void dictionary_init()
 
 int dictionary_search(int hash, char *key)
 {
-	register int mid, i, bot;
-	register char val;
+	unsigned int bot, mid, top;
 
 	bot = 0;
-	i = dictionary->listsize[hash] - 1;
-	mid = i / 2;
+	top = dictionary->listsize[hash];
 
-	while (mid)
+	while (top > 1)
 	{
-		val = strcmp(key, wordlist[hash] + dictionary->wordindex[hash][i - mid]);
+		mid = top / 2;
 
-//		printf("debug: %5d '%c' %s\n", i - mid, 'a' + hash, wordlist[hash] + dictionary->wordindex[hash][i - mid]);
-
-		if (val < 0)
-		{
-			i -= mid + 1;
-		}
-		else if (val > 0)
-		{
-			bot = i - mid + 1;
-		}
-		else
-		{
-			return i - mid;
-		}
-		mid = (i - bot) / 2;
-	}
-
-	if (i > bot)
-	{
-		val = strcmp(key, wordlist[hash] + dictionary->wordindex[hash][i]);
-
-		if (val > 0)
-		{
-			return -1;
-		}
-		else if (val < 0)
-		{
-			--i;
-		}
-		else
+		if (strcmp(key, wordlist[hash] + dictionary->wordindex[hash][bot + mid]) >= 0)
 		{
-			return i;
+			bot += mid;
 		}
+		top -= mid;
 	}
 
-	if (!strcmp(key, wordlist[hash] + dictionary->wordindex[hash][i]))
+	if (!strcmp(key, wordlist[hash] + dictionary->wordindex[hash][bot]))
 	{
-		return i;
+		return bot;
 	}
 	return -1;
 }

+ 1 - 0
src/dict.h

@@ -23,6 +23,7 @@
 *                      coded by Igor van den Hoven 2019                       *
 ******************************************************************************/
 
+// a to z, the first letter of each word is omitted to conserve space.
 
 char *wordlist[] =
 {

+ 169 - 76
src/draw.c

@@ -75,7 +75,7 @@ static int  draw_cnt;
 
 
 
-#define DO_DRAW(draw) void draw (struct session *ses, int top_row, int top_col, int bot_row, int bot_col, int rows, int cols, long long flags, char *color, char *arg, char *arg1, char *arg2, char *arg3)
+#define DO_DRAW(draw) void draw (struct session *ses, int top_row, int top_col, int bot_row, int bot_col, int rows, int cols, long long flags, char *box_color, char *txt_color, char *arg, char *arg1, char *arg2, char *arg3)
 
 extern DO_DRAW(draw_blank);
 extern DO_DRAW(draw_bot_side);
@@ -91,12 +91,13 @@ extern DO_DRAW(draw_right_side);
 extern DO_DRAW(draw_side);
 extern DO_DRAW(draw_square);
 extern DO_DRAW(draw_rain);
+extern DO_DRAW(draw_hbar);
 extern DO_DRAW(draw_table_grid);
 extern DO_DRAW(draw_text);
 extern DO_DRAW(draw_top_side);
 extern DO_DRAW(draw_vertical_lines);
 
-typedef void DRAW(struct session *ses, int top_row, int top_col, int bot_row, int bot_col, int rows, int cols, long long flags, char *color, char *arg, char *arg1, char *arg2, char *arg3);
+typedef void DRAW(struct session *ses, int top_row, int top_col, int bot_row, int bot_col, int rows, int cols, long long flags, char *box_color, char *txt_color, char *arg, char *arg1, char *arg2, char *arg3);
 
 struct draw_type
 {
@@ -108,6 +109,7 @@ struct draw_type
 
 struct draw_type draw_table[] =
 {
+	{       "BAR",       "Draw a bar.",                       DRAW_FLAG_NONE, draw_hbar },
 	{       "BOX",       "Draw four sides of a box.",         DRAW_FLAG_BOXED|DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT|DRAW_FLAG_TOP|DRAW_FLAG_BOT, draw_box },
 	{       "BUFFER",    "Draw the scrollback buffer.",       DRAW_FLAG_NONE, draw_buffer },
 	{       "CORNER",    "Draw a corner",                     DRAW_FLAG_CORNERED, draw_corner },
@@ -125,7 +127,7 @@ void scale_drawing(struct session *ses, int *top_row, int *top_col, int *bot_row
 
 DO_COMMAND(do_draw)
 {
-	char *color, *code1, *code2, *input;
+	char *box_color, *txt_color, *code1, *code2, *input;
 	long long flags;
 	int index, top_row, top_col, bot_row, bot_col, rows, cols;
 
@@ -153,7 +155,9 @@ DO_COMMAND(do_draw)
 		return ses;
 	}
 
-	color = str_alloc_stack(0);
+	box_color = str_alloc_stack(0);
+	txt_color = str_alloc_stack(0);
+
 	code1 = str_alloc_stack(0);
 	code2 = str_alloc_stack(0);
 
@@ -165,7 +169,7 @@ DO_COMMAND(do_draw)
 
 		if (!HAS_BIT(flags, DRAW_FLAG_COLOR1) && translate_color_names(ses, arg1, code1))
 		{
-			get_color_names(ses, arg1, color);
+			get_color_names(ses, arg1, box_color);
 
 			SET_BIT(flags, DRAW_FLAG_COLOR1);
 
@@ -174,7 +178,7 @@ DO_COMMAND(do_draw)
 
 		if (!HAS_BIT(flags, DRAW_FLAG_COLOR2) && translate_color_names(ses, arg1, code2))
 		{
-//			get_color_names(ses, arg1, color);
+			get_color_names(ses, arg1, txt_color);
 
 			SET_BIT(flags, DRAW_FLAG_COLOR2);
 
@@ -505,7 +509,7 @@ DO_COMMAND(do_draw)
 			*arg3 = 0;
 //			*arg4 = 0;
 
-			// not sure of the utility of this
+			// forgot why I did this originally
 /*
 			if (*arg == 0)
 			{
@@ -522,7 +526,7 @@ DO_COMMAND(do_draw)
 			str_cpy(&arg2, code1);
 			str_cpy(&arg3, code2);
 
-			draw_table[index].fun(ses, top_row, top_col, bot_row, bot_col, rows, cols, draw_table[index].flags | flags, color, arg, arg1, arg2, arg3);
+			draw_table[index].fun(ses, top_row, top_col, bot_row, bot_col, rows, cols, draw_table[index].flags | flags, box_color, txt_color, arg, arg1, arg2, arg3);
 
 			print_stdout(0, 0, "\e[0m");
 
@@ -1347,7 +1351,7 @@ DO_DRAW(draw_bot_side)
 	{
 		SET_BIT(corner, DRAW_FLAG_LEFT|DRAW_FLAG_BOT);
 
-		arg1 += sprintf(arg1, "%s%s", color, get_draw_corner(corner, "└"));
+		arg1 += sprintf(arg1, "%s%s", box_color, get_draw_corner(corner, "└"));
 	}
 
 	if (cols - 2 >= 0)
@@ -1407,7 +1411,7 @@ DO_DRAW(draw_arg)
 
 	save_pos(ses);
 
-	draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg2, arg1, arg, arg3);
+	draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, arg2, arg1, arg, arg3);
 
 	restore_pos(ses);
 }
@@ -1417,14 +1421,14 @@ DO_DRAW(draw_box)
 {
 	if (HAS_BIT(flags, DRAW_FLAG_TOP))
 	{
-		draw_top_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+		draw_top_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 	}
 
-	draw_vertical_lines(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+	draw_vertical_lines(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 
 	if (HAS_BIT(flags, DRAW_FLAG_BOT))
 	{
-		draw_bot_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+		draw_bot_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 	}
 }
 
@@ -1451,7 +1455,7 @@ DO_DRAW(draw_buffer)
 		str_cat_printf(&buf, "{%s}", ses->scroll->buffer[line - cnt]->str);
 	}
 
-	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, buf, arg1, arg2, arg3);
+	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, buf, arg1, arg2, arg3);
 
 	pop_call();
 	return;
@@ -1470,13 +1474,13 @@ DO_DRAW(draw_corner)
 
 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
 	{
-		tintin_printf2(ses, "%s%s%s", indent_one(top_col - 1), color, arg1);
+		tintin_printf2(ses, "%s%s%s", indent_one(top_col - 1), box_color, arg1);
 	}
 	else
 	{
 		goto_pos(ses, top_row, top_col);
 		
-		print_stdout(top_row, top_col, "%s%s", color, arg1);
+		print_stdout(top_row, top_col, "%s%s", box_color, arg1);
 	}
 }
 
@@ -1534,13 +1538,13 @@ DO_DRAW(draw_line_horizontal)
 
 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
 	{
-		tintin_printf2(ses, "%*s%s%s", top_col - 1, "", color, arg);
+		tintin_printf2(ses, "%*s%s%s", top_col - 1, "", box_color, arg);
 	}
 	else
 	{
 		goto_pos(ses, top_row, top_col);
 
-		print_stdout(top_row, top_col, "%s%s", color, arg);
+		print_stdout(top_row, top_col, "%s%s", box_color, arg);
 	}
 }
 
@@ -1604,13 +1608,13 @@ DO_DRAW(draw_line_vertical)
 
 		if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
 		{
-			tintin_printf2(ses, "%*s%s%s", top_col - 1, "", color, arg2);
+			tintin_printf2(ses, "%*s%s%s", top_col - 1, "", box_color, arg2);
 		}
 		else
 		{
 			goto_pos(ses, row, top_col);
 
-			print_stdout(row, top_col, "%s%s", color, arg2);
+			print_stdout(row, top_col, "%s%s", box_color, arg2);
 		}
 		row++;
 	}
@@ -1621,19 +1625,19 @@ DO_DRAW(draw_line)
 {
 	if (top_row == bot_row)
 	{
-		draw_line_horizontal(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+		draw_line_horizontal(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 
 		return;
 	}
 
 	if (top_col == bot_col)
 	{
-		draw_line_vertical(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+		draw_line_vertical(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 		
 		return;
 	}
 
-	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 }
 
 DO_DRAW(draw_map)
@@ -1674,59 +1678,148 @@ DO_DRAW(draw_map)
 
 	if (HAS_BIT(flags, DRAW_FLAG_TOP|DRAW_FLAG_BOT))
 	{
-		draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, gtd->buf, arg1, arg2, arg3);
+		draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, gtd->buf, arg1, arg2, arg3);
 	}
 	else
 	{
-		draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, gtd->buf, arg1, arg2, arg3);
+		draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, gtd->buf, arg1, arg2, arg3);
 	}
 }
 
-/*
-DO_DRAW(draw_map)
+// ideas
+// 0 use color gradients
+// 1 use inverse color so text can be added to solid blocks.
+// 2 use ralign for raligned bar
+// 3 use calign for centered bar
+// 4 use box drawing modifiers if no box is specified.
+// 4.1 rounded = (###)
+// 4.2 teed    = [---] 
+// 4.3 jeweled = <###>
+// 4.4 crossed = +++++
+// 4.5 circled = OOOOO
+// 4.6 pruned  = no rounding
+
+// hpbar <square> {val;max;color}
+
+DO_DRAW(draw_hbar)
 {
-	if (ses->map && ses->map->in_room)
+	char *nest, *buf, *ptb, *col1;
+	int cnt, val, bar;
+	long double min, max;
+
+	bar = cols;
+
+	bar -= HAS_BIT(flags, DRAW_FLAG_LEFT) ? 1 : 0;
+	bar -= HAS_BIT(flags, DRAW_FLAG_RIGHT) ? 1 : 0;
+
+	if (bar <= 0)
 	{
-		int map_top_row = ses->map->top_row;
-		int map_top_col = ses->map->top_col;
-		int map_bot_row = ses->map->bot_row;
-		int map_bot_col = ses->map->bot_col;
-		int map_rows    = ses->map->rows;
-		int map_cols    = ses->map->cols;
-		int map_flags   = ses->map->flags;
+		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);
+
+		return;
+	}
+
+	buf  = str_alloc_stack(0);
+	col1 = str_alloc_stack(0);
+
+	str_cpy(&gtd->buf, "");
+
+	bar *= 8;
+
+	start:
+
+	arg = get_arg_in_braces(ses, arg, buf, GET_ALL);
+
+	nest = buf;
+	nest = get_arg_in_braces(ses, nest, arg1, GET_ALL);
+	if (*nest == COMMAND_SEPARATOR) nest++;
+	nest = get_arg_in_braces(ses, nest, arg2, GET_ALL);
+	if (*nest == COMMAND_SEPARATOR) nest++;
+	nest = get_arg_in_braces(ses, nest, arg3, GET_ALL);
+
+	min = get_number(ses, arg1);
+	max = get_number(ses, arg2);
+
+	if (max <= 0)
+	{
+		show_error(ses, LIST_COMMAND, "#DRAW HBAR {%d;%d;%s}: MAX MUST BE GREATER THAN 0.", min, max, arg3);
+
+		return;
+	}
+
+	if (min > max)
+	{
+		min = max;
+	}
 
-		ses->map->top_row = top_row;
-		ses->map->top_col = top_col;
-		ses->map->bot_row = bot_row;
-		ses->map->bot_col = bot_col;
-		ses->map->rows    = URANGE(1, bot_row - top_row, gtd->screen->rows);
-		ses->map->cols    = URANGE(1, bot_col - top_col, gtd->screen->cols);
+	color_gradient(arg3, min, max);
 
-		SET_BIT(ses->map->flags, MAP_FLAG_VTMAP);
-		DEL_BIT(ses->map->flags, MAP_FLAG_RESIZE);
+	translate_color_names(ses, arg3, col1);
 
-		show_vtmap(ses);
+//	printf("debug: min %d max %d bar %d\n", (int) min, (int) max, bar);
 
-		ses->map->top_row = map_top_row;
-		ses->map->top_col = map_top_col;
-		ses->map->bot_row = map_bot_row;
-		ses->map->bot_col = map_bot_col;
-		ses->map->rows    = map_rows;
-		ses->map->cols    = map_cols;
+	ptb = buf;
 
-		ses->map->flags   = map_flags;
+	ptb += sprintf(ptb, "{%s", col1);
 
-		if (HAS_BIT(flags, DRAW_FLAG_BOXED|DRAW_FLAG_BOT|DRAW_FLAG_TOP|DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT|DRAW_FLAG_PRUNED))
+	val = bar * min / max;
+
+	for (cnt = 8 ; cnt <= bar + 8 ; cnt += 8)
+	{
+//		printf("debug: cnt %3d - val = %3d\n", cnt, val);
+
+		if (cnt > val)
 		{
-			draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, "", arg1, arg2, arg3);
+			break;
 		}
+		ptb += sprintf(ptb, "█");
+	}
+
+//	printf("debug: val - lst = %d - %d\n", val, lst);
+
+	if (cnt <= bar)
+	{
+		switch (val + 8 - cnt)
+		{
+			case 0: ptb += sprintf(ptb, " "); break;
+			case 1: ptb += sprintf(ptb, "▏"); break;
+			case 2: ptb += sprintf(ptb, "▎"); break;
+			case 3: ptb += sprintf(ptb, "▍"); break;
+			case 4: ptb += sprintf(ptb, "▌"); break;
+			case 5: ptb += sprintf(ptb, "▋"); break;
+			case 6: ptb += sprintf(ptb, "▊"); break;
+			case 7: ptb += sprintf(ptb, "▉"); break;
+			case 8: ptb += sprintf(ptb, "█"); break;
+		}
+		ptb += sprintf(ptb, "%*s%s}", (bar - cnt) / 8, "", box_color);
 	}
 	else
 	{
-		draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, "{}", arg1, arg2, arg3);
+		ptb += sprintf(ptb, "%s}", box_color);
+	}
+
+	str_cat(&gtd->buf, buf);
+
+//	printf("debug (%s) bar: %d cnt %d val %d\n", gtd->buf, bar, cnt, val);
+
+	if (*arg)
+	{
+		goto start;
+	}
+
+	*arg1 = 0;
+	*arg2 = 0;
+	*arg3 = 0;
+
+	if (HAS_BIT(flags, DRAW_FLAG_TOP|DRAW_FLAG_BOT))
+	{
+		draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, gtd->buf, arg1, arg2, arg3);
+	}
+	else
+	{
+		draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, gtd->buf, arg1, arg2, arg3);
 	}
 }
-*/
 
 char *rain_symbols = "ロヲアウエオカキケコサシスセソタツテナニヌネハヒホマミムメモヤユラリワ01SԐ45789Z=*+-¦|_ʺ╌";
 char *braille_symbols = "⠁⠂⠃⠄⠅⠆⠇⠈⠊⠌⠎⠐⠑⠔⠕⠘⠜⠠⠡⠢⠣⠨⠪⠰⠱⠸⡀⡁⡂⡃⡄⡅⡆⡇⡈⡊⡌⡎⡐⡑⡔⡕⡘⡜⡠⡡⡢⡣⡨⡪⡰⡱⡸⢀⢁⢂⢃⢄⢅⢆⢇⢈⢉⢊⢌⢎⢐⢑⢔⢕⢘⢜⢠⢡⢢⢣⢨⢪⢰⢱";
@@ -1983,7 +2076,7 @@ DO_DRAW(draw_side)
 {
 	push_call("draw_side()");
 
-	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+	draw_box(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 
 	pop_call();
 	return;
@@ -1993,14 +2086,14 @@ DO_DRAW(draw_square)
 {
 	if (HAS_BIT(flags, DRAW_FLAG_TOP))
 	{
-		draw_top_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+		draw_top_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 	}
 
-	draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+	draw_text(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 
 	if (HAS_BIT(flags, DRAW_FLAG_BOT))
 	{
-		draw_bot_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+		draw_bot_side(ses, top_row, top_col, bot_row, bot_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 	}
 }
 
@@ -2149,7 +2242,7 @@ DO_DRAW(draw_table_grid)
 						{
 							goto_pos(ses, top_row + r, top_col + c);
 
-							print_stdout(top_row + r, top_col + c, "%s%s", color, draw_vertical(flags, "│"));
+							print_stdout(top_row + r, top_col + c, "%s%s", box_color, draw_vertical(flags, "│"));
 						}
 					}
 					else if (c == 0 || c % max_c == 0)
@@ -2165,7 +2258,7 @@ DO_DRAW(draw_table_grid)
 						bot_r = top_row + r - 1 + max_r;
 						bot_c = top_col + c + max_c;
 
-						draw_vertical_lines(ses, top_r, top_c, top_r, bot_c, 1 + max_r, 1 + max_c, corner | DRAW_FLAG_LEFT, color, buf2, arg1, arg2, arg3);
+						draw_vertical_lines(ses, top_r, top_c, top_r, bot_c, 1 + max_r, 1 + max_c, corner | DRAW_FLAG_LEFT, box_color, txt_color, buf2, arg1, arg2, arg3);
 
 						if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
 						{
@@ -2190,7 +2283,7 @@ DO_DRAW(draw_table_grid)
 						{
 							goto_pos(ses, top_row + r, top_col + c);
 
-							print_stdout(top_row + r, top_col + c, "%s%s", color, draw_vertical(flags, "│"));
+							print_stdout(top_row + r, top_col + c, "%s%s", box_color, draw_vertical(flags, "│"));
 						}
 					}
 				}
@@ -2200,13 +2293,13 @@ DO_DRAW(draw_table_grid)
 			{
 				if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
 				{
-					tintin_printf2(ses, "%s%s%s", indent_one(top_col - 1), color, buf3);
+					tintin_printf2(ses, "%s%s%s", indent_one(top_col - 1), box_color, buf3);
 				}
 				else
 				{
 					goto_pos(ses, top_row + r, top_col);
 
-					print_stdout(top_row + r, top_col, "%s%s", color, buf3);
+					print_stdout(top_row + r, top_col, "%s%s", box_color, buf3);
 				}
 			}
 
@@ -2237,7 +2330,7 @@ DO_DRAW(draw_table_grid)
 			top_c = top_col + c * max_c;
 			bot_c = top_col + c * max_c + max_c - 1;
 
-			draw_box(ses, top_r, top_c, bot_r, bot_c, 1 + bot_r - top_r, 1 + bot_c - top_c, flags, color, buf2, arg1, arg2, arg3);
+			draw_box(ses, top_r, top_c, bot_r, bot_c, 1 + bot_r - top_r, 1 + bot_c - top_c, flags, box_color, txt_color, buf2, arg1, arg2, arg3);
 
 //			tintin_printf2(ses, "#draw box %d %d %d %d %s", top_row + r * max_r, top_col + c * max_c, top_row + r * max_r + max_r, top_col + c * max_c + max_c, buf1);
 
@@ -2252,7 +2345,7 @@ DO_DRAW(draw_table_grid)
 			top_c = top_col + c * max_c;
 			bot_c = bot_col;
 
-			draw_text(ses, top_r, top_c, bot_r, bot_c, 1 + bot_r - top_r, 1 + bot_c - top_c, blank, color, "", arg1, arg2, arg3);
+			draw_text(ses, top_r, top_c, bot_r, bot_c, 1 + bot_r - top_r, 1 + bot_c - top_c, blank, box_color, txt_color, "", arg1, arg2, arg3);
 		}
 
 		if (*arg == COMMAND_SEPARATOR)
@@ -2431,18 +2524,18 @@ DO_DRAW(draw_text)
 		{
 			if (HAS_BIT(flags, DRAW_FLAG_GRID))
 			{
-				cat_sprintf(arg2, "%s%s%s%s%s", color, side1, buf2, color, side2);
+				cat_sprintf(arg2, "%s%s%s%s%s", box_color, side1, buf2, box_color, side2);
 			}
 			else
 			{
-				tintin_printf2(ses, "%s%s%s%s%s%s", indent_one(top_col - 1), color, side1, buf2, color, side2);
+				tintin_printf2(ses, "%s%s%s%s%s%s", indent_one(top_col - 1), box_color, side1, buf2, box_color, side2);
 			}
 		}
 		else
 		{
 			goto_pos(ses, row, col);
 
-			print_stdout(row, col, "%s%s%s%s%s", color, side1, buf2, color, side2);
+			print_stdout(row, col, "%s%s%s%s%s", box_color, side1, buf2, box_color, side2);
 		}
 		row++;
 
@@ -2465,18 +2558,18 @@ DO_DRAW(draw_text)
 		{
 			if (HAS_BIT(flags, DRAW_FLAG_GRID))
 			{
-				cat_sprintf(arg2, "%s%s%*s%s%s", color, side1, cols, "", color, side2);
+				cat_sprintf(arg2, "%s%s%*s%s%s", box_color, side1, cols, "", box_color, side2);
 			}
 			else
 			{
-				tintin_printf2(ses, "%s%s%s%-*s%s%s", indent_one(top_col - 1), color, side1, cols, "", color, side2);
+				tintin_printf2(ses, "%s%s%s%-*s%s%s", indent_one(top_col - 1), box_color, side1, cols, "", box_color, side2);
 			}
 		}
 		else
 		{
 			goto_pos(ses, row, col);
 
-			print_stdout(row, col, "%s%s%*s%s%s", color, side1, cols, "", color, side2);
+			print_stdout(row, col, "%s%s%*s%s%s", box_color, side1, cols, "", box_color, side2);
 
 			row++;
 		}
@@ -2502,7 +2595,7 @@ DO_DRAW(draw_top_side)
 	{
 		SET_BIT(corner, DRAW_FLAG_LEFT|DRAW_FLAG_RIGHT);
 
-		arg1 += sprintf(arg1, "%s%s", color, get_draw_corner(corner, "┌"));
+		arg1 += sprintf(arg1, "%s%s", box_color, get_draw_corner(corner, "┌"));
 	}
 
 	if (cols - 2 >= 0)
@@ -2551,7 +2644,7 @@ DO_DRAW(draw_vertical_lines)
 
 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL) || *arg)
 	{
-		draw_text(ses, top_row, top_col, bot_row, top_col, rows, cols, flags, color, arg, arg1, arg2, arg3);
+		draw_text(ses, top_row, top_col, bot_row, top_col, rows, cols, flags, box_color, txt_color, arg, arg1, arg2, arg3);
 
 		pop_call();
 		return;
@@ -2595,7 +2688,7 @@ DO_DRAW(draw_vertical_lines)
 		{
 			goto_pos(ses, row, top_col);
 
-			print_stdout(row, top_col, "%s%s", color, arg1);
+			print_stdout(row, top_col, "%s%s", box_color, arg1);
 
 			row++;
 		}
@@ -2609,7 +2702,7 @@ DO_DRAW(draw_vertical_lines)
 		{
 			goto_pos(ses, row, bot_col);
 
-			print_stdout(row, bot_col, "%s%s", color, arg2);
+			print_stdout(row, bot_col, "%s%s", box_color, arg2);
 
 			row++;
 		}

+ 3 - 3
src/event.c

@@ -521,7 +521,7 @@ void mouse_handler(struct session *ses, int flags, int row, int col)
 		{
 			click[2] = click[1];
 			click[1] = click[0];
-			click[0] = utime();
+			click[0] = gtd->utime;
 
 			if (click[0] - click[1] < 500000)
 			{
@@ -541,7 +541,7 @@ void mouse_handler(struct session *ses, int flags, int row, int col)
 		{
 			click[2] = 0;
 			click[1] = 0;
-			click[0] = utime();
+			click[0] = gtd->utime;
 
 			sprintf(last, "PRESSED %s %d %d", arg2, col, row);
 		}
@@ -578,7 +578,7 @@ void mouse_handler(struct session *ses, int flags, int row, int col)
 			check_all_events(ses, EVENT_FLAG_MOUSE, 1, 12, "SWIPED %s", dir, dir, arg2, ntos(swipe[0]), ntos(swipe[1]), ntos(swipe[2]), ntos(swipe[3]), ntos(swipe[4]), ntos(swipe[5]), ntos(swipe[6]), ntos(swipe[7]), ntos(swipe[8]), ntos(swipe[9]));
 			check_all_events(ses, EVENT_FLAG_MOUSE, 2, 12, "SWIPED %s %s", arg2, dir, dir, arg2, ntos(swipe[0]), ntos(swipe[1]), ntos(swipe[2]), ntos(swipe[3]), ntos(swipe[4]), ntos(swipe[5]), ntos(swipe[6]), ntos(swipe[7]), ntos(swipe[8]), ntos(swipe[9]));
 		}
-		else if (utime() - click[0] >= 500000)
+		else if (gtd->utime - click[0] >= 500000)
 		{
 			mouse_event_handler(ses, "LONG-CLICKED", arg2, row, col, rev_row, rev_col, pix_row, pix_col, grid, word, line, link, name);
 		}

+ 3 - 3
src/files.c

@@ -294,7 +294,6 @@ struct session *read_file(struct session *ses, FILE *fp, char *filename)
 	*pto++ = '\n';
 	*pto   = '\0';
 
-
 	if (lvl)
 	{
 		check_all_events(ses, EVENT_FLAG_SYSTEM, 0, 2, "READ ERROR", filename, "MISSING BRACE OPEN OR CLOSE");
@@ -323,8 +322,6 @@ struct session *read_file(struct session *ses, FILE *fp, char *filename)
 		return ses;
 	}
 
-	check_all_events(ses, EVENT_FLAG_SYSTEM, 0, 1, "READ FILE", filename);
-
 	sprintf(temp, "#CONFIG {TINTIN CHAR} {%c}", bufo[0]);
 
 	if (bufo[0] != gtd->tintin_char)
@@ -409,6 +406,9 @@ struct session *read_file(struct session *ses, FILE *fp, char *filename)
 	free(bufi);
 	free(bufo);
 
+	check_all_events(ses, EVENT_FLAG_SYSTEM, 0, 1, "READ FILE", filename);
+	check_all_events(ses, EVENT_FLAG_SYSTEM, 1, 1, "READ FILE %s", filename, filename);
+
 	return ses;
 }
 

+ 73 - 46
src/help.c

@@ -436,9 +436,10 @@ struct help_type help_table[] =
 		TOKEN_TYPE_STATEMENT,
 		"<178>Command<278>: #break\n"
 		"\n"
-		"         The break command can be used inside the #foreach, #loop, #parse,\n"
-		"         #while and #switch statements. When #break is found, tintin will stop\n"
-		"         executing the statement it is currently in and move on to the next.\n"
+		"         The break command can be used inside the #else, #elseif, #if, #foreach,\n"
+		"         #loop, #parse, #switch, and #while statements. When #break is found,\n"
+		"         tintin will stop executing the statement it is currently in and move on\n"
+		"         to the next.\n"
 		"\n"
 		"<178>Example<278>: #while {1} {#math cnt $cnt + 1;#if {$cnt == 20} {#break}}\n",
 		
@@ -945,12 +946,12 @@ struct help_type help_table[] =
 		"<178>Command<278>: #delay <178>{<278>name<178>} {<278>command<178>} {<278>seconds<178>}<278>\n"
 		"\n"
 		"         Delay allows you to have tintin wait the given amount of seconds\n"
-		"         before executing the given command. tintin won't wait before\n"
-		"         executing following input commands if any.\n"
+		"         before executing the given command.\n"
 		"\n"
-		"         Floating point precision for milliseconds is possible.\n"
+		"         Nanosecond floating point precision is allowed. Delays will fire in\n"
+		"         0.01 second intervals.\n"
 		"\n"
-		"<178>Example<278>: #show first;#delay {1} {#show last}\n"
+		"<178>Example<278>: #delay {1} {#show last};#show first\n"
 		"         This will print 'first', and 'last' around one second later.\n"
 		"\n"
 		"<178>Comment<278>: If you want to remove a delay with the #undelay command you can add\n"
@@ -964,13 +965,13 @@ struct help_type help_table[] =
 	{
 		"DRAW",
 		TOKEN_TYPE_COMMAND,
-		"<178>Command<278>: #draw <178>[<278>color<178>] <178>[<278>options<178>] <178><<278>type<178>> <<278>square<178>> {<278>text<178>}\n"
+		"<178>Command<278>: #draw <178>[<278>line color<178>] <178>[<278>options<178>] <178><<278>type<178>> <<278>square<178>> {<278>text<178>}\n"
 		"<278>\n"
 		"         The draw commands allows you to draw various types of lines and shapes\n"
-		"         on the screen. Common options and types with a brief description are\n"
-		"         provided when you type #draw without an argument.\n"
+		"         on the screen. The types with a brief description are provided when you\n"
+		"         type #draw without an argument.\n"
 		"\n"
-		"         The square arguments should exists of two coordinates defining the\n"
+		"         The <square> arguments should exists of two coordinates defining the\n"
 		"         upper left and bottom right corner using row, col, row, col syntax.\n"
 		"\n"
 		"         The square arguments can be negative, in which case the coordinates\n"
@@ -1024,23 +1025,25 @@ struct help_type help_table[] =
 		"\n"
 		"         The following types are available.\n"
 		"\n"
-		"         <178>[ASCII|UNICODE|HUGE] BOX {[TEXT1]} {[TEXT2]}\n"
+		"         <278>[HORIZONTAL] <178>BAR<278> {<MIN>;<MAX>;[COLOR]}\n"
+		"         <278> will draw a bar.\n"
+		"         <278>[ASCII|UNICODE|HUGE] <178>BOX<278> {[TEXT1]} {[TEXT2]}\n"
 		"         <278>  will draw a box.\n"
-		"         <178>[BOXED|FOREGROUND] BUFFER\n"
+		"         <278>[BOXED|FOREGROUND] <178>BUFFER\n"
 		"         <278>  will draw the scrollback buffer.\n"
-		"         <178>[BLANKED|CIRCLED|CROSSED|JEWELED|ROUNDED|TEED|PRUNED] CORNER\n"
+		"         <278>[BLANKED|CIRCLED|CROSSED|JEWELED|ROUNDED|TEED|PRUNED] <178>CORNER\n"
 		"         <278>  will draw a corner.\n"
-		"         <178>[BLANKED|HORIZONTAL|NUMBERED|TUBED|VERTICAL] LINE {[TEXT]}\n"
+		"         <278>[BLANKED|HORIZONTAL|NUMBERED|TUBED|VERTICAL] <178>LINE<278> {[TEXT]}\n"
 		"         <278>  will draw a line.\n"
-		"         <178>[BOXED] MAP\n"
+		"         <278>[BOXED] <178>MAP\n"
 		"         <278>  will draw the map\n"
-		"         <178>RAIN {<VARIABLE>} {[SPAWN]} {[FADE]} {[LEGEND]}\n"
+		"         <278><178>RAIN<278> {<VARIABLE>} {[SPAWN]} {[FADE]} {[LEGEND]}\n"
 		"         <278>  will draw digital rain.\n"
-		"         <178>[JOINTED|TOP|LEFT|BOTTOM|RIGHT] SIDE\n"
+		"         <278>[JOINTED|TOP|LEFT|BOTTOM|RIGHT] <178>SIDE\n"
 		"         <278>  will draw one or more sides of a box.\n"
-		"         <178>[GRID] TABLE {[LIST1]} {[LIST2]}\n"
+		"         <278>[GRID] <178>TABLE<278> {[LIST1]} {[LIST2]}\n"
 		"         <278> will draw a table.\n"
-		"         <178>[HUGE] TILE {[TEXT1]} {[TEXT2]}\n"
+		"         <278>[CURSIVE|FAT|HUGE|SANSSERIF] <178>TILE<278> {[TEXT1]} {[TEXT2]}\n"
 		"         <278>  will draw a tile\n"
 		"\n"
 		"         All draw types take an optional text argument as long as a valid\n"
@@ -1298,7 +1301,7 @@ struct help_type help_table[] =
 	{
 		"EVENT",
 		TOKEN_TYPE_CONFIG,
-		"<178>Command<278>: #event <178>{<278>event type<178>}<278>\n"
+		"<178>Command<278>: #event <178>{<278>event type<178>}<278> <178>{<278>commands<178>}<278>\n"
 		"\n"
 		"         Events allow you to create triggers for predetermined client events.\n"
 		"\n"
@@ -1307,7 +1310,8 @@ struct help_type help_table[] =
 		"         events. Use #info {events} {on} to see events get thrown.\n"
 		"\n"
 		"         Events, like triggers in general, are case sensitive and event names\n"
-		"         must be defined using all upper case letters.\n"
+		"         must be defined using all upper case letters. Only one event can be\n"
+		"         defined for each event type.\n"
 		"\n"
 		"         To enable mouse events use #config mouse_tracking on, to see mouse\n"
 		"         events use #config mouse_tracking info.\n"
@@ -1386,6 +1390,8 @@ struct help_type help_table[] =
 		"         <178>MAP <MOUSE EVENT>\n"
 		"         <278>  Mouse events can be prefixed with MAP to only trigger when the mouse\n"
 		"         <278>  event occurs inside the VT100 map region.\n"
+		"\n"
+
 		"\n"
 		"         <178>SWIPED [DIR]\n"
 		"         <278>  %0 dir  %1 button  %2 row  %3 col  %4 -row  %5 -col\n"
@@ -1432,7 +1438,7 @@ struct help_type help_table[] =
 		"         <178>IAC <EVENT>\n"
 		"         <278>  IAC TELNET events are made visable using #config telnet info.\n"
 		"\n"
-		"         <178>IAC SB GMCP [MODULE]   %0 module    %1 data  %1 plain data\n"
+		"         <178>IAC SB GMCP [MODULE]   %0 module    %1 data  %2 plain data\n"
 		"         <178>IAC SB MSSP            %0 variable  %1 data\n"
 		"         <178>IAC SB MSDP            %0 variable  %1 data  %2 plain data\n"
 		"         <178>IAC SB MSDP [VAR]      %0 variable  %1 data  %2 plain data\n"
@@ -1457,7 +1463,9 @@ struct help_type help_table[] =
 		"\n"
 		"         <128>SCREEN EVENTS<278>\n"
 		"\n"
-		"         SCREEN FOCUS           %0 focus (0 or 1)\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"
@@ -1791,8 +1799,6 @@ struct help_type help_table[] =
 	{
 		"INDEX",
 		TOKEN_TYPE_STRING,
-		"<128>         INDEX\n"
-		"<278>\n"
 		"         On this page you'll find an introduction to using TinTin++. Additional\n"
 		"         information can be found in the individual help sections.\n"
 		"<128>\n"
@@ -2223,7 +2229,8 @@ struct help_type help_table[] =
 		"         #list {var} {explode}                  Turn list into a character list\n"
 		"         #list {var} {indexate}                 Index a list table for sorting\n"
 		"         #list {var} {insert} {index} {string}  Insert {string} at given index\n"
-		"         #list {var} {find} {string} {variable} Return the found index\n"
+		"         #list {var} {filter} {keep} {remove}   Filter with keep / remove regex\n"
+		"         #list {var} {find} {regex} {variable}  Return the found index\n"
 		"         #list {var} {get} {index} {variable}   Copy an item to {variable}\n"
 		"         #list {var} {order} {string}           Insert item in numerical order\n"
 		"         #list {var} {shuffle}                  Shuffle the list\n"
@@ -2790,11 +2797,10 @@ struct help_type help_table[] =
 		"         <278>  variable name.\n"
 		"\n"
 		"         <178>#map move <direction>\n"
-		"         <278>  This does the same as an actual movement\n"
-		"         <278>  command, updating your location on the map and creating new\n"
-		"         <278>  rooms. Useful when you are following someone and want the map\n"
-		"         <278>  to follow. You will need to create actions using '#map move',\n"
-		"         <278>  for this to work.\n"
+		"         <278>  This does the same as an actual movement command, updating your\n"
+		"         <278>  location on the map and creating new rooms. Useful when you are\n"
+		"         <278>  following someone and want the map to follow along. You will need\n"
+		"         <278>  to create actions using '#map move', for this to work.\n"
 		"\n"
 		"         <178>#map offset <row> <col> <row> <col>\n"
 		"         <278>  Define the offset of the vtmap as a square. Without an argument\n"
@@ -2907,7 +2913,7 @@ struct help_type help_table[] =
 		"         <278>  Will save the map, if you want to save a map to a .tin file\n"
 		"         <278>  you must provide the {force} argument.\n",
 
-		"path pathdir"
+		"path pathdir speedwalk"
 	},
 
 	{
@@ -3341,7 +3347,7 @@ struct help_type help_table[] =
 		"\n"
 		"<178>Example<278>: #path ins {unlock n;open n} {unlock s;open s}\n",
 
-		"map pathdir"
+		"map pathdir speedwalk"
 	},
 	{
 		"PATHDIR",
@@ -3679,7 +3685,8 @@ struct help_type help_table[] =
 		"         The expression can contain escapes, and if you want to match a literal\n"
 		"         \\ character you'll have to use \\\\ to match a single backslash.\n"
 		"\n"
-		"         Variables are stored in &1 to &99 with &0 holding the matched substring.\n"
+		"         Variables are stored in &1 to &99 with &0 holding the matched\n"
+		"         substring.\n"
 		"\n"
 		"       ^ force match of start of line.\n"
 		"       $ force match of end of line.\n"
@@ -3724,9 +3731,11 @@ struct help_type help_table[] =
 		"         %15 as a regular expression, the next unnumbered regular expression\n"
 		"         would be %16. To prevent a match from being stored use %!*, %!w, etc.\n"
 		"\n"
-		"<178>Example<278>: #regexp {bli bla blo} {bli {.*} blo} {#show &1}\n",
+		"<178>Example<278>: #regexp {bli bla blo} {bli {.*} blo} {#show &1}\n"
+		"\n"
+		"<178>Comment<278>: Like an alias or function #regex has its own scope.\n",
 
-		"case default else elseif if switch"
+		"replace"
 	},
 
 	{
@@ -3746,10 +3755,13 @@ struct help_type help_table[] =
 		TOKEN_TYPE_COMMAND,
 		"<178>Command<278>: #replace <178>{<278>variable<178>} {<278>oldtext<178>} {<278>newtext<178>}<278>\n"
 		"\n"
-		"         Searches the variable text replacing each occurrence of 'oldtext' with\n"
-		"         'newtext'. The 'newtext' argument can be a regular expression.\n"
+		"         Searches the given variable, replacing each occurrence of 'oldtext'\n"
+		"         with 'newtext'. The 'oldtext' argument is a regular expression.\n"
+		"\n"
+		"         Variables are stored in &1 to &99 with &0 holding the entire matched\n"
+		"         substring.\n"
 		"\n"
-		"         Variables are stored in &1 to &99 with &0 holding the matched substring.\n",
+		"<178>Example<278>: #function rnd #math result 1d9;#replace test {%.} {@rnd{}}\n",
 
 		"cat format function local math script variable"
 	},
@@ -4057,9 +4069,10 @@ struct help_type help_table[] =
 		TOKEN_TYPE_COMMAND,
 		"<178>Command<278>: #snoop <178>{<278>session name<178>} <178>{<278>on<178>|<278>off<178>}<278>\n"
 		"\n"
-		"         If there are multiple sessions active, this command allows you to monitor\n"
-		"         what is going on in the sessions that are not currently active.  The\n"
-		"         line of text from other sessions will be prefixed by the session's name.\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"
+		"         The line of text from other sessions will be prefixed by the session's\n"
+		"         name.\n"
 		"\n"
 		"         You can toggle off snoop mode by executing #snoop a second time.\n",
 
@@ -4068,6 +4081,7 @@ struct help_type help_table[] =
 	{
 		"SPEEDWALK",
 		TOKEN_TYPE_STRING,
+		"<128>         SPEEDWALK V1\n"
 		"<278>\n"
 		"         Speedwalking allows you to enter multiple directions without using\n"
 		"         semicolons. Directions should be prefixed with a number and will be\n"
@@ -4078,8 +4092,19 @@ struct help_type help_table[] =
 		"<178>Example<278>: Without speedwalk, you have to type:\n"
 		"         <178>s;s;w;w;w;w;w;s;s;s;w;w;w;n;n;w\n"
 		"         <278>With speedwalk, you only have to type:\n"
-		"         <178>2s5w3s3w2n1w\n",
-
+		"         <178>2s5w3s3w2nw\n"
+		"\n"
+		"         <128>SPEEDWALK V2\n"
+		"<278>\n"
+		"         Modern MUDs have increasingly adopted the use of diagonal exits, like\n"
+		"         ne, nw, sw, and se. To make accomodations for this the #map and #path\n"
+		"         command no longer interpret nesw as a speedwalk and require this to\n"
+		"         be written as 1n1e1s1w, which then allows 2ne2e to execute ne;ne;e;e.\n"
+		"\n"
+		"         Speedwalks entered on the input line continue to use the v1 system.\n"
+		"\n"
+		"<178>Example<278>: #path unzip 3n1e2nw\n"
+		"<178>Example<278>: #map move 3ne1d\n",
 		"alias cursor history keypad macro tab"
 	},
 	{
@@ -4287,7 +4312,9 @@ struct help_type help_table[] =
 		TOKEN_TYPE_CONFIG,
 		"<178>Command<278>: #ticker <178>{<278>name<178>} {<278>commands<178>} {<278>interval in seconds<178>}<278>\n"
 		"\n"
-		"         Executes given command every # of seconds.\n"
+		"         Executes given command every # of seconds. Floating point precision\n"
+		"         for the interval is allowed. A ticker cannot fire more often than\n"
+		"         10 times per second.\n"
 		"\n"
 		"<178>Comment<278>: Tickers don't work in the startup session.\n"
 		"\n"

+ 4 - 4
src/history.c

@@ -104,11 +104,11 @@ struct session *repeat_history(struct session *ses, char *line)
 			add_line_history(gtd->ses, root->list[i]->arg1);
 
 			gtd->level->repeat++;
-			
-			ses = script_driver(ses, LIST_COMMAND, root->list[i]->arg1);
-			
+
+			ses = script_driver(ses, LIST_COMMAND, root->list[root->used - 1]->arg1);
+
 			gtd->level->repeat--;
-			
+
 			return ses;
 		}
 	}

+ 1 - 1
src/input.c

@@ -517,7 +517,7 @@ int check_key(char *input, int len)
 					gtd->screen->focus = 1;
 					
 					check_all_events(gtd->ses, EVENT_FLAG_SCREEN, 0, 1, "SCREEN FOCUS", ntos(gtd->screen->focus));
-					
+
 					msdp_update_all("SCREEN_FOCUS", "%d", gtd->screen->focus);
 					
 					pop_call();

+ 46 - 2
src/list.c

@@ -35,6 +35,7 @@ extern DO_ARRAY(array_collapse);
 extern DO_ARRAY(array_create);
 extern DO_ARRAY(array_delete);
 extern DO_ARRAY(array_explode);
+extern DO_ARRAY(array_filter);
 extern DO_ARRAY(array_find);
 extern DO_ARRAY(array_get);
 extern DO_ARRAY(array_index);
@@ -66,6 +67,7 @@ struct array_type array_table[] =
 	{     "CREATE",           array_create,      "Create a list table with given items"    },
 	{     "DELETE",           array_delete,      "Delete a list item with given index"     },
 	{     "EXPLODE",          array_explode,     "Explode the variable into a list"        },
+	{     "FILTER",           array_filter,      "Filter a list with given regex"          },
 	{     "FIND",             array_find,        "Find a list item with given regex"       },
 	{     "FND",              array_find,        NULL                                      },
 	{     "GET",              array_get,         "Retrieve a list item with given index"   },
@@ -384,6 +386,48 @@ DO_ARRAY(array_explode)
 	return ses;
 }
 
+DO_ARRAY(array_filter)
+{
+	int index;
+
+	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);
+
+	if (*arg1 == 0 && *arg2 == 0)
+	{
+		show_error(ses, LIST_VARIABLE, "#SYNTAX: #LIST {variable} FILTER {keep} {remove}");
+
+		return ses;
+	}
+
+	if (list->root)
+	{
+		if (*arg1)
+		{
+			for (index = 0 ; index < list->root->used ; index++)
+			{
+				if (!match(ses, list->root->list[index]->arg2, arg1, SUB_NONE))
+				{
+					delete_index_list(list->root, index--);
+				}
+			}
+		}
+
+		if (*arg2)
+		{
+			for (index = 0 ; index < list->root->used ; index++)
+			{
+				if (match(ses, list->root->list[index]->arg2, arg2, SUB_NONE))
+				{
+					delete_index_list(list->root, index--);
+				}
+			}
+		}
+	}
+
+	return ses;
+}
+
 DO_ARRAY(array_find)
 {
 	int index;
@@ -533,13 +577,13 @@ DO_ARRAY(array_order)
 
 	if (list->root->used > 1)
 	{
-		if (*list->root->list[0]->arg2 == 0)
+/*		if (*list->root->list[0]->arg2 == 0)
 		{
 			show_error(ses, LIST_COMMAND, "#ERROR: #LIST {%s} ORDER: LIST IS NOT INDEXED.", var);
 
 			return ses;
 		}
-
+*/
 		if (list->root->list[0]->root)
 		{
 			struct listroot **root_buffer;

+ 15 - 3
src/log.c

@@ -203,6 +203,20 @@ void loginit(struct session *ses, FILE *file, int flags)
 	return;
 }
 
+char *get_charset_html(struct session *ses)
+{
+	int index;
+
+	for (index = 0 ; *charset_table[index].name ; index++)
+	{
+		if (ses->charset == charset_table[index].flags)
+		{
+			return charset_table[index].html;
+		}
+	}
+	return "";
+}
+
 void write_html_header(struct session *ses, FILE *fp)
 {
 	char header[BUFFER_SIZE];
@@ -225,9 +239,7 @@ void write_html_header(struct session *ses, FILE *fp)
 		"</head>\n"
 		"<pre>\n"
 		"<span style='background-color:#000'><span style='color:#FFF'>\n",
-		HAS_BIT(gtd->ses->charset, CHARSET_FLAG_UTF8) ? "utf-8" : 
-			HAS_BIT(ses->charset, CHARSET_FLAG_BIG5) ? "big5" : 
-				HAS_BIT(ses->charset, CHARSET_FLAG_GBK1) ? "gb18030" : "iso-8859-1");
+		get_charset_html(ses));
 
 	fputs(header, fp);
 }

+ 1 - 0
src/main.c

@@ -466,6 +466,7 @@ void init_tintin(int greeting)
 	gtd->tintin_char    = '#';
 
 	gtd->time           = time(NULL);
+	gtd->utime          = utime();
 
 	for (index = 0 ; index < 100 ; index++)
 	{

+ 14 - 12
src/mapper.c

@@ -3711,7 +3711,9 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 		ses->map->search->desc = NULL;
 	}
 
-	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN); // area
+	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN);
+
+	// area
 
 	if (ses->map->search->area)
 	{
@@ -3729,7 +3731,9 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 		ses->map->search->area = NULL;
 	}
 
-	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN); // note
+	// note
+
+	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN);
 
 	if (ses->map->search->note)
 	{
@@ -3747,7 +3751,9 @@ void map_search_compile(struct session *ses, char *arg, char *var)
 		ses->map->search->note = NULL;
 	}
 
-	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN); // terrain
+	// terrain
+
+	arg = sub_arg_in_braces(ses, arg, buf, GET_ALL, SUB_VAR|SUB_FUN);
 
 	if (ses->map->search->terrain)
 	{
@@ -4551,8 +4557,6 @@ void shortest_path(struct session *ses, int run, char *delay, char *arg)
 
 	kill_list(ses->list[LIST_PATH]);
 
-	ses->list[LIST_PATH]->update = 0;
-
 	map_search_compile(ses, arg, var);
 
 	dest = searchgrid_find(ses, ses->map->in_room, ses->map->search);
@@ -4804,8 +4808,6 @@ void explore_path(struct session *ses, int run, char *arg1, char *arg2)
 
 	kill_list(ses->list[LIST_PATH]);
 
-	ses->list[LIST_PATH]->update = 0;
-
 	room = ses->map->in_room;
 
 	exit = find_exit(ses, room, arg1);
@@ -6211,6 +6213,7 @@ DO_MAP(map_info)
 		{
 			tintin_printf2(ses, "    color: %s", str_convert_meta(exit->color, TRUE));
 			tintin_printf2(ses, "  command: %s", exit->cmd);
+			tintin_printf2(ses, "    delay: %.3f", exit->delay);
 			tintin_printf2(ses, "direction: %d", exit->dir);
 			tintin_printf2(ses, "    flags: %d", exit->flags);
 			tintin_printf2(ses, "  get/set: %s", exit->data);
@@ -6218,7 +6221,6 @@ DO_MAP(map_info)
 			tintin_printf2(ses, "     name: %s", exit->name);
 			tintin_printf2(ses, "     vnum: %d", exit->vnum);
 			tintin_printf2(ses, "   weight: %.3f", exit->weight);
-			tintin_printf2(ses, "    delay: %.3f", exit->delay);
 
 			return;
 		}
@@ -6366,20 +6368,20 @@ DO_MAP(map_insert)
 
 	if (exit == NULL)
 	{
-		show_error(ses, LIST_COMMAND, "#MAP: There is no room in that direction.");
+		show_error(ses, LIST_COMMAND, "#MAP INSERT {%s}: There is no room in that direction.", arg1);
 
 		return;
 	}
 
 	if (room == ses->map->size)
 	{
-		show_error(ses, LIST_COMMAND, "#MAP: Maximum amount of rooms of %d reached.", ses->map->size);
+		show_error(ses, LIST_COMMAND, "#MAP INSERT {%s}: Maximum amount of rooms of %d reached.", arg1, ses->map->size);
 		return;
 	}
 
 	if (dir == NULL)
 	{
-		show_error(ses, LIST_COMMAND, "#MAP: Given direction must be a pathdir.");
+		show_error(ses, LIST_COMMAND, "#MAP INSERT {%s}: Given direction must be a pathdir.", arg1);
 		return;
 	}
 
@@ -6754,7 +6756,7 @@ DO_MAP(map_link)
 
 	if (room == 0)
 	{
-		show_error(ses, LIST_COMMAND, "#MAP: Couldn't find room {%s}.", arg1);
+		show_error(ses, LIST_COMMAND, "#MAP LINK {%s}: Couldn't find room {%s}.", arg1, arg2);
 		return;
 	}
 

+ 40 - 7
src/math.c

@@ -140,6 +140,32 @@ int get_ellipsis(struct listroot *root, char *name, int *min, int *max)
 	return 1 + (*min < *max ? *max - *min : *min - *max);
 }
 
+long double get_root(long double value, long double power)
+{
+	long double bot, mid, top, sum;
+
+	bot = 0;
+	top = 2;
+
+	while (pow(top, power) < value)
+	{
+		top *= 2;
+	}
+
+	while (top > 0.000000000001)
+	{
+		mid = top / 2;
+		sum = bot + mid;
+		
+		if (powl(sum, power) <= value)
+		{
+			bot += mid;
+		}
+		top -= mid;
+	}
+	return bot;
+}
+
 long double get_double(struct session *ses, char *str)
 {
 	long double val;
@@ -990,7 +1016,9 @@ void mathexp_compute(struct session *ses, struct link_data *node)
 					value = pow(tintoi(node->prev->str3), tintoi(node->next->str3));
 					break;
 				default:
-					value = tintoi(node->prev->str3) * tintoi(node->next->str3);
+//					printf("debug: precision %d prev (%s) %.*Lf * next (%s) %Lf\n", precision, node->prev->str3, precision, tintoi(node->prev->str3), node->next->str3, tintoi(node->next->str3));
+					value = (long double) tintoi(node->prev->str3) * (long double) tintoi(node->next->str3);
+//					printf("debug: value: %20Lf\n", value);
 					break;
 			}
 			break;
@@ -998,13 +1026,13 @@ void mathexp_compute(struct session *ses, struct link_data *node)
 			switch (node->str3[1])
 			{
 				case '/':
-					if (tintoi(node->next->str3) == 3)
+					if (tintoi(node->next->str3) == 2)
 					{
-						value = cbrt(tintoi(node->prev->str3));
+						value = sqrt(tintoi(node->prev->str3));
 					}
 					else
 					{
-						value = sqrt(tintoi(node->prev->str3));
+						value = get_root(tintoi(node->prev->str3), tintoi(node->next->str3));
 					}
 					break;
 				default:
@@ -1030,6 +1058,9 @@ void mathexp_compute(struct session *ses, struct link_data *node)
 			}
 			break;
 		case '%':
+			value = fmod(tintoi(node->prev->str3), tintoi(node->next->str3));
+
+/*
 			if (tintoi(node->next->str3) == 0)
 			{
 				show_debug(ses, LIST_VARIABLE, "#MATH ERROR: MODULO ZERO.");
@@ -1041,6 +1072,7 @@ void mathexp_compute(struct session *ses, struct link_data *node)
 
 				value64 = tintou(node->prev->str3) % tintou(node->next->str3);
 			}
+*/
 			break;
 		case '+':
 			value = tintoi(node->prev->str3) + tintoi(node->next->str3);
@@ -1170,7 +1202,7 @@ void mathexp_compute(struct session *ses, struct link_data *node)
 	else
 	{
 //		sprintf(temp, "%.*Lf", precision, value);
-		sprintf(temp, "%Lf", value);
+		sprintf(temp, "%.12Lf", value);
 	}
 	free(node->str3);
 	node->str3 = strdup(temp);
@@ -1256,7 +1288,7 @@ long double tintoi(char *str)
 				break;
 
 			case ':':
-//				show_error(gtd->ses, LIST_COMMAND, "\e[1;31m#WARNING: THE : TIME OPERATOR IN #MATH WILL BE REMOVED IN FUTURE RELEASES.");
+				show_error(gtd->ses, LIST_COMMAND, "\e[1;31m#WARNING: THE : TIME OPERATOR IN #MATH WILL BE REMOVED IN FUTURE RELEASES.");
 
 				switch (i)
 				{
@@ -1363,7 +1395,8 @@ unsigned long long tintou(char *str)
 				break;
 
 			case '.':
-				*ptr = 0;
+				value = 0;
+				m = 1;
 				break;
 
 			case ':':

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 8 - 0
src/misc.c


+ 4 - 4
src/net.c

@@ -219,7 +219,7 @@ int connect_mud(struct session *ses, char *host, char *port)
 	}
 	else
 	{
-		show_error(ses, "#CONNECT: THE PORT {%s} SHOULD BE A NUMBER.", port);
+		show_error(ses, LIST_COMMAND, "#CONNECT: THE PORT {%s} SHOULD BE A NUMBER.", port);
 		return -1;
 	}
 
@@ -487,7 +487,7 @@ void readmud(struct session *ses)
 					if (ses->packet_patch)
 					{
 						str_cat(&ses->more_output, line);
-						ses->check_output = utime() + ses->packet_patch;
+						ses->check_output = gtd->utime + ses->packet_patch;
 
 						break;
 					}
@@ -498,14 +498,14 @@ void readmud(struct session *ses)
 							if (!detect_prompt(ses, line))
 							{
 								str_cat(&ses->more_output, line);
-								ses->check_output = utime() + 500000ULL;
+								ses->check_output = gtd->utime + 500000ULL;
 								break;
 							}
 						}
 						else if (HAS_BIT(ses->config_flags, CONFIG_FLAG_AUTOPROMPT))
 						{
 							str_cat(&ses->more_output, line);
-							ses->check_output = utime() + 500000ULL;
+							ses->check_output = gtd->utime + 500000ULL;
 							break;
 						}
 					}

+ 41 - 13
src/path.c

@@ -80,8 +80,6 @@ DO_PATH(path_create)
 
 	kill_list(root);
 
-	root->update = 0;
-
 	show_message(ses, LIST_COMMAND, "#PATH CREATE: YOU START MAPPING A NEW PATH.");
 
 	SET_BIT(ses->flags, SES_FLAG_PATHMAPPING);
@@ -94,8 +92,6 @@ DO_PATH(path_destroy)
 
 	kill_list(root);
 
-	root->update = 0;
-
 	DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
 
 	show_message(ses, LIST_COMMAND, "#PATH DESTROY: PATH DESTROYED.");
@@ -291,10 +287,32 @@ DO_PATH(path_get)
 	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);
 
-	if (*arg2 == 0)
+	if (*arg1 == 0 && *arg2 == 0)
 	{
 		tintin_printf2(ses, "  length: %d", root->used);
 		tintin_printf2(ses, "position: %d", root->update + 1);
+		tintin_printf2(ses, " mapping: %d", HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING) ? 1 : 0);
+		tintin_printf2(ses, " running: %.2f",
+			root->update >= root->used ? 0 :
+			root->list[root->update]->val64 == 0 ? 0 :
+			(root->list[root->update]->val64 - gtd->utime) < 10000 ? 0.01 :
+			(root->list[root->update]->val64 - gtd->utime) / 1000000.0);
+	}
+	else if (*arg2 == 0)
+	{
+		set_nest_node_ses(ses, arg2, "{length}{%d}", root->used);
+
+		add_nest_node_ses(ses, arg2, "{position}{%d}", root->update + 1);
+
+		add_nest_node_ses(ses, arg2, "{mapping}{%d}", HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING) ? 1 : 0);
+
+		add_nest_node_ses(ses, arg2, "{running}{%.2f}",
+			root->update >= root->used ? 0 :
+			root->list[root->update]->val64 == 0 ? 0 :
+			(root->list[root->update]->val64 - gtd->utime) < 10000 ? 0.01 :
+			(root->list[root->update]->val64 - gtd->utime) / 1000000.0);
+
+		show_message(ses, LIST_COMMAND, "#PATH GET: PATH INFO SAVED TO {%s}", arg2);
 	}
 	else if (is_abbrev(arg1, "LENGTH"))
 	{
@@ -304,6 +322,14 @@ DO_PATH(path_get)
 
 		show_message(ses, LIST_COMMAND, "#PATH GET: PATH LENGTH {%s} SAVED TO {%s}", result, arg2);
 	}
+	else if (is_abbrev(arg1, "MAPPING"))
+	{
+		sprintf(result, "%d", HAS_BIT(ses->flags, SES_FLAG_PATHMAPPING) ? 1 : 0);
+
+		set_nest_node_ses(ses, arg2, "%s", result);
+
+		show_message(ses, LIST_COMMAND, "#PATH GET: PATH MAPPING {%s} SAVED TO {%s}", result, arg2);
+	}
 	else if (is_abbrev(arg1, "POSITION"))
 	{
 		sprintf(result, "%d", root->update + 1);
@@ -312,6 +338,16 @@ DO_PATH(path_get)
 
 		show_message(ses, LIST_COMMAND, "#PATH GET: PATH POSITION {%s} SAVED TO {%s}", result, arg2);
 	}
+	else if (is_abbrev(arg1, "RUNNING"))
+	{
+		sprintf(result, "%.2f",
+			root->update >= root->used ? 0 :
+			root->list[root->update]->val64 == 0 ? 0 :
+			(root->list[root->update]->val64 - gtd->utime) < 10000 ? 0.01 :
+			(root->list[root->update]->val64 - gtd->utime) / 1000000.0);
+
+		show_message(ses, LIST_COMMAND, "#PATH GET: PATH RUNNING {%s} SAVED TO {%s}", result, arg2);
+	}
 	else
 	{
 		show_error(ses, LIST_COMMAND, "#SYNTAX: #PATH GET <LENGTH|POSITION> <VARIABLE NAME>");
@@ -431,8 +467,6 @@ DO_PATH(path_load)
 
 	kill_list(root);
 
-	root->update = 0;
-
 	DEL_BIT(ses->flags, SES_FLAG_PATHMAPPING);
 
 	gtd->level->input++;
@@ -715,8 +749,6 @@ DO_PATH(path_zip)
 		}
 	}
 
-	root->update = root->used;
-
 	kill_list(root);
 
 	create_node_list(root, arg1, arg2, "0", "");
@@ -745,8 +777,6 @@ DO_PATH(path_unzip)
 
 	kill_list(root);
 
-	root->update = 0;
-
 	while (*arg)
 	{
 		switch (*arg)
@@ -1161,8 +1191,6 @@ DO_PATH(path_new)
 	{
 		kill_list(root);
 
-		root->update = 0;
-
 		show_message(ses, LIST_COMMAND, "#PATH NEW: YOU ARE NOW MAPPING A PATH.");
 
 		SET_BIT(ses->flags, SES_FLAG_PATHMAPPING);

+ 19 - 0
src/regex.c

@@ -228,6 +228,25 @@ int get_regex_range(char *in, char *out, int *var, int *arg)
 	pti = in;
 	ptr = range;
 
+	switch (*pti)
+	{
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+			*ptr++ = *pti++;
+			break;
+
+		default:
+			goto end;
+	}
+
 	while (*pti)
 	{
 		switch (*pti)

+ 11 - 10
src/session.c

@@ -205,7 +205,7 @@ DO_COMMAND(do_zap)
 
 		if (sesptr == NULL)
 		{
-			show_error(ses, LIST_COMMAND, "#ZAP: THERE'S NO SESSION WITH THAT NAME!");
+			show_error(ses, LIST_COMMAND, "#ZAP: THERE'S NO SESSION NAMED {%s}", arg1);
 
 			pop_call();
 			return ses;
@@ -235,8 +235,11 @@ DO_COMMAND(do_zap)
 		pop_call();
 		return gtd->ses;
 	}
+
 	cleanup_session(sesptr);
 
+	show_message(ses, LIST_COMMAND, "#ZAP: SESSION {%s} HAS BEEN ZAPPED.", sesptr->name);
+
 	pop_call();
 	return ses;
 }
@@ -302,20 +305,18 @@ struct session *newactive_session(void)
 
 struct session *activate_session(struct session *ses)
 {
-	check_all_events(gtd->ses, EVENT_FLAG_SESSION, 0, 1, "SESSION DEACTIVATED", gtd->ses->name);
+	check_all_events(gtd->ses, EVENT_FLAG_SESSION, 0, 2, "SESSION DEACTIVATED", gtd->ses->name, ses->name);
 
 	gtd->ses = ses;
 
 	dirty_screen(ses);
 
-	if (!check_all_events(ses, EVENT_FLAG_GAG, 0, 1, "GAG SESSION ACTIVATED", ses->name))
+	if (!check_all_events(ses, EVENT_FLAG_GAG, 0, 2, "GAG SESSION ACTIVATED", ses->name, gtd->ses->name))
 	{
-		buffer_refresh(ses, "", "", "");
-
 		show_message(ses, LIST_COMMAND, "#SESSION '%s' ACTIVATED.", ses->name);
 	}
 
-	check_all_events(ses, EVENT_FLAG_SESSION, 0, 1, "SESSION ACTIVATED", ses->name);
+	check_all_events(ses, EVENT_FLAG_SESSION, 0, 2, "SESSION ACTIVATED", ses->name, gtd->ses->name);
 
 	return ses;
 }
@@ -393,7 +394,7 @@ struct session *new_session(struct session *ses, char *name, char *arg, int desc
 	newses->logname        = strdup("");
 	newses->lognext_name   = strdup("");
 	newses->logline_name   = strdup("");
-	newses->rand           = utime();
+	newses->rand           = ++gtd->utime;
 
 	newses->more_output    = str_dup("");
 
@@ -529,7 +530,7 @@ struct session *connect_session(struct session *ses)
 
 	push_call("connect_session(%p)",ses);
 
-	ses->connect_retry = utime() + gts->connect_retry;
+	ses->connect_retry = ++gtd->time + gts->connect_retry;
 
 	reconnect:
 
@@ -570,7 +571,7 @@ struct session *connect_session(struct session *ses)
 		return ses;
 	}
 
-	if (ses->connect_retry > utime())
+	if (ses->connect_retry > gtd->utime)
 	{
 		fd_set readfds;
 
@@ -583,7 +584,7 @@ struct session *connect_session(struct session *ses)
 			{
 				to.tv_sec = 1;
 
-				tintin_printf(ses, "#SESSION '%s' FAILED TO CONNECT. RETRYING FOR %d SECONDS.", ses->name, (ses->connect_retry - utime()) / 1000000);
+				tintin_printf(ses, "#SESSION '%s' FAILED TO CONNECT. RETRYING FOR %d SECONDS.", ses->name, (ses->connect_retry - gtd->utime) / 1000000);
 			}
 
 			goto reconnect;

+ 2 - 2
src/split.c

@@ -302,7 +302,7 @@ void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 		return;
 	}
 
-	if (inside_scroll_region(ses, row, col))
+	if (row != gtd->screen->rows && 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);
 
@@ -333,7 +333,7 @@ void split_show(struct session *ses, char *prompt, char *row_str, char *col_str)
 
 	if (row == gtd->screen->rows)
 	{
-		gtd->ses->input->str_off = len + 1;
+		gtd->ses->input->str_off = width + 1;
 
 		goto_pos(ses, row, col);
 

+ 179 - 3
src/substitute.c

@@ -870,6 +870,171 @@ char *lit_color_code(struct session *ses, char *pti, int mod)
 	return "";
 }
 
+int color_gradient(char *pti, int min, int max)
+{
+	char buf[6];
+	int lvl, cap;
+
+	if (strlen(pti) < 10)
+	{
+		return 0;
+	}
+
+	if (pti[0] == '<' && pti[4] == '>' && pti[5] == '<' && pti[9] == '>')
+	{
+//		if (pti[1] >= 'A' && pti[1] <= 'F' && pti[2] >= 'A' && pti[2] <= 'F' && pti[3] >= 'A' && pti[3] <= 'F')
+		if (pti[1] >= 'a' && pti[1] <= 'f' && pti[2] >= 'a' && pti[2] <= 'f' && pti[3] >= 'a' && pti[3] <= 'f')
+		{
+			if (pti[6] >= 'a' && pti[6] <= 'f' && pti[7] >= 'a' && pti[7] <= 'f' && pti[8] >= 'a' && pti[8] <= 'f')
+			{
+				buf[1] = pti[1];
+				buf[2] = pti[2];
+				buf[3] = pti[3];
+
+				for (cap = lvl = 0 ; cap < 50 ; cap++)
+				{
+//					printf("cap %2d lvl %d <%c%c%c>\n",cap,lvl,buf[1],buf[2],buf[3]);
+
+					if (lvl == 0)
+					{
+						if (buf[1] > 'a' && buf[1] < 'f')
+						{
+							buf[1]++;
+							continue;
+						}
+						if (buf[2] > 'a' && buf[2] < 'f')
+						{
+							buf[2]++;
+							continue;
+						}
+						if (buf[3] > 'a' && buf[3] < 'f')
+						{
+							buf[3]++;
+							continue;
+						}
+						lvl++;
+					}
+
+					if (lvl == 1)
+					{
+						if (pti[6] > 'a' && buf[1] < 'f')
+						{
+							buf[1]++;
+							continue;
+						}
+						if (pti[7] > 'a' && buf[2] < 'f')
+						{
+							buf[2]++;
+							continue;
+						}
+						if (pti[8] > 'a' && buf[3] < 'f')
+						{
+							buf[3]++;
+							continue;
+						}
+						lvl++;
+					}
+					
+					if (buf[1] > 'a' && pti[6] < buf[1])
+					{
+						buf[1]--;
+						continue;
+					}
+
+					if (buf[2] > 'a' && pti[7] < buf[2])
+					{
+						buf[2]--;
+						continue;
+					}
+
+					if (buf[3] > 'a' && pti[8] < buf[3])
+					{
+						buf[3]--;
+						continue;
+					}
+					break;
+				}
+				cap = cap * min / max;
+
+				buf[1] = pti[1];
+				buf[2] = pti[2];
+				buf[3] = pti[3];
+
+				for (min = lvl = 0 ; min < cap ; min++)
+				{
+					if (lvl == 0)
+					{
+						if (buf[1] > 'a' && buf[1] < 'f')
+						{
+							buf[1]++;
+							continue;
+						}
+						if (buf[2] > 'a' && buf[2] < 'f')
+						{
+							buf[2]++;
+							continue;
+						}
+						if (buf[3] > 'a' && buf[3] < 'f')
+						{
+							buf[3]++;
+							continue;
+						}
+						lvl++;
+					}
+
+					if (lvl == 1)
+					{
+						if (pti[6] > 'a' && buf[1] < 'f')
+						{
+							buf[1]++;
+							continue;
+						}
+						if (pti[7] > 'a' && buf[2] < 'f')
+						{
+							buf[2]++;
+							continue;
+						}
+						if (pti[8] > 'a' && buf[3] < 'f')
+						{
+							buf[3]++;
+							continue;
+						}
+						lvl++;
+					}
+					
+					if (pti[6] < buf[1])
+					{
+						buf[1]--;
+						continue;
+					}
+					if (pti[7] < buf[2])
+					{
+						buf[2]--;
+						continue;
+					}
+					if (pti[8] < buf[3])
+					{
+						buf[3]--;
+						continue;
+					}
+					break;
+				}
+
+				pti[6] = buf[1];
+				pti[7] = buf[2];
+				pti[8] = buf[3];
+
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+
+// color gradient <faa><afa>
+// faa fba fca fda fea ffa efa dfa cfa bfa afa
+
+
 int substitute(struct session *ses, char *string, char *result, int flags)
 {
 	struct listnode *node;
@@ -950,11 +1115,18 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 						i++;
 					}
 
-					for (ptt = temp ; is_alnum(pti[i]) || pti[i] == '_' ; i++)
+					if (pti[i] == DEFAULT_OPEN)
 					{
-						*ptt++ = pti[i];
+						i = sub_arg_in_braces(ses, &pti[i], temp, GET_ONE, flags_neol) - pti;
+					}
+					else
+					{
+						for (ptt = temp ; is_alnum(pti[i]) || pti[i] == '_' ; i++)
+						{
+							*ptt++ = pti[i];
+						}
+						*ptt = 0;
 					}
-					*ptt = 0;
 
 					if (pti[i] != DEFAULT_OPEN)
 					{
@@ -2151,6 +2323,8 @@ int is_color_name(char *string)
 	return TRUE;
 }
 
+// get any color, don't sub.
+
 int translate_color_names(struct session *ses, char *string, char *result)
 {
 	int cnt, skip;
@@ -2243,6 +2417,8 @@ int translate_color_names(struct session *ses, char *string, char *result)
 	return TRUE;
 }
 
+// get any color, sub
+
 int get_color_names(struct session *ses, char *string, char *result)
 {
 	int cnt, skip;

+ 24 - 4
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                                 },
 	{    "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 },
-	{    "DELAY",             "DELAYS",             SORT_DELAY,       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 },
 	{    "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 },
@@ -69,6 +69,25 @@ struct substitution_type substitution_table[] =
 	{    "",                     0       }
 };
 
+struct charset_type charset_table[] =
+{
+	{    "ASCII",         "iso-8859-1",  0                 },
+	{    "UTF-8",         "utf-8",       CHARSET_FLAG_UTF8 },
+	{    "BIG-5",         "big-5",       CHARSET_FLAG_BIG5 },
+	{    "GBK-1",         "gb18030",     CHARSET_FLAG_GBK1 },
+	{    "CP949",         "cp949",       CHARSET_FLAG_CP949 },
+
+	{    "BIG5TOUTF8",    "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_BIG5TOUTF8 },
+	{    "CP1251TOUTF8",  "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_CP1251TOUTF8 },
+	{    "CP949TOUTF8",   "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_CP949TOUTF8 },
+	{    "FANSITOUTF8",   "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_FANSITOUTF8 },
+	{    "GBK1TOUTF8",    "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_GBK1TOUTF8 },
+	{    "ISO1TOUTF8",    "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO1TOUTF8 },
+	{    "ISO2TOUTF8",    "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO2TOUTF8 },
+	{    "KOI8TOUTF8",    "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_KOI8TOUTF8 },
+	{    "",              "",            0 }
+};
+
 struct config_type config_table[] =
 {
 	{
@@ -1020,8 +1039,9 @@ struct event_type event_table[] =
 	{    "PRESSED ",                               0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse button is pressed"    },
 	{    "PROCESSED KEYPRESS",                     0, EVENT_FLAG_INPUT,    "INPUT",     "after a regular keypress"   },
 	{    "PROGRAM START",                          0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "main session starts"        },
-	{    "PROGRAM TERMINATION",                    0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "main session exists"        },
+	{    "PROGRAM TERMINATION",                    0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "main session exits"         },
 	{    "READ ERROR",                             0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "the read command fails"     },
+	{    "READ FILE",                              0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "the read command finished"  },
 	{    "RECEIVED ERROR",                         0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "an error is received"       },
 	{    "RECEIVED INPUT",                         0, EVENT_FLAG_INPUT,    "INPUT",     "keyboard input is received" },
 	{    "RECEIVED KEYPRESS",                      0, EVENT_FLAG_INPUT,    "INPUT",     "a keypress is received"     },
@@ -1037,7 +1057,7 @@ struct event_type event_table[] =
 	{    "SCREEN DESKTOP SIZE",                    0, EVENT_FLAG_SCREEN,   "SCREEN",    "called by #screen raise"    },
 	{    "SCREEN DIMENSIONS",                      0, EVENT_FLAG_SCREEN,   "SCREEN",    "called by #screen raise"    },
 	{    "SCREEN FILL",                            0, EVENT_FLAG_SCREEN,   "SCREEN",    "split bars are filled"      },
-	{    "SCREEN FOCUS",                           0, EVENT_FLAG_MOUSE,    "MOUSE",     "focus changes",             },
+	{    "SCREEN FOCUS",                           0, EVENT_FLAG_SCREEN,   "SCREEN",    "focus changes",             },
 	{    "SCREEN LOCATION",                        0, EVENT_FLAG_SCREEN,   "SCREEN",    "called by #screen raise"    },
 	{    "SCREEN MINIMIZED",                       0, EVENT_FLAG_SCREEN,   "SCREEN",    "called by #screen raise"    },
 	{    "SCREEN MOUSE LOCATION",                  0, EVENT_FLAG_MOUSE,    "MOUSE",     "called by #screen raise"    },
@@ -1067,7 +1087,7 @@ struct event_type event_table[] =
 	{    "SWIPED",                                 0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse swipe"                },
 	{    "SYSTEM CRASH",                           0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "system crash"               },
 	{    "SYSTEM ERROR",                           0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "system errors"              },
-	{    "TIME",                                   0, EVENT_FLAG_TIME,     "TIME",      "the given time"             },
+	{    "TIME ",                                  0, EVENT_FLAG_TIME,     "TIME",      "the given time"             },
 	{    "TRIPLE-CLICKED",                         0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is triple-clicked"    },
 	{    "UNKNOWN COMMAND",                        0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "unknown tintin command"     },
 	{    "VARIABLE UPDATE ",                       0, EVENT_FLAG_VARIABLE, "VARIABLE",  "before a variable updates"  },

+ 30 - 79
src/telopt_client.c

@@ -1300,7 +1300,7 @@ int client_recv_sb_charset(struct session *ses, int cplen, unsigned char *src)
 {
 	char buf[BUFFER_SIZE], var[BUFFER_SIZE];
 	char *pto;
-	int i;
+	int i, j, accept;
 
 	if (client_skip_sb(ses, cplen, src) > cplen)
 	{
@@ -1348,77 +1348,46 @@ int client_recv_sb_charset(struct session *ses, int cplen, unsigned char *src)
 		{
 			if (!strcmp(buf, "REQUEST"))
 			{
-				if (!strcasecmp(var, "UTF-8"))
+				for (j = 0 ; var[j] ; j++)
 				{
-					if (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && !HAS_BIT(ses->charset, CHARSET_FLAG_ALL_TOUTF8))
-					{
-						telnet_printf(ses, 12, "%c%c%c%c UTF-8%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_ACCEPTED, IAC, SE);
-
-						client_telopt_debug(ses, "SENT IAC SB CHARSET ACCEPTED UTF-8");
-					}
-					else
-					{
-						telnet_printf(ses, 12, "%c%c%c%c UTF-8%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_REJECTED, IAC, SE);
+					var[j] = toupper((int) var[j]);
+				}
+				accept = -1;
 
-						client_telopt_debug(ses, "SENT IAC SB CHARSET REJECTED UTF-8");
-					}
+				if (!strcmp(var, "UTF-8"))
+				{
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && !HAS_BIT(ses->charset, CHARSET_FLAG_ALL_TOUTF8);
 				}
-				else if (!strcasecmp(var, "BIG-5"))
+				else if (!strcmp(var, "BIG-5"))
 				{
-					if (HAS_BIT(ses->charset, CHARSET_FLAG_BIG5) || HAS_BIT(ses->charset, CHARSET_FLAG_BIG5TOUTF8))
-					{
-						telnet_printf(ses, 12, "%c%c%c%c BIG-5%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_ACCEPTED, IAC, SE);
-
-						client_telopt_debug(ses, "SENT IAC SB CHARSET ACCEPTED BIG-5");
-					}
-					else
-					{
-						telnet_printf(ses, 12, "%c%c%c%c BIG-5%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_REJECTED, IAC, SE);
-
-						client_telopt_debug(ses, "SENT IAC SB CHARSET REJECTED BIG-5");
-					}
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_BIG5) || HAS_BIT(ses->charset, CHARSET_FLAG_BIG5TOUTF8);
 				}
-				else if (!strcasecmp(var, "FANSI"))
+				else if (!strcmp(var, "CP949"))
 				{
-					if (!check_all_events(ses, EVENT_FLAG_CATCH, 2, 2, "CATCH IAC SB CHARSET %s %s", buf, var, buf, var))
-					{
-						if (HAS_BIT(ses->charset, CHARSET_FLAG_FANSITOUTF8))
-						{
-							telnet_printf(ses, 12, "%c%c%c%c FANSI%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_ACCEPTED, IAC, SE);
-
-							client_telopt_debug(ses, "SENT IAC SB CHARSET ACCEPTED FANSI");
-						}
-						else
-						{
-							telnet_printf(ses, 12, "%c%c%c%c FANSI%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_REJECTED, IAC, SE);
-
-							client_telopt_debug(ses, "SENT IAC SB CHARSET REJECTED FANSI");
-						}
-					}
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_CP949) || HAS_BIT(ses->charset, CHARSET_FLAG_CP949TOUTF8);
 				}
-				else if (!strcasecmp(var, "ISO-8859-1") || !strcasecmp(var, "ISO-1"))
+				else if (!strcmp(var, "FANSI"))
 				{
-					if (!check_all_events(ses, EVENT_FLAG_CATCH, 2, 2, "CATCH IAC SB CHARSET %s %s", buf, var, buf, var))
-					{
-						if (HAS_BIT(ses->charset, CHARSET_FLAG_ISO1TOUTF8))
-						{
-							telnet_printf(ses, -1, "%c%c%c%c %s%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_ACCEPTED, var, IAC, SE);
-							
-							client_telopt_debug(ses, "SENT IAC SB CHARSET ACCEPTED %s", var);
-						}
-						else
-						{
-							telnet_printf(ses, -1, "%c%c%c%c %s%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_REJECTED, var, IAC, SE);
-
-							client_telopt_debug(ses, "SENT IAC SB CHARSET REJECTED %s", var);
-						}
-					}
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_FANSITOUTF8);
+				}
+				else if (!strcmp(var, "ISO-8859-1") || !strcasecmp(var, "ISO-1"))
+				{
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_ISO1TOUTF8);
 				}
-				else if (!strcasecmp(var, "ISO-8859-2") || !strcasecmp(var, "ISO-2"))
+				else if (!strcmp(var, "ISO-8859-2") || !strcasecmp(var, "ISO-2"))
 				{
-					if (!check_all_events(ses, EVENT_FLAG_CATCH, 2, 2, "CATCH IAC SB CHARSET %s %s", buf, var, buf, var))
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_ISO2TOUTF8);
+				}
+				else if (!strcmp(var, "GBK-1") || !strcmp(var, "GB18030"))
+				{
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_GBK1) || HAS_BIT(ses->charset, CHARSET_FLAG_GBK1TOUTF8);
+				}
+
+				if (!check_all_events(ses, EVENT_FLAG_CATCH, 2, 2, "CATCH IAC SB CHARSET %s %s", buf, var, buf, var))
+				{
+					if (accept >= 0)
 					{
-						if (HAS_BIT(ses->charset, CHARSET_FLAG_ISO2TOUTF8))
+						if (accept)
 						{
 							telnet_printf(ses, -1, "%c%c%c%c %s%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_ACCEPTED, var, IAC, SE);
 							
@@ -1432,24 +1401,6 @@ int client_recv_sb_charset(struct session *ses, int cplen, unsigned char *src)
 						}
 					}
 				}
-				else if (!strcasecmp(var, "GBK-1"))
-				{
-					if (!check_all_events(ses, EVENT_FLAG_CATCH, 2, 2, "CATCH IAC SB CHARSET %s %s", buf, var, buf, var))
-					{
-						if (HAS_BIT(ses->charset, CHARSET_FLAG_GBK1TOUTF8))
-						{
-							telnet_printf(ses, 12, "%c%c%c%c GBK-1%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_ACCEPTED, IAC, SE);
-
-							client_telopt_debug(ses, "SENT IAC SB CHARSET ACCEPTED GBK-1");
-						}
-						else
-						{
-							telnet_printf(ses, 16, "%c%c%c%c GB-18030%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_REJECTED, IAC, SE);
-
-							client_telopt_debug(ses, "SENT IAC SB CHARSET REJECTED GBK-1");
-						}
-					}
-				}
 			}
 		}
 		i++;

+ 11 - 36
src/terminal.c

@@ -80,7 +80,7 @@ void init_terminal(struct session *ses)
 		syserr_fatal(-1, "init_terminal: tcgetattr 2");
 	}
 
-	print_stdout(0, 0, "\e=\e[>4;1m");
+	print_stdout(0, 0, "\e[?1004h\e=\e[>4;1m");
 }
 
 void reset_terminal(struct session *ses)
@@ -95,9 +95,9 @@ void reset_terminal(struct session *ses)
 
 	if (HAS_BIT(gtd->flags, TINTIN_FLAG_MOUSETRACKING))
 	{
-		print_stdout(0, 0, "\e[?1000l\e[?1002l\e[?1004l\e[?1006l");
+		print_stdout(0, 0, "\e[?1000l\e[?1002l\e[?1006l");
 	}
-	print_stdout(0, 0, "\e[?25h\e[23t\e[>4n\e[?47l\e[r\e[0#t");
+	print_stdout(0, 0, "\e[?25h\e[23t\e[?1004l\e[>4n\e[?47l\e[r\e[0#t");
 }
 
 
@@ -206,39 +206,14 @@ int get_scroll_cols(struct session *ses)
 
 char *get_charset(struct session *ses)
 {
-	switch (HAS_BIT(ses->charset, CHARSET_FLAG_ALL))
-	{
-		case CHARSET_FLAG_BIG5:
-			return "BIG-5";
-
-		case CHARSET_FLAG_GBK1:
-			return "GBK-1";
-
-		case CHARSET_FLAG_UTF8:
-			return "UTF-8";
-
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_BIG5TOUTF8:
-			return "BIG5TOUTF8";
-
-	        case CHARSET_FLAG_UTF8|CHARSET_FLAG_CP1251TOUTF8:
-	        	return "CP1251TOUTF8";
-
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_FANSITOUTF8:
-			return "FANSI";
-		
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_GBK1TOUTF8:
-			return "GBK1TOUTF8";
+	int index;
 
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_KOI8TOUTF8:
-			return "KOI8TOUTF8";
-
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO1TOUTF8:
-			return "ISO1TOUTF8";
-
-		case CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO2TOUTF8:
-			return "ISO2TOUTF8";
-
-		default:
-			return "ASCII";
+	for (index = 0 ; *charset_table[index].name ; index++)
+	{
+		if (ses->charset == charset_table[index].flags)
+		{
+			return charset_table[index].name;
+		}
 	}
+	return "ASCII";
 }

+ 35 - 20
src/tintin.h

@@ -132,8 +132,13 @@
 #define SORT_PRIORITY                    0
 #define SORT_ALPHA                       1
 #define SORT_ALNUM                       2
-#define SORT_APPEND                      3
-#define SORT_DELAY                       4
+#define SORT_STABLE                      3
+#define SORT_APPEND                      4
+#define SORT_DELAY                       5
+
+#define SEEK_MATCH                       0
+#define SEEK_REPLACE                     1
+#define SEEK_APPEND                      2
 
 #define DEFAULT_OPEN                   '{'
 #define DEFAULT_CLOSE                  '}'
@@ -203,7 +208,7 @@
 #define STRING_SIZE        2 * BUFFER_SIZE
 
 #define CLIENT_NAME              "TinTin++"
-#define CLIENT_VERSION           "2.02.05 "
+#define CLIENT_VERSION           "2.02.10 "
 
 
 #define XT_E                            0x27
@@ -393,17 +398,19 @@ enum operators
 #define CHARSET_FLAG_UTF8                 BV01
 #define CHARSET_FLAG_BIG5                 BV02
 #define CHARSET_FLAG_GBK1                 BV03
-
-#define CHARSET_FLAG_BIG5TOUTF8           BV04
-#define CHARSET_FLAG_FANSITOUTF8          BV05
-#define CHARSET_FLAG_GBK1TOUTF8           BV06
-#define CHARSET_FLAG_ISO1TOUTF8           BV07
-#define CHARSET_FLAG_ISO2TOUTF8           BV08
-#define CHARSET_FLAG_KOI8TOUTF8           BV09
-#define CHARSET_FLAG_CP1251TOUTF8         BV10
-
-#define CHARSET_FLAG_EUC                  CHARSET_FLAG_BIG5|CHARSET_FLAG_GBK1
-#define CHARSET_FLAG_ALL_TOUTF8           CHARSET_FLAG_BIG5TOUTF8|CHARSET_FLAG_CP1251TOUTF8|CHARSET_FLAG_FANSITOUTF8|CHARSET_FLAG_GBK1TOUTF8|CHARSET_FLAG_ISO1TOUTF8|CHARSET_FLAG_ISO2TOUTF8|CHARSET_FLAG_KOI8TOUTF8
+#define CHARSET_FLAG_CP949                BV04
+
+#define CHARSET_FLAG_BIG5TOUTF8           BV05
+#define CHARSET_FLAG_FANSITOUTF8          BV06
+#define CHARSET_FLAG_GBK1TOUTF8           BV07
+#define CHARSET_FLAG_ISO1TOUTF8           BV08
+#define CHARSET_FLAG_ISO2TOUTF8           BV09
+#define CHARSET_FLAG_KOI8TOUTF8           BV10
+#define CHARSET_FLAG_CP1251TOUTF8         BV11
+#define CHARSET_FLAG_CP949TOUTF8          BV12
+
+#define CHARSET_FLAG_EUC                  CHARSET_FLAG_BIG5|CHARSET_FLAG_GBK1|CHARSET_FLAG_CP949
+#define CHARSET_FLAG_ALL_TOUTF8           CHARSET_FLAG_BIG5TOUTF8|CHARSET_FLAG_CP1251TOUTF8|CHARSET_FLAG_FANSITOUTF8|CHARSET_FLAG_GBK1TOUTF8|CHARSET_FLAG_ISO1TOUTF8|CHARSET_FLAG_ISO2TOUTF8|CHARSET_FLAG_KOI8TOUTF8|CHARSET_FLAG_CP949TOUTF8
 #define CHARSET_FLAG_ALL                  CHARSET_FLAG_UTF8|CHARSET_FLAG_ALL_TOUTF8|CHARSET_FLAG_EUC
 
 
@@ -1631,6 +1638,13 @@ struct buffer_type
 	char                  * desc;
 };
 
+struct charset_type
+{
+	char                  * name;
+	char                  * html;
+	int                     flags;
+};
+
 struct chat_type
 {
 	char                  * name;
@@ -2782,6 +2796,7 @@ extern  int valid_escape(struct session *ses, char *arg);
 extern char *fuzzy_color_code(struct session *ses, char *pti);
 extern char *dim_color_code(struct session *ses, char *pti, int mod);
 extern char *lit_color_code(struct session *ses, char *pti, int mod);
+extern int color_gradient(char *pti, int low, int max);
 extern int is_color_code(char *str);
 extern int is_color_name(char *str);
 extern int substitute_color(char *input, char *output, int colors);
@@ -2800,6 +2815,7 @@ extern DO_COMMAND(do_suspend);
 #define __TABLES_H__
 
 extern struct buffer_type buffer_table[];
+extern struct charset_type charset_table[];
 extern struct chat_type chat_table[];
 extern   char character_table[];
 extern struct color_type color_table[];
@@ -2807,7 +2823,6 @@ extern struct color_type map_color_table[];
 extern struct config_type config_table[];
 extern struct cursor_type cursor_table[];
 extern struct daemon_type daemon_table[];
-//extern struct draw_type draw_table[];
 extern struct edit_type edit_table[];
 extern struct event_type event_table[];
 extern struct history_type history_table[];
@@ -2818,13 +2833,11 @@ extern struct map_type map_table[];
 extern struct path_type path_table[];
 extern struct port_type port_table[];
 extern struct rank_type rank_table[];
-//extern struct scan_type scan_table[];
 extern struct stamp_type huge_stamp_table[];
 extern struct substitution_type substitution_table[];
 extern struct telopt_type telopt_table[];
 extern   char *telcmds[];
 extern struct timer_type timer_table[];
-//extern struct screen_type screen_table[];
 extern struct map_legend_type map_legend_table[];
 extern struct map_legend_group_type map_legend_group_table[];
 
@@ -2979,6 +2992,8 @@ extern int utf8_strlen(char *str, int *width);
 
 extern int utf8_to_all(struct session *ses, char *in, char *out);
 extern int all_to_utf8(struct session *ses, char *in, char *out);
+extern int cp1251_to_utf8(char *input, char *output);
+extern int utf8_to_cp1251(char *input, char *output);
 extern int iso1_to_utf8(char *input, char *output);
 extern int utf8_to_iso1(char *input, char *output);
 extern int iso2_to_utf8(char *input, char *output);
@@ -2995,9 +3010,9 @@ extern int utf8_to_big5(char *input, char *output);
 extern int is_gbk1(char *str);
 extern int gbk1_to_utf8(char *input, char *output);
 extern int utf8_to_gbk1(char *input, char *output);
-
-extern int cp1251_to_utf8(char *input, char *output);
-extern int utf8_to_cp1251(char *input, char *output);
+extern int is_cp949(char *str);
+extern int cp949_to_utf8(char *input, char *output);
+extern int utf8_to_cp949(char *input, char *output);
 
 #endif
 

+ 16 - 8
src/trigger.c

@@ -48,7 +48,7 @@ DO_COMMAND(do_action)
 	{
 		if (*arg3 && (atof(arg3) < 1 || atof(arg3) >= 10))
 		{
-			show_error(ses, LIST_ACTION, "\e[1;31m#ERROR: #ACTION {%s} {..} {%s} SHOULD HAVE A PRIORITY BETWEEN 1.000 and 9.999.", arg1, arg3);
+			show_error(ses, LIST_ACTION, "\e[1;31m#WARNING: #ACTION {%s} {..} {%s} SHOULD HAVE A PRIORITY BETWEEN 1.000 and 9.999.", arg1, arg3);
 		}
 
 		update_node_list(ses->list[LIST_ACTION], arg1, arg2, arg3, "");
@@ -383,6 +383,7 @@ void check_all_buttons(struct session *ses, short row, short col, char *arg1, ch
 DO_COMMAND(do_delay)
 {
 	char time[NUMBER_SIZE];
+	long double number;
 
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
 	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
@@ -403,13 +404,16 @@ DO_COMMAND(do_delay)
 	{
 		if (*arg3 == 0)
 		{
-			sprintf(arg3, "%lld", utime() + (long long) (1000000 * get_number(ses, arg1)));
+			number = get_number(ses, arg1);
 
-			get_number_string(ses, arg1, time);
+			sprintf(arg3, "%lld", gtd->utime);
 
-			create_node_list(ses->list[LIST_DELAY], arg3, arg2, arg3, time);
+			sprintf(time, "%llu.%010llu", gtd->utime + (unsigned long long) (number * 1000000), (unsigned long long) (number * 10000000000) % 10000000000);
+
+			create_node_list(ses->list[LIST_DELAY], time, arg2, arg1, arg3);
+
+			show_message(ses, LIST_DELAY, "#OK, IN {%s} SECONDS {%s} IS EXECUTED.", arg1, arg2);
 
-			show_message(ses, LIST_DELAY, "#OK, IN {%s} SECONDS {%s} IS EXECUTED.", time, arg2);
 		}
 		else
 		{
@@ -417,7 +421,9 @@ DO_COMMAND(do_delay)
 
 			get_number_string(ses, arg3, time);
 
-			node = update_node_list(ses->list[LIST_TICKER], arg1, arg2, time, "");
+			sprintf(arg3, "%lld", gtd->utime);
+
+			node = update_node_list(ses->list[LIST_TICKER], arg1, arg2, time, arg3);
 
 			node->shots = 1;
 
@@ -977,7 +983,7 @@ DO_COMMAND(do_tick)
 	char time[NUMBER_SIZE];
 
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
-	arg = get_arg_in_braces(ses, arg, arg2, GET_ALL);
+	arg = get_arg_in_braces(ses, arg, arg2, GET_ONE);
 	arg = get_arg_in_braces(ses, arg, arg3, GET_ALL);
 
 	if (*arg3 == 0)
@@ -989,6 +995,8 @@ DO_COMMAND(do_tick)
 		get_number_string(ses, arg3, time);
 	}
 
+	sprintf(arg3, "%lld", ++gtd->utime);
+
 	if (*arg1 == 0)
 	{
 		show_list(ses->list[LIST_TICKER], 0);
@@ -1002,7 +1010,7 @@ DO_COMMAND(do_tick)
 	}
 	else
 	{
-		update_node_list(ses->list[LIST_TICKER], arg1, arg2, time, "");
+		update_node_list(ses->list[LIST_TICKER], arg1, arg2, time, arg3);
 
 		show_message(ses, LIST_TICKER, "#OK. #TICK {%s} NOW EXECUTES {%s} EVERY {%s} SECONDS.", arg1, arg2, time);
 	}

+ 4 - 4
src/update.c

@@ -858,7 +858,7 @@ void tick_update(void)
 
 	gtd->utime_next_tick = gtd->utime + 1000000000;
 
-	for (ses = gts ; ses ; ses = gtd->update)
+	for (ses = gts->next ; ses ; ses = gtd->update)
 	{
 		gtd->update = ses->next;
 
@@ -875,7 +875,7 @@ void tick_update(void)
 
 			if (node->val64 <= gtd->utime)
 			{
-				node->val64 = gtd->utime + (long long) (get_number(ses, node->arg3) * 1000000LL);
+				node->val64 += (long long) (get_number(ses, node->arg3) * 1000000LL);
 
 				show_info(ses, LIST_TICKER, "#INFO TICK {%s} INITIALIZED WITH TIMESTAMP {%lld}", node->arg1, node->val64);
 
@@ -933,7 +933,7 @@ void delay_update(void)
 			{
 				show_debug(ses, LIST_DELAY, "#DEBUG DELAY {%s}", node->arg2);
 
-				delete_node_list(ses, LIST_DELAY, node);
+				delete_index_list(root, root->update);
 
 				script_driver(ses, LIST_DELAY, node->arg2);
 			}
@@ -1134,7 +1134,7 @@ void time_update(void)
 		}
 		event_time = event_second;
 
-		while (!strcmp(event_table[event_time].name, "TIME"))
+		while (strcmp(event_table[++event_time].name, "TIME "))
 		{
 		}
 	}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 155 - 42
src/utf8.c


+ 2 - 6
src/utils.c

@@ -350,16 +350,12 @@ unsigned long long utime()
 
 	utime = now_time.tv_sec * 1000000ULL + now_time.tv_usec;
 
-	if (gtd->utime >= utime)
-	{
-		gtd->utime++;
-	}
-	else
+	if (gtd->utime < utime)
 	{
 		gtd->utime = utime;
 	}
 
-	return gtd->utime;
+	return gtd->utime++;
 }
 
 time_t get_time(struct session *ses, char *str)

+ 3 - 3
src/variable.c

@@ -1080,7 +1080,7 @@ int string_raw_str_len(struct session *ses, char *str, int raw_start, int raw_en
 		}
 
 		col_len = is_color_code(&str[raw_cnt]);
-		
+
 		if (col_len)
 		{
 			raw_cnt += col_len;
@@ -1104,7 +1104,7 @@ int string_raw_str_len(struct session *ses, char *str, int raw_start, int raw_en
 			continue;
 		}
 
-		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC)  && is_euc_head(ses, &str[raw_cnt]))
+		if (HAS_BIT(ses->charset, CHARSET_FLAG_EUC) && is_euc_head(ses, &str[raw_cnt]))
 		{
 			raw_cnt += get_euc_width(ses, &str[raw_cnt], &width);
 
@@ -1478,7 +1478,7 @@ void format_string(struct session *ses, char *format, char *arg, char *out)
 						break;
 
 					case 'U':
-						sprintf(arglist[i], "%lld", utime());
+						sprintf(arglist[i], "%lld", ++gtd->utime);
 						break;
 
 					case 'X':

+ 12 - 11
src/vt102.c

@@ -140,11 +140,11 @@ void scroll_region(struct session *ses, int top, int bot)
 	{
 		if (top != 1)
 		{
-			print_stdout(0, 0, "\e[?1047h\e[?7787h\e[%d;%dr", top, bot);
+			print_stdout(0, 0, "\e[?1049h\e[?7787h\e[%d;%dr", top, bot);
 		}
 		else
 		{
-			print_stdout(0, 0, "\e[?1047l\e[?7787l\e[%d;%dr", top, bot);
+			print_stdout(0, 0, "\e[?1049l\e[?7787l\e[%d;%dr", top, bot);
 		}
 	}
 	ses->split->top_row = top;
@@ -160,7 +160,7 @@ void reset_scroll_region(struct session *ses)
 {
 	if (ses == gtd->ses)
 	{
-		print_stdout(0, 0, "\e[?1047l\e[?7787l\e[r");
+		print_stdout(0, 0, "\e[?1049l\e[?7787l\e[r");
 	}
 	ses->split->top_row = 1;
 	ses->split->top_col = 1;
@@ -1301,7 +1301,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 								pop_call();
 								return len + 1;
 							}
-							break;
+							goto end;
 
 						case 'H':
 							if (check_all_events(ses, EVENT_FLAG_CATCH, 0, 2, "CATCH VT100 CURSOR H", ntos(val[0]), ntos(val[1])))
@@ -1309,7 +1309,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 								pop_call();
 								return len + 1;
 							}
-							break;
+							goto end;
 
 						case 'J':
 							if (val[0] == 0)
@@ -1344,7 +1344,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 									return len + 1;
 								}
 							}
-							break;
+							goto end;
 
 						case 'K':
 							if (val[0] == 0)
@@ -1371,7 +1371,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 									return len + 1;
 								}
 							}
-							break;
+							goto end;
 
 						case 'Z':
 							check_all_events(ses, EVENT_FLAG_VT100, 0, 0, "VT100 DECID");
@@ -1379,8 +1379,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 							return len + 1;
 
 						default:
-							pop_call();
-							return 0;
+							goto end;
 					}
 				}
 			}
@@ -1405,8 +1404,7 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 							return 11;
 						}
 					}
-					pop_call();
-					return 0;
+					goto end;
 				}
 				else
 				{
@@ -1458,6 +1456,9 @@ int catch_vt102_codes(struct session *ses, unsigned char *str, int cplen)
 			}
 			break;
 	}
+
+	end:
+
 	pop_call();
 	return 0;
 }

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels