Scandum 3 年之前
父节点
当前提交
2e1c3ab693
共有 41 个文件被更改,包括 2371 次插入1321 次删除
  1. 25 12
      TODO
  2. 194 182
      docs/help.html
  3. 32 26
      docs/tutorial.html
  4. 87 2
      mods/igr.mods
  5. 139 132
      src/banner.c
  6. 1 1
      src/buffer.c
  7. 57 5
      src/command.c
  8. 3 1
      src/config.c
  9. 11 13
      src/cursor.c
  10. 6 1
      src/daemon.c
  11. 51 6
      src/data.c
  12. 24 6
      src/draw.c
  13. 177 152
      src/gui.h
  14. 430 224
      src/help.c
  15. 30 19
      src/input.c
  16. 82 2
      src/line.c
  17. 86 3
      src/list.c
  18. 15 7
      src/main.c
  19. 425 208
      src/mapper.c
  20. 5 6
      src/math.c
  21. 6 0
      src/misc.c
  22. 4 3
      src/msdp.c
  23. 77 2
      src/nest.c
  24. 12 4
      src/net.c
  25. 17 4
      src/parse.c
  26. 106 129
      src/regex.c
  27. 19 17
      src/screen.c
  28. 12 3
      src/show.c
  29. 6 0
      src/split.c
  30. 4 0
      src/substitute.c
  31. 27 44
      src/tables.c
  32. 66 38
      src/telopt_client.c
  33. 13 4
      src/telopt_server.c
  34. 42 29
      src/terminal.c
  35. 2 1
      src/text.c
  36. 18 16
      src/tintin.h
  37. 22 3
      src/tokenize.c
  38. 22 4
      src/trigger.c
  39. 5 1
      src/update.c
  40. 4 10
      src/variable.c
  41. 7 1
      src/vt102.c

+ 25 - 12
TODO

@@ -1,16 +1,28 @@
-- make #draw talign+balign do a vertical calign
-             lalign+ralign do a horizontal calign
+- Handle more_output more cleanly in net.c
 
 
-- make -g mode not write to disk
+- return #regex #else to old format
 
 
-- look into #draw boxed map with unicode mode.
+- Look into #split 1 1 1 1 on termux when hiding / showing keyboard.
 
 
-- Display room symbol in #map info
-- Add nohup mode
+- Make WinTin++ 64 bit and double check windows console link opens main.tin
 
 
-ne room has #map set roomsymbol {<faa>/},
-e room has #map set roomsymbol {<faa>------}
-se room has #map set roomsymbol {<faa>\\}
+- look into invalid { } in MSDP / GMCP handling
+
+- mapper.c FAST handling
+
+- grid tables don't handle color codes
+
+- sandbox mode to disable shell integration.
+
+- color patch issues in #help
+
+- update telopt_server with MSSP, MTTS and TTYPE changes
+
+- look into #draw Yellow scroll bot side 1 1 1 80 drawing weird
+
+- check that vertical split screen update is fast using a trigger
+  with an instant screen update for reference. Some issues reported
+  related to packet patch.
 
 
 ----------------
 ----------------
   - add shadow session support with access to all events.
   - add shadow session support with access to all events.
@@ -33,7 +45,7 @@ se room has #map set roomsymbol {<faa>\\}
 
 
   - add ctrl-r support for scrollback
   - add ctrl-r support for scrollback
 
 
-  - Add #event {SESSION CONNECTED} {5.1} option.
+  - Add #event {SESSION CONNECTED} {#command} {5.1} option.
 
 
   - TT++ HANDBOOK for meticulous organized details.
   - TT++ HANDBOOK for meticulous organized details.
 
 
@@ -65,8 +77,6 @@ se room has #map set roomsymbol {<faa>\\}
 
 
   - look into transparent drawing
   - look into transparent drawing
 
 
-  - Add #line gag 2 +2 -2 support.
-
   - VT2020
   - VT2020
 
 
   - mouse enter/leave events on move. hoover/long-press.
   - mouse enter/leave events on move. hoover/long-press.
@@ -77,6 +87,9 @@ se room has #map set roomsymbol {<faa>\\}
 
 
   - tab completion on directory structure.
   - tab completion on directory structure.
 
 
+  - direction field for exits that allow longer than 1x1x1 x/y/z jumps.
+  - global mapper flag that would imply "Hide" on all exits that change area.
+  - multiple global exit rooms and noglobal flags.
   - auto align routine that inserts void rooms where needed
   - auto align routine that inserts void rooms where needed
   - look into writing script to drag rooms + void with mouse
   - look into writing script to drag rooms + void with mouse
   - pancake mode to display rooms at all levels and annotations
   - pancake mode to display rooms at all levels and annotations

文件差异内容过多而无法显示
+ 194 - 182
docs/help.html


+ 32 - 26
docs/tutorial.html

@@ -15,17 +15,23 @@ a:active {color:#b06}
 </head>
 </head>
 <pre>
 <pre>
 <span style='background-color:#000'><span style='color:#FFF'>
 <span style='background-color:#000'><span style='color:#FFF'>
-         <a href='#INDEX'>INDEX          </a> <a href='#EDITING'>EDITING        </a> <a href='#MAPPING'>MAPPING        </a> <a href='#MSLP'>MSLP           </a> <a href='#SPEEDWALK'>SPEEDWALK      </a>
-         <a href='#INTRODUCTION'>INTRODUCTION   </a> <a href='#ESCAPE CODES'>ESCAPE CODES   </a> <a href='#MATHEMATICS'>MATHEMATICS    </a> <a href='#PCRE'>PCRE           </a> <a href='#STATEMENTS'>STATEMENTS     </a>
-         <a href='#CHARACTERS'>CHARACTERS     </a> <a href='#GREETING'>GREETING       </a> <a href='#METRIC SYSTEM'>METRIC SYSTEM  </a> <a href='#REPEAT'>REPEAT         </a> <a href='#SUBSTITUTIONS'>SUBSTITUTIONS  </a>
-         <a href='#COLORS'>COLORS         </a> <a href='#KEYPAD'>KEYPAD         </a> <a href='#MOUSE'>MOUSE          </a> <a href='#SCREEN READER'>SCREEN READER  </a> <a href='#SUSPEND'>SUSPEND        </a>
-         <a href='#COORDINATES'>COORDINATES    </a> <a href='#LISTS'>LISTS          </a> <a href='#MSDP'>MSDP           </a> <a href='#SESSIONNAME'>SESSIONNAME    </a> <a href='#TIME'>TIME           </a>
+</span><span style='color:#FF5'>        ╭──────────────────────────────────────────────────────────────────────╮
+        │                                 <a href='index.html'>Home</a>                                 │
+        ╰──────────────────────────────────────────────────────────────────────╯
+
+         <a href='#INDEX'>INDEX           </a>  <a href='#GREETING'>GREETING        </a>  <a href='#MSDP'>MSDP            </a>  <a href='#STATEMENTS'>STATEMENTS      </a> 
+         <a href='#INTRODUCTION'>INTRODUCTION    </a>  <a href='#KEYPAD'>KEYPAD          </a>  <a href='#MSLP'>MSLP            </a>  <a href='#SUBSTITUTIONS'>SUBSTITUTIONS   </a> 
+         <a href='#CHARACTERS'>CHARACTERS      </a>  <a href='#LISTS'>LISTS           </a>  <a href='#PCRE'>PCRE            </a>  <a href='#SUSPEND'>SUSPEND         </a> 
+         <a href='#COLORS'>COLORS          </a>  <a href='#MAPPING'>MAPPING         </a>  <a href='#REPEAT'>REPEAT          </a>  <a href='#TIME'>TIME            </a> 
+         <a href='#COORDINATES'>COORDINATES     </a>  <a href='#MATHEMATICS'>MATHEMATICS     </a>  <a href='#SCREEN_READER'>SCREEN READER   </a> 
+         <a href='#EDITING'>EDITING         </a>  <a href='#METRIC_SYSTEM'>METRIC SYSTEM   </a>  <a href='#SESSIONNAME'>SESSIONNAME     </a> 
+         <a href='#ESCAPE_CODES'>ESCAPE CODES    </a>  <a href='#MOUSE'>MOUSE           </a>  <a href='#SPEEDWALK'>SPEEDWALK       </a> 
         
         
 
 
 
 
 <a name='INDEX'></a>
 <a name='INDEX'></a>
 
 
-</span><span style='color:#FF5'>         INDEX
+         INDEX
 
 
 </span><span style='color:#08F'>                   ████████┐██████┐███┐   ██┐████████┐██████┐███┐   ██┐
 </span><span style='color:#08F'>                   ████████┐██████┐███┐   ██┐████████┐██████┐███┐   ██┐
                    └──██┌──┘└─██┌─┘████┐  ██│└──██┌──┘└─██┌─┘████┐  ██│
                    └──██┌──┘└─██┌─┘████┐  ██│└──██┌──┘└─██┌─┘████┐  ██│
@@ -59,7 +65,7 @@ a:active {color:#b06}
          If you're new to TinTin++ a good place to start is the introduction,
          If you're new to TinTin++ a good place to start is the introduction,
          which should be linked below.
          which should be linked below.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#INTRODUCTION'>introduction</a>
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#INTRODUCTION'>introduction</a>
 <a name='INTRODUCTION'></a>
 <a name='INTRODUCTION'></a>
 
 
 </span><span style='color:#FF5'>         INTRODUCTION
 </span><span style='color:#FF5'>         INTRODUCTION
@@ -330,7 +336,7 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
 </span><span style='color:#5F5'>
 </span><span style='color:#5F5'>
          That's all for the introduction, enjoy</span><span style='color:#AAA'>
          That's all for the introduction, enjoy</span><span style='color:#AAA'>
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#CHARACTERS'>characters</a>, <a href='help.html#COLORS'>colors</a>, <a href='help.html#COORDINATES'>coordinates</a>, <a href='help.html#EDITING'>editing</a>, <a href='help.html#ESCAPE_CODES'>escape_codes</a>, <a href='help.html#GREETING'>greeting</a>, <a href='help.html#KEYPAD'>keypad</a>, <a href='help.html#LISTS'>lists</a>, <a href='help.html#MAPPING'>mapping</a>, <a href='help.html#MATHEMATICS'>mathematics</a>, <a href='help.html#SCREEN_READER'>screen_reader</a>, <a href='help.html#SESSIONNAME'>sessionname</a>, <a href='help.html#SPEEDWALK'>speedwalk</a>, <a href='help.html#STATEMENTS'>statements</a>, <a href='help.html#SUSPEND'>suspend</a> and <a href='help.html#TIME'>time</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CHARACTERS'>characters</a>, <a href='#COLORS'>colors</a>, <a href='#COORDINATES'>coordinates</a>, <a href='#EDITING'>editing</a>, <a href='#ESCAPE_CODES'>escape_codes</a>, <a href='#GREETING'>greeting</a>, <a href='#KEYPAD'>keypad</a>, <a href='#LISTS'>lists</a>, <a href='#MAPPING'>mapping</a>, <a href='#MATHEMATICS'>mathematics</a>, <a href='#SCREEN_READER'>screen_reader</a>, <a href='#SESSIONNAME'>sessionname</a>, <a href='#SPEEDWALK'>speedwalk</a>, <a href='#STATEMENTS'>statements</a>, <a href='#SUSPEND'>suspend</a> and <a href='#TIME'>time</a>.
 <a name='CHARACTERS'></a>
 <a name='CHARACTERS'></a>
 
 
 </span><span style='color:#FF5'>         CHARACTERS
 </span><span style='color:#FF5'>         CHARACTERS
@@ -366,7 +372,7 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
          #config, and is itself sent verbatim when the verbatim config mode
          #config, and is itself sent verbatim when the verbatim config mode
          is enabled.
          is enabled.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#COLORS'>colors</a>, <a href='help.html#ESCAPE'>escape</a>, <a href='help.html#FUNCTION'>function</a>, <a href='help.html#MATHEMATICS'>mathematics</a>, <a href='help.html#PCRE'>pcre</a> and <a href='help.html#VARIABLE'>variable</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#COLORS'>colors</a>, <a href='#ESCAPE_CODES'>escape_codes</a>, <a href='help.html#FUNCTION'>function</a>, <a href='#MATHEMATICS'>mathematics</a>, <a href='#PCRE'>pcre</a> and <a href='help.html#VARIABLE'>variable</a>.
 <a name='COLORS'></a>
 <a name='COLORS'></a>
 
 
 </span><span style='color:#FF5'>         COLORS
 </span><span style='color:#FF5'>         COLORS
@@ -416,7 +422,7 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
          If the color code exceeds your configured color mode it will be
          If the color code exceeds your configured color mode it will be
          downgraded to the closest match.
          downgraded to the closest match.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#CHARACTERS'>characters</a>, <a href='help.html#COORDINATES'>coordinates</a>, <a href='help.html#ESCAPE'>escape</a>, <a href='help.html#MATHEMATICS'>mathematics</a> and <a href='help.html#PCRE'>pcre</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CHARACTERS'>characters</a>, <a href='#COORDINATES'>coordinates</a>, <a href='#ESCAPE_CODES'>escape_codes</a>, <a href='#MATHEMATICS'>mathematics</a> and <a href='#PCRE'>pcre</a>.
 <a name='COORDINATES'></a>
 <a name='COORDINATES'></a>
 
 
 </span><span style='color:#FF5'>         COORDINATES
 </span><span style='color:#FF5'>         COORDINATES
@@ -459,7 +465,7 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
          index is defined as -1. This type of argument is used by #buffer
          index is defined as -1. This type of argument is used by #buffer
          and #variable.
          and #variable.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#CHARACTERS'>characters</a>, <a href='help.html#COLORS'>colors</a>, <a href='help.html#ESCAPE'>escape</a>, <a href='help.html#MATHEMATICS'>mathematics</a> and <a href='help.html#PCRE'>pcre</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CHARACTERS'>characters</a>, <a href='#COLORS'>colors</a>, <a href='#ESCAPE_CODES'>escape_codes</a>, <a href='#MATHEMATICS'>mathematics</a> and <a href='#PCRE'>pcre</a>.
 <a name='EDITING'></a>
 <a name='EDITING'></a>
 
 
 </span><span style='color:#FF5'>         EDITING
 </span><span style='color:#FF5'>         EDITING
@@ -576,7 +582,7 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
 </span><span style='color:#0AA'>└─────────────────────────┘└────────────────────────────────────────────┘</span><span style='color:#AAA'>
 </span><span style='color:#0AA'>└─────────────────────────┘└────────────────────────────────────────────┘</span><span style='color:#AAA'>
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#CURSOR'>cursor</a>, <a href='help.html#EDIT'>edit</a> and <a href='help.html#MACRO'>macro</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#CURSOR'>cursor</a>, <a href='help.html#EDIT'>edit</a> and <a href='help.html#MACRO'>macro</a>.
-<a name='ESCAPE CODES'></a>
+<a name='ESCAPE_CODES'></a>
 
 
 </span><span style='color:#FF5'>         ESCAPE CODES
 </span><span style='color:#FF5'>         ESCAPE CODES
 
 
@@ -600,14 +606,14 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
          Ending a line with &bsol; will stop tintin from appending a line feed.
          Ending a line with &bsol; will stop tintin from appending a line feed.
          To escape arguments in an alias or action use %%0 %%1 %%2 etc.
          To escape arguments in an alias or action use %%0 %%1 %%2 etc.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#CHARACTERS'>characters</a>, <a href='help.html#COLORS'>colors</a>, <a href='help.html#COORDINATES'>coordinates</a>, <a href='help.html#MATHEMATICS'>mathematics</a> and <a href='help.html#PCRE'>pcre</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CHARACTERS'>characters</a>, <a href='#COLORS'>colors</a>, <a href='#COORDINATES'>coordinates</a>, <a href='#MATHEMATICS'>mathematics</a> and <a href='#PCRE'>pcre</a>.
 <a name='GREETING'></a>
 <a name='GREETING'></a>
 
 
 </span><span style='color:#FF5'>         GREETING
 </span><span style='color:#FF5'>         GREETING
 
 
 </span><span style='color:#0AA'>      ####################################################################
 </span><span style='color:#0AA'>      ####################################################################
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
-      #</span><span style='color:#AAA'>                    T I N T I N + +   2.02.21b                    </span><span style='color:#0AA'>#
+      #</span><span style='color:#AAA'>                    T I N T I N + +   2.02.30                     </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>      Code by Peter Unold, Bill Reis, and Igor van den Hoven      </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>      Code by Peter Unold, Bill Reis, and Igor van den Hoven      </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
       #</span><span style='color:#AAA'>                                                                  </span><span style='color:#0AA'>#
@@ -655,7 +661,7 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
          Mac OS X Terminal requires enabling 'strict vt100 keypad behavior' in
          Mac OS X Terminal requires enabling 'strict vt100 keypad behavior' in
          Terminal -&gt; Window Settings -&gt; Emulation.
          Terminal -&gt; Window Settings -&gt; Emulation.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#COLORS'>colors</a>, <a href='help.html#COORDINATES'>coordinates</a>, <a href='help.html#ESCAPE'>escape</a>, <a href='help.html#MATHEMATICS'>mathematics</a> and <a href='help.html#PCRE'>pcre</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#COLORS'>colors</a>, <a href='#COORDINATES'>coordinates</a>, <a href='#ESCAPE_CODES'>escape_codes</a>, <a href='#MATHEMATICS'>mathematics</a> and <a href='#PCRE'>pcre</a>.
 <a name='LISTS'></a>
 <a name='LISTS'></a>
 
 
 </span><span style='color:#FF5'>         LISTS
 </span><span style='color:#FF5'>         LISTS
@@ -981,7 +987,7 @@ Command</span><span style='color:#AAA'>: #alias </span><span style='color:#FFF'>
              }
              }
         }
         }
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#BREAK'>break</a>, <a href='help.html#CONTINUE'>continue</a>, <a href='help.html#FOREACH'>foreach</a>, <a href='help.html#LOOP'>loop</a>, <a href='help.html#PARSE'>parse</a>, <a href='help.html#REPEAT'>repeat</a>, <a href='help.html#RETURN'>return</a> and <a href='help.html#WHILE'>while</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#BREAK'>break</a>, <a href='help.html#CONTINUE'>continue</a>, <a href='help.html#FOREACH'>foreach</a>, <a href='help.html#LOOP'>loop</a>, <a href='help.html#PARSE'>parse</a>, <a href='#REPEAT'>repeat</a>, <a href='help.html#RETURN'>return</a> and <a href='help.html#WHILE'>while</a>.
 <a name='MAPPING'></a>
 <a name='MAPPING'></a>
 
 
 </span><span style='color:#FF5'>         MAPPING
 </span><span style='color:#FF5'>         MAPPING
@@ -1161,7 +1167,7 @@ expressions, with the argument on the left being the string, and the argument
 on the right being the regex. For example {bla} == {%*a} would evaluate as 1.
 on the right being the regex. For example {bla} == {%*a} would evaluate as 1.
 
 
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#MATH'>math</a> and <a href='help.html#REGEXP'>regexp</a>.
 </span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#MATH'>math</a> and <a href='help.html#REGEXP'>regexp</a>.
-<a name='METRIC SYSTEM'></a>
+<a name='METRIC_SYSTEM'></a>
 
 
 </span><span style='color:#FF5'>         METRIC SYSTEM
 </span><span style='color:#FF5'>         METRIC SYSTEM
 
 
@@ -1196,7 +1202,7 @@ on the right being the regex. For example {bla} == {%*a} would evaluate as 1.
          specific events when clicked.
          specific events when clicked.
 
 
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#BUTTON'>button</a>, <a href='help.html#DRAW'>draw</a>, <a href='help.html#EVENT'>event</a> and <a href='help.html#MSLP'>MSLP</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#BUTTON'>button</a>, <a href='help.html#DRAW'>draw</a>, <a href='help.html#EVENT'>event</a> and <a href='#MSLP'>MSLP</a>.
 <a name='MSDP'></a>
 <a name='MSDP'></a>
 
 
 </span><span style='color:#FF5'>         MSDP
 </span><span style='color:#FF5'>         MSDP
@@ -1474,8 +1480,8 @@ easiest way to accomplish that.
 
 
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #10 {buy bread}
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #10 {buy bread}
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#MATHEMATICS'>mathematics</a> and <a href='help.html#STATEMENTS'>statements</a>.
-<a name='SCREEN READER'></a>
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#MATHEMATICS'>mathematics</a> and <a href='#STATEMENTS'>statements</a>.
+<a name='SCREEN_READER'></a>
 
 
 </span><span style='color:#FF5'>         SCREEN READER
 </span><span style='color:#FF5'>         SCREEN READER
 
 
@@ -1527,7 +1533,7 @@ easiest way to accomplish that.
          #showme {@two{&dollar;test}} in session one would print the value of &dollar;test,
          #showme {@two{&dollar;test}} in session one would print the value of &dollar;test,
          as defined by session two.
          as defined by session two.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#SUSPEND'>suspend</a>
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#SUSPEND'>suspend</a>
 <a name='SPEEDWALK'></a>
 <a name='SPEEDWALK'></a>
 
 
 </span><span style='color:#FF5'>         SPEEDWALK
 </span><span style='color:#FF5'>         SPEEDWALK
@@ -1562,7 +1568,7 @@ easiest way to accomplish that.
 </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'>: #path unzip 3n1e2nw
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #map move 3ne1d
 </span><span style='color:#FFF'>Example</span><span style='color:#AAA'>: #map move 3ne1d
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#KEYPAD'>keypad</a>, <a href='help.html#MAPPING'>mapping</a> and <a href='help.html#REPEAT'>repeat</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#KEYPAD'>keypad</a>, <a href='#MAPPING'>mapping</a> and <a href='#REPEAT'>repeat</a>.
 <a name='STATEMENTS'></a>
 <a name='STATEMENTS'></a>
 
 
 </span><span style='color:#FF5'>         STATEMENTS
 </span><span style='color:#FF5'>         STATEMENTS
@@ -1584,7 +1590,7 @@ easiest way to accomplish that.
          #switch {expression} {commands}
          #switch {expression} {commands}
          #while {expression} {commands}
          #while {expression} {commands}
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#MATHEMATICS'>mathematics</a>, <a href='help.html#PCRE'>pcre</a> and <a href='help.html#REPEAT'>repeat</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#MATHEMATICS'>mathematics</a>, <a href='#PCRE'>pcre</a> and <a href='#REPEAT'>repeat</a>.
 <a name='SUBSTITUTIONS'></a>
 <a name='SUBSTITUTIONS'></a>
 
 
 </span><span style='color:#FF5'>         SUBSTITUTIONS
 </span><span style='color:#FF5'>         SUBSTITUTIONS
@@ -1656,7 +1662,7 @@ easiest way to accomplish that.
           displayed on the screen, or being processed as part of a regex.
           displayed on the screen, or being processed as part of a regex.
           Escapes try to mimic escapes in PCRE when possible.
           Escapes try to mimic escapes in PCRE when possible.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#CHARACTERS'>characters</a>, <a href='help.html#COLORS'>colors</a>, <a href='help.html#ESCAPES'>escapes</a> and <a href='help.html#PCRE'>pcre</a>.
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#CHARACTERS'>characters</a>, <a href='#COLORS'>colors</a>, <a href='#ESCAPE_CODES'>escape_codes</a> and <a href='#PCRE'>pcre</a>.
 <a name='SUSPEND'></a>
 <a name='SUSPEND'></a>
 
 
 </span><span style='color:#FF5'>         SUSPEND
 </span><span style='color:#FF5'>         SUSPEND
@@ -1669,7 +1675,7 @@ easiest way to accomplish that.
          While suspended your tintin sessions will freeze. To keep a
          While suspended your tintin sessions will freeze. To keep a
          suspended session running use the #daemon command.
          suspended session running use the #daemon command.
 
 
-</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='help.html#SESSIONNAME'>sessionname</a>
+</span><span style='color:#FFF'>Related</span><span style='color:#AAA'>: <a href='#SESSIONNAME'>sessionname</a>
 <a name='TIME'></a>
 <a name='TIME'></a>
 
 
 </span><span style='color:#FF5'>         TIME
 </span><span style='color:#FF5'>         TIME
@@ -1685,7 +1691,7 @@ easiest way to accomplish that.
          The current epoch time value is obtained using #format {time} {%T}.
          The current epoch time value is obtained using #format {time} {%T}.
 
 
          When using %t the argument should contain strftime format specifiers.
          When using %t the argument should contain strftime format specifiers.
-         The output may differ depending on your locale. See man strftime.
+         Below are some common specifiers, see man strftime for the full list.
 
 
          %a  Abbreviated name of the day of the week (mon ... sun).
          %a  Abbreviated name of the day of the week (mon ... sun).
          %A  Full name of the day of the week. (Monday ... Sunday)
          %A  Full name of the day of the week. (Monday ... Sunday)

+ 87 - 2
mods/igr.mods

@@ -1,3 +1,88 @@
+Jul 2022        2.02.30
+------------------------------------------------------------------------------
+help.c          #help and #command when used with no argument display the
+                entries as columns instead of rows.
+
+../docs/        I got started on a tintin generated github website.
+
+                https://scandum.github.io/tintin
+
+mapper.c        Using #map exit <exit> dir 0, will now properly save.
+
+screen.c        #screen set rows/cols will now properly initialize the new
+                rows/cols setting for the screen dimensions. This will be
+                global for all sessions. The values are reset when resizing
+                the terminal.
+
+telopt_client.c Updated the TTYPE MNES negotiation to report a standardized
+                charset value.
+
+telopt_client.c Updated the TTYPE MTTS negotiation to report SSL support if
+                GnuTLS is included in the compilation.
+
+telopt_client.c Updated the TTYPE MTTS negotiation to report MSLP and mouse
+                support if #config mouse is set to on.
+
+draw.c          #draw SCALED will not scale horizontally when combined with
+                the VERTICAL flag.
+
+gui.h           Updated the connection manager (tt++ -g) with new sponsors and
+                some bug fixes.
+
+trigger.c       #prompt with a row argument of 0 will behave like #substitute.
+
+input.c         Fixed memory access violation identified by dzp.
+
+line.c          Updated #line gag to support #line gag [amount], you can use
+                + or - to increase or decrease the current amount.
+
+mapper.c        Added {both} option to #map exit and entrance where
+                applicable.
+
+list.c          Added #list {var} refine {keep} {remove}. Keep and remove must
+                be a mathematical expression, the keep argument is ignored if
+                {} is used, the remove expression is optional. #list indexate
+                must be used to refine tables. In the expression &0 must be
+                used as the placeholder of the item value being compared.
+
+draw.c          If you #draw with both the talign and balign flags set the
+                text will be centered vertically.
+
+mapper.c        Added #map flag symbolgraphics support to #map flag mudfont
+
+line.c          Added #line json <variable> <command> with &0 containing the
+                variable's value translated to json.
+
+telopt_client.c IAC SB GMCP <MODULE>   %0 data      %1 plain data
+                has been changed to
+                IAC SB GMCP <MODULE>   %0 data      %1 data  %2 plain data
+
+trigger.c       Fixed a bug with using #highlight {[}
+
+list.c          Added #list <list> numerate to renumber a list or table.
+
+list.c          Proper lists will be renumbered after using #list filter.
+
+net.c           Added a GAG NO SESSION ACTIVE event to block the NO SESSION
+                ACTIVE message. %0 holds the command.
+
+regex.c         Added %c for regular expressions which captures color codes.
+
+mapper.c        Added #map flag fast which will limit coordinate searches to
+                a 50 room radius. Improves the speed of map drawing and auto
+                linking on large maps. This can result in the mapper failing
+                to auto link if the path connecting two rooms exceeds the
+                search radius.
+
+split.c         Moving the cursor back to the scroll region if #split is used
+                in an #action.
+
+parse.c         No longer echoing hashbangs/shebangs unless tt++ -v is used.
+
+tables.c        Fixed two errors in the ascii table, patch by dzp.
+
+net.c           Added tcp keepalive at the socket level, patch by beinvisible.
+
 Sep 2021        2.02.20
 Sep 2021        2.02.20
 ------------------------------------------------------------------------------
 ------------------------------------------------------------------------------
 main.c          Added -H startup option to run tintin in a nohup compatible
 main.c          Added -H startup option to run tintin in a nohup compatible
@@ -898,7 +983,7 @@ path.c          #path run no longer uses delays but uses its own timer system,
                 #path run again you'll continue where you stopped.
                 #path run again you'll continue where you stopped.
 
 
 trigger.c       Named delays are now automatically converted to one shot
 trigger.c       Named delays are now automatically converted to one shot
-                triggers. #undelay will use #untick if the argument begins
+                tickers. #undelay will use #untick if the argument begins
                 with a letter.
                 with a letter.
 
 
 mapper.c        Changed #map destroy to #map destroy {area|world} {arg}
 mapper.c        Changed #map destroy to #map destroy {area|world} {arg}
@@ -4172,7 +4257,7 @@ tick.c         wrote a new ticker from scratch, uses alarm(1) to sleep 1
                the 'tick' and 'untick' command for manipulation.
                the 'tick' and 'untick' command for manipulation.
 
 
 macro.c        added 'macro' and 'unmacro' commands for keybinding, I couldn't
 macro.c        added 'macro' and 'unmacro' commands for keybinding, I couldn't
-               figure out how to actually undo the real macro's though
+               figure out how to actually undo the real macros though
                without using a messy hack, so I just skipped that till later
                without using a messy hack, so I just skipped that till later
                for now.
                for now.
 
 

+ 139 - 132
src/banner.c

@@ -27,6 +27,8 @@
 
 
 #include "gui.h"
 #include "gui.h"
 
 
+#define BANNER_FLAG_DUPLICATE BV01
+
 void banner_create(struct session *ses, char *name, char *arg)
 void banner_create(struct session *ses, char *name, char *arg)
 {
 {
 	update_node_list(gtd->banner_list, name, "", "", "");
 	update_node_list(gtd->banner_list, name, "", "", "");
@@ -47,6 +49,16 @@ void banner_desc(struct session *ses, char *name, char *arg, char *arg1)
 	}
 	}
 }
 }
 
 
+void banner_flag(struct session *ses, char *name, unsigned int flag)
+{
+	struct listnode *node = search_node_list(gtd->banner_list, name);
+
+	if (node)
+	{
+		node->shots = flag;
+	}
+}
+
 void banner_website(struct session *ses, char *name, char *arg, char *arg1)
 void banner_website(struct session *ses, char *name, char *arg, char *arg1)
 {
 {
 	struct listnode *node;
 	struct listnode *node;
@@ -85,7 +97,7 @@ void banner_expires(struct session *ses, char *name, char *arg, char *arg1)
 
 
 	if (node)
 	if (node)
 	{
 	{
-		node->val64 = UMAX(0, (atoi(arg1) - 1970) * 31556926);
+		node->val64 = UMAX(0, (atoi(arg1) - 1969) * 31556926);
 	}
 	}
 }
 }
 
 
@@ -104,10 +116,28 @@ void banner_init(struct session *ses, char *arg1)
 		"\n"
 		"\n"
 		"  -- Yahoo! Wild Web Rides", arg1);
 		"  -- Yahoo! Wild Web Rides", arg1);
 
 
-	banner_website(ses, "Lost Souls", "http://lostsouls.org", arg1);
+	banner_website(ses, "Lost Souls", "https://lostsouls.org", arg1);
 	banner_address(ses, "Lost Souls", "ls lostsouls.org 23", arg1);
 	banner_address(ses, "Lost Souls", "ls lostsouls.org 23", arg1);
-	banner_expires(ses, "Lost Souls", "2027", arg1);
+	banner_expires(ses, "Lost Souls", "2028", arg1);
+
+
+	banner_create(ses, "Kallisti MUD", arg1);
+
+	banner_desc(ses, "Kallisti MUD",
+		"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, "Kallisti MUD", "https://www.KallistiMUD.com", arg1);
+	banner_address(ses, "Kallisti MUD", "LoK kallistimud.com 4000", arg1);
+	banner_expires(ses, "Kallisti MUD", "2028", arg1);
+	banner_flag(ses, "Kallisti MUD", BANNER_FLAG_DUPLICATE);
 
 
 	banner_create(ses, "Legends of Kallisti", arg1);
 	banner_create(ses, "Legends of Kallisti", arg1);
 
 
@@ -122,9 +152,9 @@ void banner_init(struct session *ses, char *arg1)
 		"This is an amazing game that you could literally play for a decade and still\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);
 		"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", "2027", arg1);
+	banner_website(ses, "Legends of Kallisti", "https://legendsofkallisti.com", arg1);
+	banner_address(ses, "Legends of Kallisti", "LoK legendsofkallisti.com 4000", arg1);
+	banner_expires(ses, "Legends of Kallisti", "2028", arg1);
 
 
 
 
 	banner_create(ses, "3Kingdoms", arg1);
 	banner_create(ses, "3Kingdoms", arg1);
@@ -142,7 +172,8 @@ void banner_init(struct session *ses, char *arg1)
 
 
 	banner_website(ses, "3Kingdoms", "http://3k.org", arg1);
 	banner_website(ses, "3Kingdoms", "http://3k.org", arg1);
 	banner_address(ses, "3Kingdoms", "3K 3k.org 3000", arg1);
 	banner_address(ses, "3Kingdoms", "3K 3k.org 3000", arg1);
-	banner_expires(ses, "3Kingdoms", "2027", arg1);
+	banner_expires(ses, "3Kingdoms", "2028", arg1);
+
 
 
 	banner_create(ses, "RetroMUD", arg1);
 	banner_create(ses, "RetroMUD", arg1);
 
 
@@ -153,24 +184,8 @@ void banner_init(struct session *ses, char *arg1)
 
 
 	banner_website(ses, "RetroMUD", "http://www.retromud.org", arg1);
 	banner_website(ses, "RetroMUD", "http://www.retromud.org", arg1);
 	banner_address(ses, "RetroMUD", "rm 96.126.116.118 3000", arg1);
 	banner_address(ses, "RetroMUD", "rm 96.126.116.118 3000", arg1);
-	banner_expires(ses, "RetroMUD", "2027", arg1);
-
-/*
-	banner_create(ses, "New World Ateraan", arg1);
-
-	banner_desc(ses, "New World Ateraan",
-		"Ateraan is a world of Intensive Roleplaying offering many unique and powerful\n"
-		"guilds, races, politics, religion, justice, economy, and a storyline that is\n"
-		"dominantly player controlled and based on a novel. The game is based on a\n"
-		"Kingdom with knights, merchants, mages, and thieves, and a fierce southern\n"
-		"state that has warriors, shaman, slaves, and servants. Ships rule the seas and\n"
-		"caravans travel the lands. With 100's of players and features like invasions,\n"
-		"ship creation, house building, clans, theaters, leatherball fields, and massive\n"
-		"events, the game is incredibly robust and diverse.", arg1);
+	banner_expires(ses, "RetroMUD", "2032", 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", "2026", arg1);
 
 
 	banner_create(ses, "Realm of Utopian Dreams (RUD)", arg1);
 	banner_create(ses, "Realm of Utopian Dreams (RUD)", arg1);
 
 
@@ -186,8 +201,74 @@ void banner_init(struct session *ses, char *arg1)
 
 
 	banner_website(ses, "Realm of Utopian Dreams (RUD)", "http://rudmud.com", 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_address(ses, "Realm of Utopian Dreams (RUD)", "rud rudmud.com 1701", arg1);
-	banner_expires(ses, "Realm of Utopian Dreams (RUD)", "2026", arg1);
+	banner_expires(ses, "Realm of Utopian Dreams (RUD)", "2028", arg1);
 
 
+
+	banner_create(ses, "Alter Aeon", arg1);
+
+	banner_desc(ses, "Alter Aeon",
+		"Alter Aeon is a custom multiclass MUD, where each of the character\n"
+		"classes can be combined to make very unique characters.  This huge\n"
+		"fantasy themed game has hundreds of areas and quests, spanning\n"
+		"several continents and outer planar regions.  There are custom spells,\n"
+		"skills, minions, player run shops, boats, PvP, and many other features\n"
+		"for nearly every kind of player.  The game is very friendly to new players\n"
+		"and has extensive support for the blind and visually impaired.", arg1);
+
+	banner_website(ses, "Alter Aeon", "https://www.alteraeon.com", arg1);
+	banner_address(ses, "Alter Aeon", "aa alteraeon.com 3000", arg1);
+	banner_expires(ses, "Alter Aeon", "2028", arg1);
+
+
+	banner_create(ses, "Threshold RPG", arg1);
+
+	banner_desc(ses, "Threshold RPG",
+		"Join us at Threshold RPG, one of the oldest RP enforced games on the\n"
+		"internet. Add to twenty-six years of player created history and make your\n"
+		"own mark on the world today. Join a hundred other players who are vying for\n"
+		"political and religious power in complex systems that reward skill, effort,\n"
+		"and social interactions. Threshold RPG is a custom code-base written in\n"
+		"LPC and features a completely unique and original world.", arg1);
+
+	banner_website(ses, "Threshold RPG", "https://www.thresholdrpg.com", arg1);
+	banner_address(ses, "Threshold RPG", "thresh thresholdrpg.com 3333", arg1);
+	banner_expires(ses, "Threshold RPG", "2028", arg1);
+
+
+	banner_create(ses, "Primal Darkness", arg1);
+	
+	banner_desc(ses, "Primal Darkness",
+		"Primal Darkness boasts twenty three start races, three quest races, five start\n"
+		"classes and twenty one subclasses to suit your adventuring needs, and a custom\n"
+		"remort system allowing you to save all your hard work while trying out new\n"
+		"races and/or classes. The world has zoned player killing (pk) supported by a\n"
+		"justice system, player built and ran guilds, a fully sail-able ocean with\n"
+		"customizable ships and ship battle system, a fully flyable sky with mapping\n"
+		"system, mud-wide auction line, a colosseum in which to prove your battle\n"
+		"prowess (harmless/free pk), and 30+ areas on multiple continents to explore.", arg1);
+
+	banner_website(ses, "Primal Darkness", "https://www.primaldarkness.com", arg1);
+	banner_address(ses, "Primal Darkness", "pd mud.primaldarkness.com 5000", arg1);
+	banner_expires(ses, "Primal Darkness", "2028", arg1);
+
+
+	banner_create(ses, "New Worlds Ateraan", arg1);
+
+	banner_desc(ses, "New Worlds Ateraan",
+		"Ateraan is a world of Intensive Roleplaying offering many unique and powerful\n"
+		"guilds, races, politics, religion, justice, economy, and a storyline that is\n"
+		"dominantly player controlled and based on a novel. The game is based on a\n"
+		"Kingdom with knights, merchants, mages, and thieves, and a fierce southern\n"
+		"state that has warriors, shaman, slaves, and servants. Ships rule the seas and\n"
+		"caravans travel the lands. With 100's of players and features like invasions,\n"
+		"ship creation, house building, clans, theaters, leatherball fields, and massive\n"
+		"events, the game is incredibly robust and diverse.", arg1);
+
+	banner_website(ses, "New Worlds Ateraan", "http://www.ateraan.com", arg1);
+	banner_address(ses, "New Worlds Ateraan", "nwa ateraan.com 4002", arg1);
+	banner_expires(ses, "New Worlds Ateraan", "2028", arg1);
+
+/*
 	banner_create(ses, "Carrion Fields", arg1);
 	banner_create(ses, "Carrion Fields", arg1);
 
 
 	banner_desc(ses, "Carrion Fields",
 	banner_desc(ses, "Carrion Fields",
@@ -322,6 +403,10 @@ void banner_save(struct session *ses, char *arg1)
 	{
 	{
 		node = gtd->banner_list->list[index];
 		node = gtd->banner_list->list[index];
 
 
+		if (HAS_BIT(node->shots, BANNER_FLAG_DUPLICATE))
+		{
+			continue;
+		}
 		sprintf(name, "info[BANNERS][%s]", node->arg1);
 		sprintf(name, "info[BANNERS][%s]", node->arg1);
 
 
 		arg1 = node->arg4;
 		arg1 = node->arg4;
@@ -379,6 +464,30 @@ void banner_test(struct session *ses, char *arg1)
 
 
 struct session *banner_gui(struct session *ses, char *arg1)
 struct session *banner_gui(struct session *ses, char *arg1)
 {
 {
+	char *data;
+	FILE *fp;
+	size_t len;
+
+	fp = open_memstream(&data, (size_t *) &len);
+
+	fputs(tt_gui, fp);
+
+	fclose(fp);
+
+	fp = fmemopen(data, len, "r");
+
+	gtd->level->quiet++;
+
+	ses = read_file(ses, fp, "tt_gui.h");
+
+	gtd->level->quiet--;
+
+	fclose(fp);
+
+	free(data);
+
+	return ses;
+/*
 	char filename[PATH_SIZE];
 	char filename[PATH_SIZE];
 	FILE *fp;
 	FILE *fp;
 
 
@@ -396,6 +505,7 @@ struct session *banner_gui(struct session *ses, char *arg1)
 	fclose(fp);
 	fclose(fp);
 
 
 	return command(ses, do_line, "quiet #read %s", filename);
 	return command(ses, do_line, "quiet #read %s", filename);
+*/
 }
 }
 
 
 DO_COMMAND(do_banner)
 DO_COMMAND(do_banner)
@@ -426,10 +536,13 @@ DO_COMMAND(do_banner)
 	{
 	{
 		banner_save(ses, arg1);
 		banner_save(ses, arg1);
 	}
 	}
+	else if (is_abbrev(arg1, "HELP"))
+	{
+		tintin_printf2(ses, "#SYNTAX: #BANNER {GUI|INIT|LIST|RANDOM|SAVE|TEST}");
+	}	
 	else
 	else
 	{
 	{
 		banner_list(ses, arg1);
 		banner_list(ses, arg1);
-//		tintin_printf2(ses, "#SYNTAX: #BANNER {INIT|LIST|RANDOM|TEST}");
 	}
 	}
 	return ses;
 	return ses;
 }
 }
@@ -437,36 +550,6 @@ DO_COMMAND(do_banner)
 // archive
 // archive
 
 
 /*
 /*
-	{
-		1400000000,  // 2014
-		1800000000,  // 2027
-		100,
-
-		"\n"
-		"<138>                 Primal Darkness  -  http://www.primaldarkness.com\n"
-		"\n"
-		"<078>Primal Darkness boasts twenty three start races, three quest races, five start\n"
-		"<078>classes and twenty one subclasses to suit your adventuring needs, and a custom\n"
-		"<078>remort system allowing you to save all your hard work while trying out new\n"
-		"<078>races and/or classes. The world has zoned player killing (pk) supported by a\n"
-		"<078>justice system, player built and ran guilds, a fully sail-able ocean with\n"
-		"<078>customizable ships and ship battle system, a fully flyable sky with mapping\n"
-		"<078>system, mud-wide auction line, a colosseum in which to prove your battle\n"
-		"<078>prowess (harmless/free pk), and 30+ areas on multiple continents to explore.\n"
-		"\n"
-		"<178>To connect to Primal Darkness enter: #session pd mud.primaldarkness.com 5000\n"
-		"\n",
-		
-		"\n"
-		"<138>Primal Darkness\n"
-		"<168>http://www.primaldarkness.com\n"
-		"\n"
-		"<078>Primal Darkness boasts twenty three start races, three quest races, five start classes and twenty one subclasses to suit your adventuring needs, and a custom remort system allowing you to save all your hard work while trying out new races and/or classes. The world has zoned player killing (pk) supported by a justice system, player built and ran guilds, a fully sail-able ocean with customizable ships and ship battle system, a fully flyable sky with mapping system, mud-wide auction line, a colosseum in which to prove your battle prowess (harmless/free pk), and 30+ areas on multiple continents to explore.\n"
-		"\n"
-		"<178>To connect to Primal Darkness enter: #session pd mud.primaldarkness.com 5000\n"
-		"\n"
-	},
-
 	{
 	{
 		1400000000,
 		1400000000,
  		1800000000,
  		1800000000,
@@ -496,25 +579,6 @@ DO_COMMAND(do_banner)
 		"\n"
 		"\n"
 	},
 	},
 
 
-	{
-		1400000000, 
-		1700000000, 
-		100,
-		"\n"
-		"<138>                 Alter Aeon  -  http://www.alteraeon.com\n"
-		"\n"
-		"<078>Alter Aeon is a custom multiclass MUD, where each of the character\n"
-		"<078>classes can be combined to make very unique characters.  This huge\n"
-		"<078>fantasy themed game has hundreds of areas and quests, spanning\n"
-		"<078>several continents and outer planar regions.  There are custom spells,\n"
-		"<078>skills, minions, player run shops, boats, PvP, and many other features\n"
-		"<078>for nearly every kind of player.  The game is very friendly to new players\n"
-		"<078>and has extensive support for the blind and visually impaired.\n"
-		"\n"
-		"<178>To connect to Alter Aeon enter: #session aa alteraeon.com 3000\n"
-		"\n"
-	},
-
 	{
 	{
 		1260469590, * 10 Dec 2009 *
 		1260469590, * 10 Dec 2009 *
 		1323541590, * 10 Dec 2011 *
 		1323541590, * 10 Dec 2011 *
@@ -533,63 +597,6 @@ DO_COMMAND(do_banner)
 		"\n"
 		"\n"
 	},
 	},
 
 
-	{
-		1260469590, * 10 Dec 2009 *
-		1323541590, * 10 Dec 2011 *
-		"\n"
-		"<138>                Maiden Desmodus  -  http://maidendesmodus.com\n"
-		"\n"
-		"<078>Maiden Desmodus is an immersive world of high adventure where your actions, or\n"
-		"<078>inaction, will determine the fate of The Isle. Choose to be born unto one of\n"
-		"<078>two opposing factions, join one of the six powerful guilds, and carve your\n"
-		"<078>place in history through your cunning, your strategy, and your skill with magic\n"
-		"<078>or a blade. At every turn are players who may ally themselves to you, or work\n"
-		"<078>to destroy you. Shall you form your own cabal and command your peers, control\n"
-		"<078>the politics of your city, or lead an army against those who oppose you?\n"
-		"<078>Maiden Desmodus features a completely original world and a custom game engine.\n"
-		"\n"
-		"<178>To connect to Maiden Desmodus enter: #session md maidendesmodus.com 4000\n"
-		"\n"
-	},
-
-	{
-		1260469590, * 10 Dec 2009 *
-		1323541590, * 10 Dec 2011 *
-		"\n"
-		"<138>                     Lost Souls  -  http://lostsouls.org\n"
-		"\n"
-		"<078>\"Our world is fallen, boy.  Aedaris is a ruin.  My grandfather, he told me\n"
-		"<078>of days, not so long gone, when everything you see was part of a great empire.\n"
-		"<078>Peaceful, he said.  Full of wonders.  They called it eternal.  Funny, eh, boy?\n"
-		"<078>They thought it'd last forever, and it went crazy and tore itself apart.  But\n"
-		"<078>they left behind a few things for us, didn't they?  Ha!  Yes, lots for us.  Now\n"
-		"<078>give that wizard-stick here before you blow your fool horns off, and get to\n"
-		"<078>work.  Daylight's soon, and these faeries aren't going to skin themselves.\"\n"
-		"<078>Lost Souls: chaos in the wreckage of empire.  Be clever if you want to live.\n"
-		"\n"
-                "<178>To connect to Lost Souls enter: #session ls lostsouls.org 23\n"
-                "\n"
-		                
-	},
-
-	{
-		1291140000, * 30 Nov 2010 *
-		1354280000, * 30 Nov 2012 *
-		100,
-		"\n"
-		"<138>                Threshold RPG  -  http://www.thresholdrpg.com\n"
-		"\n"
-		"<078>Join us as Threshold RPG, one of the oldest RP enforced games on the\n"
-		"<078>internet. Add to thirteen years of player created history and make your own\n"
-		"<078>mark on the world today. Join a hundred other players who are vying for\n"
-		"<078>political and religious power in complex systems that reward skill, effort,\n"
-		"<078>and social interactions. Threshold RPG is a custom code-base written in\n"
-		"<078>LPC and features a completely unique and original world.\n"
-		"\n"
-		"<178>To connect to Threshold RPG enter: #session thresh thresholdrpg.com 23\n"
-		"\n"
-	},
-
 	{
 	{
 		1291140000, * 30 Nov 2010 *
 		1291140000, * 30 Nov 2010 *
 		1354280000, * 30 Nov 2012 *
 		1354280000, * 30 Nov 2012 *

+ 1 - 1
src/buffer.c

@@ -1135,7 +1135,7 @@ DO_BUFFER(buffer_write)
 		{
 		{
 			show_message(ses, LIST_COMMAND, "#OK: WRITING BUFFER TO '%s'.", arg1);
 			show_message(ses, LIST_COMMAND, "#OK: WRITING BUFFER TO '%s'.", arg1);
 
 
-			logheader(ses, fp, ses->log->mode + LOG_FLAG_OVERWRITE);
+			logheader(ses, fp, ses->log->mode | LOG_FLAG_OVERWRITE);
 
 
 			for (cnt = 1 ; cnt < ses->scroll->used ; cnt++)
 			for (cnt = 1 ; cnt < ses->scroll->used ; cnt++)
 			{
 			{

+ 57 - 5
src/command.c

@@ -27,15 +27,63 @@
 
 
 struct command_type command_table[];
 struct command_type command_table[];
 
 
+size_t command_size();
+
 DO_COMMAND(do_commands)
 DO_COMMAND(do_commands)
 {
 {
-	int cmd;
+	int cmd, size, rows, cols, row, col;
+
+	size = command_size();
+	rows = UMAX(1, ses->wrap / 20);
+	cols = size / rows + (size % rows > 0);
 
 
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
 	arg = sub_arg_in_braces(ses, arg, arg1, GET_ALL, SUB_VAR|SUB_FUN);
 
 
 	tintin_header(ses, 0, " %s ", "COMMANDS");
 	tintin_header(ses, 0, " %s ", "COMMANDS");
 
 
-	for (cmd = 0 ; *command_table[cmd].name != 0 ; cmd++)
+	for (cmd = col = 0 ; col < cols ; col++)
+	{
+		if (*arg1 == 0 && !HAS_BIT(ses->config_flags, CONFIG_FLAG_SCREENREADER))
+		{
+			cmd = col;
+		}
+
+		for (row = 0 ; row < rows && cmd < size ; row++)
+		{
+			if (*arg1 && !is_abbrev(arg1, command_table[cmd].name))
+			{
+				row--;
+				cmd++;
+				continue;
+			}
+
+			if (command_table[cmd].type == TOKEN_TYPE_COMMAND)
+			{
+				cat_sprintf(arg2, "%s%-20s", COLOR_COMMAND, command_table[cmd].name);
+			}
+			else
+			{
+				cat_sprintf(arg2, "%s%-20s", COLOR_STATEMENT, command_table[cmd].name);
+			}
+
+			if (*arg1 == 0 && !HAS_BIT(ses->config_flags, CONFIG_FLAG_SCREENREADER))
+			{
+				cmd += cols;
+			}
+			else
+			{
+				cmd++;
+			}
+
+			if (row + 1 == rows || cmd >= size)
+			{
+				tintin_puts2(ses, arg2);
+				*arg2 = 0;
+				break;
+			}
+		}
+	}
+/*	for (cmd = 0 ; *command_table[cmd].name != 0 ; cmd++)
 	{
 	{
 		if (*arg1 && !is_abbrev(arg1, command_table[cmd].name))
 		if (*arg1 && !is_abbrev(arg1, command_table[cmd].name))
 		{
 		{
@@ -57,7 +105,7 @@ DO_COMMAND(do_commands)
 			cat_sprintf(arg2, "%s%20s", COLOR_STATEMENT, command_table[cmd].name);
 			cat_sprintf(arg2, "%s%20s", COLOR_STATEMENT, command_table[cmd].name);
 		}
 		}
 	}
 	}
-
+*/
 	if (*arg2)
 	if (*arg2)
 	{
 	{
 		tintin_puts2(ses, arg2);
 		tintin_puts2(ses, arg2);
@@ -172,7 +220,6 @@ extern DO_COMMAND(do_debug);
 extern DO_COMMAND(do_echo);
 extern DO_COMMAND(do_echo);
 extern DO_COMMAND(do_event);
 extern DO_COMMAND(do_event);
 extern DO_COMMAND(do_format);
 extern DO_COMMAND(do_format);
-extern DO_COMMAND(do_function);
 extern DO_COMMAND(do_gag);
 extern DO_COMMAND(do_gag);
 extern DO_COMMAND(do_highlight);
 extern DO_COMMAND(do_highlight);
 extern DO_COMMAND(do_ignore);
 extern DO_COMMAND(do_ignore);
@@ -266,7 +313,7 @@ struct command_type command_table[] =
 	{    "log",               do_log,               2, TOKEN_TYPE_COMMAND },
 	{    "log",               do_log,               2, TOKEN_TYPE_COMMAND },
 	{    "loop",              do_nop,               3, TOKEN_TYPE_LOOP    },
 	{    "loop",              do_nop,               3, TOKEN_TYPE_LOOP    },
 	{    "macro",             do_macro,             3, TOKEN_TYPE_COMMAND },
 	{    "macro",             do_macro,             3, TOKEN_TYPE_COMMAND },
-	{    "map",               do_map,               2, TOKEN_TYPE_COMMAND },
+	{    "map",               do_map,               3, TOKEN_TYPE_COMMAND },
 	{    "math",              do_math,              2, TOKEN_TYPE_COMMAND },
 	{    "math",              do_math,              2, TOKEN_TYPE_COMMAND },
 	{    "message",           do_message,           2, TOKEN_TYPE_COMMAND },
 	{    "message",           do_message,           2, TOKEN_TYPE_COMMAND },
 	{    "nop",               do_nop,               0, TOKEN_TYPE_COMMAND },
 	{    "nop",               do_nop,               0, TOKEN_TYPE_COMMAND },
@@ -319,3 +366,8 @@ struct command_type command_table[] =
 	{    "zap",               do_zap,               1, TOKEN_TYPE_COMMAND },
 	{    "zap",               do_zap,               1, TOKEN_TYPE_COMMAND },
 	{    "",                  NULL,                 0, TOKEN_TYPE_COMMAND }
 	{    "",                  NULL,                 0, TOKEN_TYPE_COMMAND }
 };
 };
+
+size_t command_size()
+{
+	return sizeof(command_table) / sizeof(command_table[0]) - 1;
+}

+ 3 - 1
src/config.c

@@ -194,7 +194,7 @@ DO_CONFIG(config_charset)
 
 
 			if (*charset_table[index].name == 0)
 			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>");
+				show_error(ses, LIST_CONFIG, "#SYNTAX: #CONFIG {CHARSET} <AUTO|ASCII|BIG-5|BIG5TOUTF8|CP437TOUTF8|CP949|CP949TOUTF8|CP1251TOUTF8|GBK-1|GBK1TOUTF8|ISO1TOUTF8|ISO2TOUTF8|KOI8TOUTF8|UTF-8>");
 
 
 				return NULL;
 				return NULL;
 			}
 			}
@@ -881,6 +881,8 @@ DO_CONFIG(config_telnet)
 		}
 		}
 		else if (is_abbrev(arg2, "OFF"))
 		else if (is_abbrev(arg2, "OFF"))
 		{
 		{
+			ses->read_len = 0;
+
 			DEL_BIT(ses->telopts, TELOPT_FLAG_DEBUG);
 			DEL_BIT(ses->telopts, TELOPT_FLAG_DEBUG);
 			DEL_BIT(ses->config_flags, CONFIG_FLAG_TELNET);
 			DEL_BIT(ses->config_flags, CONFIG_FLAG_TELNET);
 		}
 		}

+ 11 - 13
src/cursor.c

@@ -2021,23 +2021,21 @@ DO_CURSOR(cursor_redraw_line)
 		return;
 		return;
 	}
 	}
 
 
+	SET_BIT(gtd->ses->input->flags, INPUT_FLAG_REDRAW);
+
 	if (inputline_editor())
 	if (inputline_editor())
 	{
 	{
 		cursor_redraw_singleline(ses, "");
 		cursor_redraw_singleline(ses, "");
-
-		pop_call();
-		return;
 	}
 	}
-
-	if (inputline_multiline())
+	else if (inputline_multiline())
 	{
 	{
 		cursor_redraw_multiline(ses, "");
 		cursor_redraw_multiline(ses, "");
-
-		pop_call();
-		return;
 	}
 	}
-
-	cursor_redraw_singleline(ses, "");
+	else
+	{
+		cursor_redraw_singleline(ses, "");
+	}
+	DEL_BIT(gtd->ses->input->flags, INPUT_FLAG_REDRAW);
 
 
 	pop_call();
 	pop_call();
 	return;
 	return;
@@ -2700,7 +2698,7 @@ DO_CURSOR(cursor_tab)
 
 
 		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
 		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
 		{
 		{
-			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {DICTIONARY|LIST|SCROLLBACK} FORWARD");
+			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|LIST|SCROLLBACK> FORWARD}");
 		}
 		}
 		else
 		else
 		{
 		{
@@ -2722,7 +2720,7 @@ DO_CURSOR(cursor_tab)
 
 
 		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
 		if (!HAS_BIT(flag, TAB_FLAG_DICTIONARY|TAB_FLAG_LIST|TAB_FLAG_SCROLLBACK))
 		{
 		{
-			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {DICTIONARY|LIST|SCROLLBACK} BACKWARD");
+			show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|LIST|SCROLLBACK> BACKWARD}");
 		}
 		}
 		else
 		else
 		{
 		{
@@ -2731,6 +2729,6 @@ DO_CURSOR(cursor_tab)
 	}
 	}
 	else
 	else
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {DICTIONARY;LIST;SCROLLBACK} <BACKWARD|FORWARD>");
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #CURSOR TAB {<DICTIONARY|LIST|SCROLLBACK> <BACKWARD|FORWARD>}");
 	}
 	}
 }
 }

+ 6 - 1
src/daemon.c

@@ -311,11 +311,16 @@ DO_DAEMON(daemon_attach)
 	{
 	{
 		tintin_printf2(ses, "do_attach: select rds: timeout");
 		tintin_printf2(ses, "do_attach: select rds: timeout");
 
 
-		gtd->attach_sock = close(gtd->attach_sock);
+		check_all_events(gtd->ses, EVENT_FLAG_SYSTEM, 0, 2, "DAEMON ATTACH TIMEOUT", sock_file, ntos(pid));
+
+		gtd->attach_sock = 0;
+//		gtd->attach_sock = close(gtd->attach_sock);
 		
 		
 		return;
 		return;
 	}
 	}
 
 
+	tintin_printf2(ses, "do_attach: succes");
+
 	return;
 	return;
 }
 }
 
 

+ 51 - 6
src/data.c

@@ -499,6 +499,31 @@ int bsearch_alpha_list(struct listroot *root, char *text, int seek)
 	bot = 0;
 	bot = 0;
 	top = root->used;
 	top = root->used;
 
 
+	if (HAS_BIT(root->flags, LIST_FLAG_CASE))
+	{
+		while (top > 1)
+		{
+			mid = top / 2;
+
+			if (strcasecmp(text, root->list[bot + mid]->arg1) >= 0)
+			{
+				bot += mid;
+			}
+			top -= mid;
+		}
+
+		if (strcasecmp(text, root->list[bot]->arg1) == 0)
+		{
+			return bot + (seek == SEEK_APPEND);
+		}
+
+		if (seek)
+		{
+			return bot + (strcasecmp(text, root->list[bot]->arg1) > 0);
+		}
+		return -1;
+	}
+
 	while (top > 1)
 	while (top > 1)
 	{
 	{
 		mid = top / 2;
 		mid = top / 2;
@@ -625,7 +650,7 @@ int bsearch_alnum_list(struct listroot *root, char *text, int seek)
 
 
 		if (noi)
 		if (noi)
 		{
 		{
-			srt = (toi < toj) ? -1 : (toi > toj) ? 1 : 0;
+			srt = !noj ? 1 : (toi < toj) ? -1 : (toi > toj) ? 1 : 0;
 		}
 		}
 		else if (noj)
 		else if (noj)
 		{
 		{
@@ -650,7 +675,6 @@ int bsearch_alnum_list(struct listroot *root, char *text, int seek)
 		{
 		{
 			bot = val + 1;
 			bot = val + 1;
 		}
 		}
-
 		val = bot + (top - bot) / 2;
 		val = bot + (top - bot) / 2;
 	}
 	}
 
 
@@ -1371,6 +1395,31 @@ DO_COMMAND(do_info)
 				}
 				}
 				break;
 				break;
 
 
+			case CTRL_D:
+				if (is_abbrev(arg1, "DAEMON"))
+				{
+					if (is_abbrev(arg2, "SAVE"))
+					{
+						sprintf(name, "info[DAEMON]");
+
+						set_nest_node_ses(ses, name, "{DETACH_FILE}{%s}{ATTACH_FILE}{%s}", gtd->detach_port > 0 ? gtd->detach_file : "", gtd->attach_sock > 0 ? gtd->attach_file : "");
+
+						show_message(ses, LIST_COMMAND, "#INFO: DATA WRITTEN TO {info[SYSTEM]}");
+					}
+					else
+					{
+						tintin_printf2(ses, "#INFO DAEMON: DETACH UID     = %d", gtd->detach_info.uid);
+						tintin_printf2(ses, "#INFO DAEMON: DETACH GID     = %d", gtd->detach_info.gid);
+						tintin_printf2(ses, "#INFO DAEMON: DETACH PID     = %d", gtd->detach_info.pid);
+						tintin_printf2(ses, "#INFO DAEMON: DETACH_SOCK    = %d", gtd->detach_sock);
+						tintin_printf2(ses, "#INFO DAEMON: DETACH_PORT    = %d", gtd->detach_port);
+						tintin_printf2(ses, "#INFO DAEMON: DETACH_FILE    = %s", gtd->detach_port ? gtd->detach_file : "");
+						tintin_printf2(ses, "#INFO DAEMON: ATTACH_SOCK    = %d", gtd->attach_sock);
+						tintin_printf2(ses, "#INFO DAEMON: ATTACH_FILE    = %s", gtd->attach_sock ? gtd->attach_file : "");
+					}
+				}
+				break;
+
 			case CTRL_E:
 			case CTRL_E:
 				if (is_abbrev(arg1, "ENVIRON"))
 				if (is_abbrev(arg1, "ENVIRON"))
 				{
 				{
@@ -1655,10 +1704,6 @@ DO_COMMAND(do_info)
 						tintin_printf2(ses, "#INFO SYSTEM: PID            = %d", getpid());
 						tintin_printf2(ses, "#INFO SYSTEM: PID            = %d", getpid());
 						tintin_printf2(ses, "#INFO SYSTEM: TERM           = %s", gtd->system->term);
 						tintin_printf2(ses, "#INFO SYSTEM: TERM           = %s", gtd->system->term);
 						tintin_printf2(ses, "#INFO SYSTEM: TINTIN         = %s", gtd->system->tt_dir);
 						tintin_printf2(ses, "#INFO SYSTEM: TINTIN         = %s", gtd->system->tt_dir);
-						tintin_printf2(ses, "#INFO SYSTEM: DETACH_PORT    = %d", gtd->detach_port);
-						tintin_printf2(ses, "#INFO SYSTEM: DETACH_FILE    = %s", gtd->detach_port ? gtd->detach_file : "");
-						tintin_printf2(ses, "#INFO SYSTEM: ATTACH_SOCK    = %d", gtd->attach_sock);
-						tintin_printf2(ses, "#INFO SYSTEM: ATTACH_FILE    = %s", gtd->attach_sock ? gtd->attach_file : "");
 					}
 					}
 				}
 				}
 				break;
 				break;

+ 24 - 6
src/draw.c

@@ -602,6 +602,11 @@ void scale_drawing(struct session *ses, int *top_row, int *top_col, int *bot_row
 		max_width  = gtd->screen->cols;
 		max_width  = gtd->screen->cols;
 	}
 	}
 
 
+	if (HAS_BIT(flags, DRAW_FLAG_VER))
+	{
+		max_width = 1 + *bot_col - *top_col;
+	}
+
 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
 	{
 	{
 		max_height = gtd->screen->rows * 10;
 		max_height = gtd->screen->rows * 10;
@@ -1754,7 +1759,7 @@ DO_DRAW(draw_map)
 	{
 	{
 		sprintf(arg, "{%d} {%d} {SAVE}", map_rows, map_cols);
 		sprintf(arg, "{%d} {%d} {SAVE}", map_rows, map_cols);
 
 
-		map_map(ses, arg, arg1, arg2);
+		map_map(ses, arg, arg1, arg2, arg3);
 	}
 	}
 	else
 	else
 	{
 	{
@@ -2532,10 +2537,22 @@ DO_DRAW(draw_text)
 	{
 	{
 		str_fix(buf1);
 		str_fix(buf1);
 
 
-		while (height < rows)
+		if (HAS_BIT(flags, DRAW_FLAG_TALIGN))
 		{
 		{
-			str_ins(&buf1, 0, "\n");
-			height++;
+			while (height < rows - 1)
+			{
+				str_ins(&buf1, 0, "\n");
+				str_cat(&buf1, "\n");
+				height += 2;
+			}
+		}
+		else
+		{
+			while (height < rows)
+			{
+				str_ins(&buf1, 0, "\n");
+				height++;
+			}
 		}
 		}
 	}
 	}
 
 
@@ -2554,9 +2571,10 @@ DO_DRAW(draw_text)
 	}
 	}
 	else
 	else
 	{
 	{
-		while (*txt && height > rows)
+		while (*txt && height && height > rows)
 		{
 		{
 			txt = strchr(txt, '\n');
 			txt = strchr(txt, '\n');
+
 			txt++;
 			txt++;
 			height--;
 			height--;
 		}
 		}
@@ -2598,7 +2616,7 @@ DO_DRAW(draw_text)
 		}
 		}
 		else if (HAS_BIT(flags, DRAW_FLAG_CALIGN|DRAW_FLAG_LALIGN|DRAW_FLAG_RALIGN))
 		else if (HAS_BIT(flags, DRAW_FLAG_CALIGN|DRAW_FLAG_LALIGN|DRAW_FLAG_RALIGN))
 		{
 		{
-			if (HAS_BIT(flags, DRAW_FLAG_CALIGN))
+			if (HAS_BIT(flags, DRAW_FLAG_CALIGN) || HAS_BIT(flags, DRAW_FLAG_LALIGN|DRAW_FLAG_RALIGN) == DRAW_FLAG_LALIGN+DRAW_FLAG_RALIGN)
 			{
 			{
 				calign(ses, txt, buf3, cols);
 				calign(ses, txt, buf3, cols);
 			}
 			}

+ 177 - 152
src/gui.h

@@ -1,5 +1,5 @@
 char *tt_gui = "#line quiet #port init gui 0\n"
 char *tt_gui = "#line quiet #port init gui 0\n"
-"\n"
+
 "#function gui_link\n"
 "#function gui_link\n"
 "{\n"
 "{\n"
 "	#format gui[link] {%+11h} {%3};\n"
 "	#format gui[link] {%+11h} {%3};\n"
@@ -7,102 +7,102 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#line sub esc #var gui[link] {\e]68;2;%1;%2\a\e[4;24m$gui[link]\e[24m};\n"
 "	#line sub esc #var gui[link] {\e]68;2;%1;%2\a\e[4;24m$gui[link]\e[24m};\n"
 "	#return $gui[link]\n"
 "	#return $gui[link]\n"
 "}\n"
 "}\n"
-"\n"
+
 "#function gui_profile_link\n"
 "#function gui_profile_link\n"
 "{\n"
 "{\n"
 "	#format gui[link] {%-24.24s} {%3};\n"
 "	#format gui[link] {%-24.24s} {%3};\n"
-"\n"
+
 "	#line sub esc #var gui[link] {\e]68;2;%1;%2\a\e[4;24m$gui[link]\e[24m};\n"
 "	#line sub esc #var gui[link] {\e]68;2;%1;%2\a\e[4;24m$gui[link]\e[24m};\n"
 "	#return $gui[link]\n"
 "	#return $gui[link]\n"
 "}\n"
 "}\n"
-"\n"
+
 "#event {PRESSED SECURE LINK COMMAND MOUSE BUTTON ONE} {%4}\n"
 "#event {PRESSED SECURE LINK COMMAND MOUSE BUTTON ONE} {%4}\n"
-"\n"
+
 "#event {PRESSED SECURE LINK COMMAND MOUSE BUTTON THREE}\n"
 "#event {PRESSED SECURE LINK COMMAND MOUSE BUTTON THREE}\n"
 "{\n"
 "{\n"
 "	#line ignore #showme {<138>Group<178>: %6 <138>Command<178>: %4}\n"
 "	#line ignore #showme {<138>Group<178>: %6 <138>Command<178>: %4}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#event {PRESSED SECURE LINK WORLD MOUSE BUTTON ONE}\n"
 "#event {PRESSED SECURE LINK WORLD MOUSE BUTTON ONE}\n"
 "{\n"
 "{\n"
 "	world_click {%4}\n"
 "	world_click {%4}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#event {PRESSED SECURE LINK WORLD MOUSE BUTTON THREE}\n"
 "#event {PRESSED SECURE LINK WORLD MOUSE BUTTON THREE}\n"
 "{\n"
 "{\n"
 "	#line ignore #showme {<138>Group<178>: %6 <138>Command<178>: %4}\n"
 "	#line ignore #showme {<138>Group<178>: %6 <138>Command<178>: %4}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#event {DOUBLE-CLICKED SECURE LINK WORLD MOUSE BUTTON ONE} {gui_connect}\n"
 "#event {DOUBLE-CLICKED SECURE LINK WORLD MOUSE BUTTON ONE} {gui_connect}\n"
-"\n"
+
 "#button {-2 28 -2 -28;PRESSED MOUSE BUTTON ONE}\n"
 "#button {-2 28 -2 -28;PRESSED MOUSE BUTTON ONE}\n"
 "{\n"
 "{\n"
 "	profile_tab_update;\n"
 "	profile_tab_update;\n"
-"\n"
+
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
-"\n"
+
 "	profile_tab_set INPUT\n"
 "	profile_tab_set INPUT\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_worlds}   {world_tab worlds}\n"
 "#alias {gui_worlds}   {world_tab worlds}\n"
 "#alias {gui_sponsors} {world_tab sponsors}\n"
 "#alias {gui_sponsors} {world_tab sponsors}\n"
-"\n"
+
 "#alias {world_tab}\n"
 "#alias {world_tab}\n"
 "{\n"
 "{\n"
 "	#var gui[world_tab] %1;\n"
 "	#var gui[world_tab] %1;\n"
-"\n"
+
 "	#class world_tab kill;\n"
 "	#class world_tab kill;\n"
-"\n"
+
 "	#if {{$gui[world_tab]} == {worlds}}\n"
 "	#if {{$gui[world_tab]} == {worlds}}\n"
 "	{\n"
 "	{\n"
-"		#draw jade Yellow rounded calign box 1  1 3 13 {@gui_link{COMMAND;{profile_tab_cancel;world_tab worlds;draw_worlds 0};worlds}};\n"
-"		#draw jade Azure  rounded calign box 1 14 3 26 {@gui_link{COMMAND;{profile_tab_cancel;world_tab sponsors;draw_sponsors 0};sponsors}}\n"
+"		#draw jade Yellow rounded calign box 1  1 3 13 {@gui_link{COMMAND;{profile_tab_cancel;world_tab worlds;draw_worlds};worlds}};\n"
+"		#draw jade Azure  rounded calign box 1 14 3 26 {@gui_link{COMMAND;{profile_tab_cancel;world_tab sponsors;draw_sponsors};sponsors}}\n"
 "	};\n"
 "	};\n"
 "	#else\n"
 "	#else\n"
 "	{\n"
 "	{\n"
-"		#draw jade Azure  rounded calign box 1  1 3 13 {@gui_link{COMMAND;{profile_tab_cancel;world_tab worlds;draw_worlds 0};worlds}};\n"
-"		#draw jade Yellow rounded calign box 1 14 3 26 {@gui_link{COMMAND;{profile_tab_cancel;world_tab sponsors;draw_sponsors 0};sponsors}}\n"
+"		#draw jade Azure  rounded calign box 1  1 3 13 {@gui_link{COMMAND;{profile_tab_cancel;world_tab worlds;draw_worlds};worlds}};\n"
+"		#draw jade Yellow rounded calign box 1 14 3 26 {@gui_link{COMMAND;{profile_tab_cancel;world_tab sponsors;draw_sponsors};sponsors}}\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#draw jade Green rounded calign box -3  1 -1 13 {@gui_link{COMMAND;gui_new;new}};\n"
 "	#draw jade Green rounded calign box -3  1 -1 13 {@gui_link{COMMAND;gui_new;new}};\n"
 "	#draw jade Green rounded calign box -3 14 -1 26 {@gui_link{COMMAND;#delay 0 #end;exit}}\n"
 "	#draw jade Green rounded calign box -3 14 -1 26 {@gui_link{COMMAND;#delay 0 #end;exit}}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {draw_world}\n"
 "#alias {draw_world}\n"
 "{\n"
 "{\n"
 "	#if {{%2} == {%3}}\n"
 "	#if {{%2} == {%3}}\n"
 "	{\n"
 "	{\n"
-"		#draw jade Yellow rounded TALIGN box %1*3+1 1 %1*3+3 26 @gui_profile_link{WORLD;%2;%2};\n"
+"		#draw jade Yellow rounded TALIGN tile %1*2+3 2 %1*2+3 25 @gui_profile_link{WORLD;%2;%2};\n"
 "	};\n"
 "	};\n"
 "	#else\n"
 "	#else\n"
 "	{\n"
 "	{\n"
-"		#draw jade Azure rounded TALIGN box %1*3+1 1 %1*3+3 26 @gui_profile_link{WORLD;%2;%2}\n"
+"		#draw jade  Azure rounded TALIGN tile %1*2+3 2 %1*2+3 25 @gui_profile_link{WORLD;%2;%2}\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {world_click}\n"
 "#alias {world_click}\n"
 "{\n"
 "{\n"
 "	#var gui[active] {%1};\n"
 "	#var gui[active] {%1};\n"
-"\n"
-"	profile_tab_cancel;\n"
-"\n"
+
+"	#nop profile_tab_cancel;\n"
+
 "	#if {{$gui[world_tab]} == {worlds}}\n"
 "	#if {{$gui[world_tab]} == {worlds}}\n"
 "	{\n"
 "	{\n"
 "		#var gui[new] {$worldlist[%1]};\n"
 "		#var gui[new] {$worldlist[%1]};\n"
-"\n"
+
 "		draw_worlds {%1}\n"
 "		draw_worlds {%1}\n"
 "	};\n"
 "	};\n"
 "	#else\n"
 "	#else\n"
 "	{\n"
 "	{\n"
 "		#var gui[new] {$info[BANNERS][%1]} {{SSL}{off}} {{FILE}{}} {{CHARACTER}{}} {{PASSWORD}{}} {{INPUT}{}};\n"
 "		#var gui[new] {$info[BANNERS][%1]} {{SSL}{off}} {{FILE}{}} {{CHARACTER}{}} {{PASSWORD}{}} {{INPUT}{}};\n"
-"\n"
-"		draw_sponsors {%1}\n"
+
+"		draw_sponsors\n"
 "	};\n"
 "	};\n"
 "	reload_profile_tab;\n"
 "	reload_profile_tab;\n"
-"\n"
+
 "	#buffer end\n"
 "	#buffer end\n"
 "}\n"
 "}\n"
-"\n"
+
 "#function {gui_size_left}\n"
 "#function {gui_size_left}\n"
 "{\n"
 "{\n"
 "	#if {{$gui[world_tab]} == {worlds}}\n"
 "	#if {{$gui[world_tab]} == {worlds}}\n"
@@ -114,7 +114,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#return &info[BANNERS][];\n"
 "		#return &info[BANNERS][];\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_draw_left}\n"
 "#alias {gui_draw_left}\n"
 "{\n"
 "{\n"
 "	#if {{$gui[world_tab]} == {worlds}}\n"
 "	#if {{$gui[world_tab]} == {worlds}}\n"
@@ -126,68 +126,90 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		draw_sponsors\n"
 "		draw_sponsors\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {draw_worlds}\n"
 "#alias {draw_worlds}\n"
 "{\n"
 "{\n"
 "	#class world_tab kill;\n"
 "	#class world_tab kill;\n"
 "	#class profile_tab kill;\n"
 "	#class profile_tab kill;\n"
-"\n"
+
 "	#draw tile 4 1 -4 26 { };\n"
 "	#draw tile 4 1 -4 26 { };\n"
-"\n"
+
 "	#if {&worldlist[] == 0}\n"
 "	#if {&worldlist[] == 0}\n"
 "	{\n"
 "	{\n"
 "		#return;\n"
 "		#return;\n"
 "	};\n"
 "	};\n"
-"\n"
-"	#local index 1;\n"
+
+"	#local index $gui[index];\n"
 "	#local offset 1;\n"
 "	#local offset 1;\n"
-"\n"
+"       #local rows 0;\n"
+
+"       #if {&worldlist[] * 2 - $index * 2 > $gui[rows] - 9}\n"
+"       {\n"
+"		#math rows ($gui[rows] - 3) & ~1;\n"
+"	}\n"
+"	{\n"
+"		#math rows 6 + &worldlist[] * 2 - $index * 2;\n"
+"	};\n"
+
+"       #draw jade Azure rounded grid table 4 1 $rows 26 { }$worldlist[];\n"
+
 "	#loop $gui[index] &worldlist[] index\n"
 "	#loop $gui[index] &worldlist[] index\n"
 "	{\n"
 "	{\n"
-"		draw_world {$offset} {$worldlist[+$index][NAME]} {%1};\n"
-"\n"
+"		draw_world {$offset} {$worldlist[+$index][NAME]} {$gui[active]};\n"
+
 "		#math offset $offset + 1;\n"
 "		#math offset $offset + 1;\n"
-"\n"
-"		#if {$offset * 3 > $gui[rows] - 6}\n"
+
+"		#if {$offset * 2 + 1 > $gui[rows] - 6}\n"
 "		{\n"
 "		{\n"
 "			#break;\n"
 "			#break;\n"
 "		};\n"
 "		};\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {draw_sponsors}\n"
 "#alias {draw_sponsors}\n"
 "{\n"
 "{\n"
 "	#class world_tab kill;\n"
 "	#class world_tab kill;\n"
 "	#class profile_tab kill;\n"
 "	#class profile_tab kill;\n"
-"\n"
+
 "	#draw tile 4 1 -4 26 { };\n"
 "	#draw tile 4 1 -4 26 { };\n"
-"\n"
+
 "	#if {&info[BANNERS][] == 0}\n"
 "	#if {&info[BANNERS][] == 0}\n"
 "	{\n"
 "	{\n"
 "		#line ignore #showme <faa>Sponsors: No banners found.;\n"
 "		#line ignore #showme <faa>Sponsors: No banners found.;\n"
 "		#return;\n"
 "		#return;\n"
 "	};\n"
 "	};\n"
-"\n"
-"	#local index 1;\n"
+
+"	#local index $gui[index];\n"
 "	#local offset 1;\n"
 "	#local offset 1;\n"
-"\n"
+"       #local rows 0;\n"
+
+"       #if {&info[BANNERS][] * 2 - $index * 2 > $gui[rows] - 9}\n"
+"       {\n"
+"		#math rows ($gui[rows] - 3) & ~1;\n"
+"	}\n"
+"	{\n"
+"		#math rows 6 + &info[BANNERS][] * 2 - $index * 2;\n"
+"	};\n"
+
+"       #draw jade Azure rounded grid table 4 1 $rows 26 { }$info[BANNERS][];\n"
+
 "	#loop $gui[index] &info[BANNERS][] index\n"
 "	#loop $gui[index] &info[BANNERS][] index\n"
 "	{\n"
 "	{\n"
-"		draw_world {$offset} {$info[BANNERS][+$index][NAME]} {%1};\n"
-"\n"
+"		draw_world {$offset} {$info[BANNERS][+$index][NAME]} {$gui[active]};\n"
+
 "		#math offset $offset + 1;\n"
 "		#math offset $offset + 1;\n"
-"\n"
-"		#if {$offset * 3 > $gui[rows] - 6}\n"
+
+"		#if {$offset * 2 + 1 > $gui[rows] - 6}\n"
 "		{\n"
 "		{\n"
-"			#break;\n"
-"		};\n"
+"			#break\n"
+"		}\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_tab_forward}\n"
 "#alias {gui_tab_forward}\n"
 "{\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#switch {{$input_name}}\n"
 "	#switch {{$input_name}}\n"
 "	{\n"
 "	{\n"
 "		#case {{profile_tab_NAME}}      {profile_tab_cycle ALIAS NAME};\n"
 "		#case {{profile_tab_NAME}}      {profile_tab_cycle ALIAS NAME};\n"
@@ -200,11 +222,11 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#case {{profile_tab_INPUT}}     {profile_tab_cycle NAME INPUT};\n"
 "		#case {{profile_tab_INPUT}}     {profile_tab_cycle NAME INPUT};\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_tab_backward}\n"
 "#alias {gui_tab_backward}\n"
 "{\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#switch {{$input_name}}\n"
 "	#switch {{$input_name}}\n"
 "	{\n"
 "	{\n"
 "		#case {{profile_tab_NAME}}      {profile_tab_cycle INPUT NAME};\n"
 "		#case {{profile_tab_NAME}}      {profile_tab_cycle INPUT NAME};\n"
@@ -217,16 +239,16 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#case {{profile_tab_INPUT}}     {profile_tab_cycle PASSWORD INPUT};\n"
 "		#case {{profile_tab_INPUT}}     {profile_tab_cycle PASSWORD INPUT};\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_cycle}\n"
 "#alias {profile_tab_cycle}\n"
 "{\n"
 "{\n"
 "	profile_tab_pull %2;\n"
 "	profile_tab_pull %2;\n"
-"\n"
+
 "	#screen inputregion $gui[input][%1][top_row] $gui[input][%1][top_col] $gui[input][%1][bot_row] $gui[input][%1][bot_col] profile_tab_%1;\n"
 "	#screen inputregion $gui[input][%1][top_row] $gui[input][%1][top_col] $gui[input][%1][bot_row] $gui[input][%1][bot_col] profile_tab_%1;\n"
-"\n"
+
 "	profile_tab_set %1;\n"
 "	profile_tab_set %1;\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_pull}\n"
 "#alias {profile_tab_pull}\n"
 "{\n"
 "{\n"
 "	#if {{%1} == {PASSWORD}}\n"
 "	#if {{%1} == {PASSWORD}}\n"
@@ -242,17 +264,17 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#cursor clear;\n"
 "	#cursor clear;\n"
 "	profile_tab %1\n"
 "	profile_tab %1\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_update}\n"
 "#alias {profile_tab_update}\n"
 "{\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|INPUT|HOST|PORT|FILE|CHARACTER|PASSWORD}}\n"
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|INPUT|HOST|PORT|FILE|CHARACTER|PASSWORD}}\n"
 "	{\n"
 "	{\n"
 "		profile_tab_pull &1\n"
 "		profile_tab_pull &1\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#function gui_toggle\n"
 "#function gui_toggle\n"
 "{\n"
 "{\n"
 "	#if {{%1} == {%2}}\n"
 "	#if {{%1} == {%2}}\n"
@@ -261,7 +283,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	};\n"
 "	};\n"
 "	#return %2\n"
 "	#return %2\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_set}\n"
 "#alias {profile_tab_set}\n"
 "{\n"
 "{\n"
 "	#if {{%1} == {PASSWORD}}\n"
 "	#if {{%1} == {PASSWORD}}\n"
@@ -275,11 +297,11 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#cursor set {$gui[new][%1]};\n"
 "		#cursor set {$gui[new][%1]};\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_input}\n"
 "#alias {profile_tab_input}\n"
 "{\n"
 "{\n"
 "	#var gui[input][%5] {{top_row}{%1}{top_col}{%2}{bot_row}{%3}{bot_col}{%4}};\n"
 "	#var gui[input][%5] {{top_row}{%1}{top_col}{%2}{bot_row}{%3}{bot_col}{%4}};\n"
-"\n"
+
 "	#if {{%6} == {toggle}}\n"
 "	#if {{%6} == {toggle}}\n"
 "	{\n"
 "	{\n"
 "		#button {%1 %2 %3 %4;PRESSED MOUSE BUTTON ONE}\n"
 "		#button {%1 %2 %3 %4;PRESSED MOUSE BUTTON ONE}\n"
@@ -303,7 +325,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		}\n"
 "		}\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#function b64z\n"
 "#function b64z\n"
 "{\n"
 "{\n"
 "	#if {{%0} === {}}\n"
 "	#if {{%0} === {}}\n"
@@ -314,7 +336,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#format temp %+64z {%0};\n"
 "	#format temp %+64z {%0};\n"
 "	#return $temp\n"
 "	#return $temp\n"
 "}\n"
 "}\n"
-"\n"
+
 "#function b64Z\n"
 "#function b64Z\n"
 "{\n"
 "{\n"
 "	#if {{%0} === {}}\n"
 "	#if {{%0} === {}}\n"
@@ -325,14 +347,14 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#format temp %+64Z {%0};\n"
 "	#format temp %+64Z {%0};\n"
 "	#return $temp\n"
 "	#return $temp\n"
 "}\n"
 "}\n"
-"\n"
+
 "#function starout\n"
 "#function starout\n"
 "{\n"
 "{\n"
 "	#local temp {%0};\n"
 "	#local temp {%0};\n"
 "	#replace temp {%.} {*};\n"
 "	#replace temp {%.} {*};\n"
 "	#return $temp\n"
 "	#return $temp\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_draw}\n"
 "#alias {profile_tab_draw}\n"
 "{\n"
 "{\n"
 "	#if {{%5} == {PASSWORD}}\n"
 "	#if {{%5} == {PASSWORD}}\n"
@@ -351,7 +373,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		profile_tab_input %1+1 %2+1 %1+1 %4-1 %5 %6\n"
 "		profile_tab_input %1+1 %2+1 %1+1 %4-1 %5 %6\n"
 "	};\n"
 "	};\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab}\n"
 "#alias {profile_tab}\n"
 "{\n"
 "{\n"
 "	#switch {{%1}}\n"
 "	#switch {{%1}}\n"
@@ -366,75 +388,75 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#case {{PASSWORD}}  {profile_tab_draw 19 -26 21 -1 PASSWORD}\n"
 "		#case {{PASSWORD}}  {profile_tab_draw 19 -26 21 -1 PASSWORD}\n"
 "	};\n"
 "	};\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_cancel}\n"
 "#alias {profile_tab_cancel}\n"
 "{\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|HOST|PORT|SSL|FILE|CHARACTER|PASSWORD}}\n"
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|HOST|PORT|SSL|FILE|CHARACTER|PASSWORD}}\n"
 "	{\n"
 "	{\n"
 "		profile_tab_cycle INPUT &1\n"
 "		profile_tab_cycle INPUT &1\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#screen clear square 1 -26 -1 -1;\n"
 "	#screen clear square 1 -26 -1 -1;\n"
 "	#var gui[profile_tab] 0;\n"
 "	#var gui[profile_tab] 0;\n"
 "	#math gui[index] 1\n"
 "	#math gui[index] 1\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_save}\n"
 "#alias {profile_tab_save}\n"
 "{\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|INPUT|HOST|PORT|SSL|FILE|CHARACTER|PASSWORD}}\n"
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|INPUT|HOST|PORT|SSL|FILE|CHARACTER|PASSWORD}}\n"
 "	{\n"
 "	{\n"
 "		profile_tab_pull &1\n"
 "		profile_tab_pull &1\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_new}\n"
 "#alias {gui_new}\n"
 "{\n"
 "{\n"
 "	#class profile_tab kill;\n"
 "	#class profile_tab kill;\n"
-"\n"
+
 "	#var gui[new] {{NAME}{} {ALIAS}{} {HOST}{} {PORT}{} {SSL}{off} {FILE}{} {CHARACTER}{} {PASSWORD}{} {INPUT}{}};\n"
 "	#var gui[new] {{NAME}{} {ALIAS}{} {HOST}{} {PORT}{} {SSL}{off} {FILE}{} {CHARACTER}{} {PASSWORD}{} {INPUT}{}};\n"
-"\n"
+
 "	reload_profile_tab\n"
 "	reload_profile_tab\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_connect}\n"
 "#alias {gui_connect}\n"
 "{\n"
 "{\n"
 "	#if {&gui[new] == 0}\n"
 "	#if {&gui[new] == 0}\n"
 "	{\n"
 "	{\n"
 "		#line ignore #showme <faa>Connect: No world selected;#return;\n"
 "		#line ignore #showme <faa>Connect: No world selected;#return;\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	profile_tab_update;\n"
 "	profile_tab_update;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "	#cursor clear;\n"
 "	#cursor clear;\n"
-"\n"
+
 "	#if {{$gui[new][ALIAS]} == {}}\n"
 "	#if {{$gui[new][ALIAS]} == {}}\n"
 "	{\n"
 "	{\n"
 "		#line ignore #showme <faa>Connect: No alias set;\n"
 "		#line ignore #showme <faa>Connect: No alias set;\n"
 "		#return\n"
 "		#return\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#if {{$gui[new][HOST]} == {}}\n"
 "	#if {{$gui[new][HOST]} == {}}\n"
 "	{\n"
 "	{\n"
 "		#line ignore #showme <faa>Connect: No host set;\n"
 "		#line ignore #showme <faa>Connect: No host set;\n"
 "		#return\n"
 "		#return\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#if {{$gui[new][PORT]} == {}}\n"
 "	#if {{$gui[new][PORT]} == {}}\n"
 "	{\n"
 "	{\n"
 "		#line ignore #showme <faa>Connect: No port set;\n"
 "		#line ignore #showme <faa>Connect: No port set;\n"
 "		#return\n"
 "		#return\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#line ignore #showme {<acf>Connecting to <ffa>$gui[new][NAME]<acf>..};\n"
 "	#line ignore #showme {<acf>Connecting to <ffa>$gui[new][NAME]<acf>..};\n"
-"\n"
+
 "	#config mouse off;\n"
 "	#config mouse off;\n"
-"\n"
+
 "	#buffer refresh;\n"
 "	#buffer refresh;\n"
-"\n"
+
 "	#if {{$gui[new][SSL]} == {off}}\n"
 "	#if {{$gui[new][SSL]} == {off}}\n"
 "	{\n"
 "	{\n"
 "		#session $gui[new][ALIAS] $gui[new][HOST] $gui[new][PORT] $gui[new][FILE];\n"
 "		#session $gui[new][ALIAS] $gui[new][HOST] $gui[new][PORT] $gui[new][FILE];\n"
@@ -443,15 +465,15 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	{\n"
 "	{\n"
 "		#ssl $gui[new][ALIAS] $gui[new][HOST] $gui[new][PORT] $gui[new][FILE];\n"
 "		#ssl $gui[new][ALIAS] $gui[new][HOST] $gui[new][PORT] $gui[new][FILE];\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#info SESSION save;\n"
 "	#info SESSION save;\n"
-"\n"
+
 "	#if {{$info[SESSION][NAME]} !== {gui}}\n"
 "	#if {{$info[SESSION][NAME]} !== {gui}}\n"
 "	{\n"
 "	{\n"
 "		#if {{@gui{$gui[new][CHARACTER]}} !== {}}\n"
 "		#if {{@gui{$gui[new][CHARACTER]}} !== {}}\n"
 "		{\n"
 "		{\n"
 "			#send {@gui{$gui[new][CHARACTER]}};\n"
 "			#send {@gui{$gui[new][CHARACTER]}};\n"
-"\n"
+
 "			#if {{@gui{$gui[new][PASSWORD]}} !== {}}\n"
 "			#if {{@gui{$gui[new][PASSWORD]}} !== {}}\n"
 "			{\n"
 "			{\n"
 "				#send {@gui{@b64Z{$gui[new][PASSWORD]}}}\n"
 "				#send {@gui{@b64Z{$gui[new][PASSWORD]}}}\n"
@@ -463,7 +485,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#line ignore #showme <faa>Connect: Failed to connect to <ffa>$gui[new][NAME]<faa>.\n"
 "		#line ignore #showme <faa>Connect: Failed to connect to <ffa>$gui[new][NAME]<faa>.\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_save}\n"
 "#alias {gui_save}\n"
 "{\n"
 "{\n"
 "	#if {&gui[new] == 0}\n"
 "	#if {&gui[new] == 0}\n"
@@ -472,32 +494,32 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#showme {<acf>Saving worlds.};\n"
 "		#showme {<acf>Saving worlds.};\n"
 "		#return;\n"
 "		#return;\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	profile_tab_update;\n"
 "	profile_tab_update;\n"
-"\n"
+
 "	#if {{$gui[new][NAME]} === {}}\n"
 "	#if {{$gui[new][NAME]} === {}}\n"
 "	{\n"
 "	{\n"
 "		#showme {<faa>Save: No profile name set.};\n"
 "		#showme {<faa>Save: No profile name set.};\n"
 "		#return;\n"
 "		#return;\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
-"\n"
+
 "	#var {worldlist[$gui[new][NAME]]} {$gui[new]};\n"
 "	#var {worldlist[$gui[new][NAME]]} {$gui[new]};\n"
-"\n"
+
 "	#unvar {worldlist[$gui[new][NAME]][DESC]};\n"
 "	#unvar {worldlist[$gui[new][NAME]][DESC]};\n"
-"\n"
+
 "	gui_worlds;\n"
 "	gui_worlds;\n"
-"\n"
+
 "	draw_worlds {&worldlist[$gui[new][NAME]]};\n"
 "	draw_worlds {&worldlist[$gui[new][NAME]]};\n"
-"\n"
+
 "	reload_profile_tab;\n"
 "	reload_profile_tab;\n"
-"\n"
+
 "	#line ignore #showme {<acf>World <ffa>$gui[new][NAME]<acf> saved.};\n"
 "	#line ignore #showme {<acf>World <ffa>$gui[new][NAME]<acf> saved.};\n"
-"\n"
+
 "	#CLASS WORLDS WRITE $info[SYSTEM][TINTIN]/worlds.tin;\n"
 "	#CLASS WORLDS WRITE $info[SYSTEM][TINTIN]/worlds.tin;\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_remove}\n"
 "#alias {gui_remove}\n"
 "{\n"
 "{\n"
 "	#if {&gui[new] == 0}\n"
 "	#if {&gui[new] == 0}\n"
@@ -510,26 +532,26 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#showme {<faa>Remove: No profile name set.};\n"
 "		#showme {<faa>Remove: No profile name set.};\n"
 "		#return;\n"
 "		#return;\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	profile_tab_save;\n"
 "	profile_tab_save;\n"
-"\n"
+
 "	#unvar {worldlist[$gui[new][NAME]]};\n"
 "	#unvar {worldlist[$gui[new][NAME]]};\n"
-"\n"
+
 "	profile_tab_cancel;\n"
 "	profile_tab_cancel;\n"
-"\n"
+
 "	draw_worlds 0;\n"
 "	draw_worlds 0;\n"
-"\n"
-"\n"
+
+
 "	#line ignore #showme {<acf>World <ffa>$gui[new][NAME]<acf> removed.};\n"
 "	#line ignore #showme {<acf>World <ffa>$gui[new][NAME]<acf> removed.};\n"
-"\n"
+
 "	#CLASS WORLDS WRITE $info[SYSTEM][TINTIN]/worlds.tin;\n"
 "	#CLASS WORLDS WRITE $info[SYSTEM][TINTIN]/worlds.tin;\n"
 "}\n"
 "}\n"
-"\n"
-"\n"
+
+
 "#alias {reload_profile_tab}\n"
 "#alias {reload_profile_tab}\n"
 "{\n"
 "{\n"
 "	#var gui[profile_tab] 1;\n"
 "	#var gui[profile_tab] 1;\n"
-"\n"
+
 "	profile_tab NAME;\n"
 "	profile_tab NAME;\n"
 "	profile_tab ALIAS;\n"
 "	profile_tab ALIAS;\n"
 "	profile_tab HOST;\n"
 "	profile_tab HOST;\n"
@@ -538,17 +560,20 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	profile_tab FILE;\n"
 "	profile_tab FILE;\n"
 "	profile_tab CHARACTER;\n"
 "	profile_tab CHARACTER;\n"
 "	profile_tab PASSWORD;\n"
 "	profile_tab PASSWORD;\n"
-"\n"
-"	#if {&gui[new][DESC] && $gui[cols] > 26}\n"
+
+"	#buffer clear;\n"
+
+"	#if {&gui[new][DESC] && $gui[cols] >= 26}\n"
 "	{\n"
 "	{\n"
-"		#draw jade bumped ualign rounded scaled calign scroll box 1 1 1 $gui[cols] {<ffa>$gui[new][NAME] <fff>- <ffa>$gui[new][WEBSITE]};\n"
+//"		#draw jade bumped ualign rounded scaled calign scroll box 1 1 1 $gui[cols] {<ffa>$gui[new][NAME] <fff>- <ffa>$gui[new][WEBSITE]};\n"
+"		#draw jade bumped ualign rounded scaled calign scroll box 1 1 1 $gui[cols] {<ffa>$gui[new][NAME] <fff>- <ffa>\e]8;;$gui[new][WEBSITE]\a\e[04m$gui[new][WEBSITE]\e[24m\e]8;;\a};\n"
 "		#draw jade Silver ualign rounded scaled scroll box 1 1 1 $gui[cols] {$gui[new][DESC]}\n"
 "		#draw jade Silver ualign rounded scaled scroll box 1 1 1 $gui[cols] {$gui[new][DESC]}\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#draw jade Green rounded calign box -3 14 -1 26 {@gui_link{COMMAND;gui_connect;connect}};\n"
 "	#draw jade Green rounded calign box -3 14 -1 26 {@gui_link{COMMAND;gui_connect;connect}};\n"
-"\n"
+
 "	#draw jade Green rounded calign box -3 -26 -1 -14 {@gui_link{COMMAND;gui_save;save}};\n"
 "	#draw jade Green rounded calign box -3 -26 -1 -14 {@gui_link{COMMAND;gui_save;save}};\n"
-"\n"
+
 "	#if {{$gui[world_tab]} !== {sponsors}}\n"
 "	#if {{$gui[world_tab]} !== {sponsors}}\n"
 "	{\n"
 "	{\n"
 "		#draw jade Green rounded calign box -3 -13 -1 -1  {@gui_link{COMMAND;gui_remove;remove}};\n"
 "		#draw jade Green rounded calign box -3 -13 -1 -1  {@gui_link{COMMAND;gui_remove;remove}};\n"
@@ -556,66 +581,66 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#macro {\t} {gui_tab_forward};\n"
 "	#macro {\t} {gui_tab_forward};\n"
 "	#macro {\e[Z} {gui_tab_backward};\n"
 "	#macro {\e[Z} {gui_tab_backward};\n"
 "}\n"
 "}\n"
-"\n"
+
 "#event {SESSION ACTIVATED}\n"
 "#event {SESSION ACTIVATED}\n"
 "{\n"
 "{\n"
 "	gui_reload\n"
 "	gui_reload\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_reload}\n"
 "#alias {gui_reload}\n"
 "{\n"
 "{\n"
 "	#split 1 3 27 27;\n"
 "	#split 1 3 27 27;\n"
 "	#config mouse on;\n"
 "	#config mouse on;\n"
-"\n"
+
 "	#screen clear split;\n"
 "	#screen clear split;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
-"\n"
+
 "	#screen get rows gui[rows];\n"
 "	#screen get rows gui[rows];\n"
 "	#screen get cols gui[cols];\n"
 "	#screen get cols gui[cols];\n"
-"\n"
+
 "	#math gui[cols] $gui[cols] - 54;\n"
 "	#math gui[cols] $gui[cols] - 54;\n"
-"\n"
+
 "	#var gui[index] 1;\n"
 "	#var gui[index] 1;\n"
-"\n"
+
 "	#draw Orange rounded box -3 27 -1 -27;\n"
 "	#draw Orange rounded box -3 27 -1 -27;\n"
 "	#draw Orange rounded box 1 27 -4 -27;\n"
 "	#draw Orange rounded box 1 27 -4 -27;\n"
-"\n"
+
 "	world_tab $gui[world_tab];\n"
 "	world_tab $gui[world_tab];\n"
-"\n"
+
 "	#switch {{$gui[world_tab]}}\n"
 "	#switch {{$gui[world_tab]}}\n"
 "	{\n"
 "	{\n"
-"		#case {{worlds}}   {draw_worlds 0};\n"
-"		#case {{sponsors}} {draw_sponsors 0}\n"
+"		#case {{worlds}}   {draw_worlds};\n"
+"		#case {{sponsors}} {draw_sponsors}\n"
 "	};\n"
 "	};\n"
-"\n"
+
 "	#if {$gui[profile_tab] == 1}\n"
 "	#if {$gui[profile_tab] == 1}\n"
 "	{\n"
 "	{\n"
 "		reload_profile_tab\n"
 "		reload_profile_tab\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#alias {gui_init}\n"
 "#alias {gui_init}\n"
 "{\n"
 "{\n"
 "	#config scroll_lock off;\n"
 "	#config scroll_lock off;\n"
-"\n"
+
 "	#class WORLDS assign #variable {worldlist} {};\n"
 "	#class WORLDS assign #variable {worldlist} {};\n"
-"\n"
+
 "	#info system save;\n"
 "	#info system save;\n"
-"\n"
+
 "	#banner save;\n"
 "	#banner save;\n"
-"\n"
+
 "	#line quiet #read $info[SYSTEM][TINTIN]/worlds.tin;\n"
 "	#line quiet #read $info[SYSTEM][TINTIN]/worlds.tin;\n"
-"\n"
+
 "	#var gui[pause] 0;\n"
 "	#var gui[pause] 0;\n"
 "	#var gui[profile_tab] 0;\n"
 "	#var gui[profile_tab] 0;\n"
 "	#var gui[world_tab] worlds;\n"
 "	#var gui[world_tab] worlds;\n"
-"\n"
+
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
-"\n"
+
 "	#var gui[input][INPUT] {{top_row}{-2}{top_col}{28}{bot_row}{-2}{bot_col}{-28}};\n"
 "	#var gui[input][INPUT] {{top_row}{-2}{top_col}{28}{bot_row}{-2}{bot_col}{-28}};\n"
-"\n"
+
 "	gui_reload;\n"
 "	gui_reload;\n"
-"\n"
+
 "	#if {$gui[cols] > 75}\n"
 "	#if {$gui[cols] > 75}\n"
 "	{\n"
 "	{\n"
 "		#draw Silver huge traced scroll tile 1 1 6 73 { TINTIN++};\n"
 "		#draw Silver huge traced scroll tile 1 1 6 73 { TINTIN++};\n"
@@ -645,19 +670,19 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#draw Silver calign scroll tile 1 1 8 $gui[cols] {T}{i}{n}{T}{i}{n}{+}{+}\n"
 "		#draw Silver calign scroll tile 1 1 8 $gui[cols] {T}{i}{n}{T}{i}{n}{+}{+}\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#EVENT {SCREEN RESIZE}\n"
 "#EVENT {SCREEN RESIZE}\n"
 "{\n"
 "{\n"
 "	#delay {gui_reload} {gui_reload;#buffer end} {0.1}\n"
 "	#delay {gui_reload} {gui_reload;#buffer end} {0.1}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#EVENT {SESSION DESTROYED} {#gts #delay 0 #end}\n"
 "#EVENT {SESSION DESTROYED} {#gts #delay 0 #end}\n"
-"\n"
+
 "#event {SCROLLED MOUSE WHEEL UP}\n"
 "#event {SCROLLED MOUSE WHEEL UP}\n"
 "{\n"
 "{\n"
 "	#if {%1 <= 26}\n"
 "	#if {%1 <= 26}\n"
 "	{\n"
 "	{\n"
-"		#if {$gui[profile_tab] && $gui[index] > 1}\n"
+"		#if {$gui[profile_tab] >= 0 && $gui[index] > 1}\n"
 "		{\n"
 "		{\n"
 "			#math gui[index] $gui[index] - 1;\n"
 "			#math gui[index] $gui[index] - 1;\n"
 "			gui_draw_left\n"
 "			gui_draw_left\n"
@@ -678,12 +703,12 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#buffer up 1\n"
 "		#buffer up 1\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
+
 "#event {SCROLLED MOUSE WHEEL DOWN}\n"
 "#event {SCROLLED MOUSE WHEEL DOWN}\n"
 "{\n"
 "{\n"
 "	#if {%1 <= 26}\n"
 "	#if {%1 <= 26}\n"
 "	{\n"
 "	{\n"
-"		#if {$gui[profile_tab] && $gui[index] < @gui_size_left{} && @gui_size_left{} > $gui[rows] / 3 - 6}\n"
+"		#if {$gui[profile_tab] >= 0 && $gui[index] < @gui_size_left{} && @gui_size_left{} > $gui[rows] / 3 - 6}\n"
 "		{\n"
 "		{\n"
 "			#math gui[index] $gui[index] + 1;\n"
 "			#math gui[index] $gui[index] + 1;\n"
 "			gui_draw_left\n"
 "			gui_draw_left\n"
@@ -704,5 +729,5 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#buffer down 1;\n"
 "		#buffer down 1;\n"
 "	}\n"
 "	}\n"
 "}\n"
 "}\n"
-"\n"
-"gui_init\n";
+
+"#delay 0 gui_init\n";

文件差异内容过多而无法显示
+ 430 - 224
src/help.c


+ 30 - 19
src/input.c

@@ -485,26 +485,28 @@ int check_key(char *input, int len)
 			}
 			}
 		}
 		}
 
 
-
-		if (!HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_SGA) || HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO) || gtd->ses->input->buf[0] == gtd->tintin_char)
+		if (gtd->macro_buf[0] < 32 || gtd->macro_buf[0] == 127)
 		{
 		{
-			for (cnt = 0 ; *cursor_table[cnt].fun != NULL ; cnt++)
+			if (!HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_SGA) || HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO) || gtd->ses->input->buf[0] == gtd->tintin_char)
 			{
 			{
-				if (*cursor_table[cnt].code)
+				for (cnt = 0 ; *cursor_table[cnt].fun != NULL ; cnt++)
 				{
 				{
-					if (!strcmp(gtd->macro_buf, cursor_table[cnt].code))
+					if (*cursor_table[cnt].code)
 					{
 					{
-						cursor_table[cnt].fun(gtd->ses, cursor_table[cnt].arg);
+						if (!strcmp(gtd->macro_buf, cursor_table[cnt].code))
+						{
+							cursor_table[cnt].fun(gtd->ses, cursor_table[cnt].arg);
 
 
-						gtd->macro_buf[0] = 0;
+							gtd->macro_buf[0] = 0;
 
 
-						pop_call();
-						return TRUE;
-					}
-					else if (!strncmp(gtd->macro_buf, cursor_table[cnt].code, strlen(gtd->macro_buf)))
-					{
-						pop_call();
-						return TRUE;
+							pop_call();
+							return TRUE;
+						}
+						else if (!strncmp(gtd->macro_buf, cursor_table[cnt].code, strlen(gtd->macro_buf)))
+						{
+							pop_call();
+							return TRUE;
+						}
 					}
 					}
 				}
 				}
 			}
 			}
@@ -775,6 +777,14 @@ void convert_meta(char *input, char *output, int eol)
 	{
 	{
 		switch (*pti)
 		switch (*pti)
 		{
 		{
+			case -1:
+				*pto++ = '\\';
+				*pto++ = 'x';
+				*pto++ = 'F';
+				*pto++ = 'F';
+				pti++;
+				break;
+
 			case ASCII_ESC:
 			case ASCII_ESC:
 				*pto++ = '\\';
 				*pto++ = '\\';
 				*pto++ = 'e';
 				*pto++ = 'e';
@@ -908,19 +918,19 @@ char *str_convert_meta(char *input, int eol)
 
 
 void echo_command(struct session *ses, char *line)
 void echo_command(struct session *ses, char *line)
 {
 {
-	char buffer[BUFFER_SIZE], output[BUFFER_SIZE];
+	char buffer[BUFFER_SIZE];
 
 
 	DEL_BIT(ses->telopts, TELOPT_FLAG_PROMPT);
 	DEL_BIT(ses->telopts, TELOPT_FLAG_PROMPT);
 
 
 	if (ses->check_output)
 	if (ses->check_output)
 	{
 	{
-		strcpy(output, ses->more_output);
+		strcpy(buffer, ses->more_output);
 
 
 		process_mud_output(ses, buffer, FALSE);
 		process_mud_output(ses, buffer, FALSE);
 	}
 	}
 	else
 	else
 	{
 	{
-		strcpy(output, "");
+		buffer[0] = 0;
 	}
 	}
 
 
 	if (ses->scroll->line != -1)
 	if (ses->scroll->line != -1)
@@ -946,7 +956,8 @@ void echo_command(struct session *ses, char *line)
 	}
 	}
 	else
 	else
 	{
 	{
-		if (strip_vt102_strlen(ses, output) == 0)
+
+		if (strip_vt102_strlen(ses, buffer) == 0)
 		{
 		{
 			return;
 			return;
 		}
 		}
@@ -1040,7 +1051,7 @@ void input_printf(char *format, ...)
 	char *buf;
 	char *buf;
 	va_list args;
 	va_list args;
 
 
-	if (!HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH))
+	if (!HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_HISTORYSEARCH) && !HAS_BIT(gtd->ses->input->flags, INPUT_FLAG_REDRAW))
 	{
 	{
 		if (!HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO) && gtd->ses->input->buf[0] != gtd->tintin_char)
 		if (!HAS_BIT(gtd->ses->telopts, TELOPT_FLAG_ECHO) && gtd->ses->input->buf[0] != gtd->tintin_char)
 		{
 		{

+ 82 - 2
src/line.c

@@ -25,6 +25,38 @@
 
 
 #include "tintin.h"
 #include "tintin.h"
 
 
+struct line_type
+{
+	char                  * name;
+	LINE                  * fun;
+	char                  * desc;
+};
+
+struct line_type line_table[] =
+{
+	{    "BACKGROUND",        line_background,     "Execute line without stealing session focus."   },
+	{    "BENCHMARK",         line_benchmark,      "Execute line and provide timing information."   },
+	{    "CAPTURE",           line_capture,        "Capture output in the given variable."          },
+	{    "CONVERT",           line_convert,        "Execute line in convert meta data mode."        },
+	{    "DEBUG",             line_debug,          "Execute line in debug mode."                    },
+	{    "GAG",               line_gag,            "Gag the next line."                             },
+	{    "IGNORE",            line_ignore,         "Execute line with triggers ignored."            },
+	{    "JSON",              line_json,           "Execute line with json conversion."             },
+	{    "LOCAL",             line_local,          "Execute line with local scope."                 },
+	{    "LOG",               line_log,            "Log the next line or given line."               },
+	{    "LOGMODE",           line_logmode,        "Execute line with given log mode."              },
+	{    "LOGVERBATIM",       line_logverbatim,    "Log the line as plain text verbatim."           },
+	{    "MSDP",              line_msdp,           "Execute line with msdp conversion."             },
+	{    "MULTISHOT",         line_multishot,      "Execute line creating multishot triggers."      },
+	{    "ONESHOT",           line_oneshot,        "Execute line creating oneshot triggers."        },
+	{    "QUIET",             line_quiet,          "Execute line with all system messages off."     },
+	{    "STRIP",             line_strip,          "Execute line with escape codes stripped."       },
+	{    "SUBSTITUTE",        line_substitute,     "Execute line with given substitution."          },
+	{    "VERBATIM",          line_verbatim,       "Execute line as plain text."                    },
+	{    "VERBOSE",           line_verbose,        "Execute line with all system messages on."      },
+	{    "",                  NULL,                ""                                               }
+};
+
 DO_COMMAND(do_line)
 DO_COMMAND(do_line)
 {
 {
 	int cnt;
 	int cnt;
@@ -205,7 +237,11 @@ DO_LINE(line_gag)
 			break;
 			break;
 	}
 	}
 
 
-	show_debug(ses, LIST_GAG, "#DEBUG LINE GAG {%s}", arg1);
+	if (ses->gagline < 0)
+	{
+		ses->gagline = 0;
+	}
+	show_debug(ses, LIST_GAG, "#DEBUG LINE GAG {%s} [%d]", arg1, ses->gagline);
 
 
 //	SET_BIT(ses->flags, SES_FLAG_GAG);
 //	SET_BIT(ses->flags, SES_FLAG_GAG);
 
 
@@ -462,7 +498,7 @@ DO_LINE(line_msdp)
 
 
 	if (*arg1 == 0)
 	if (*arg1 == 0)
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {STRIP} {command}.");
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {MSDP} {command}.");
 
 
 		return ses;
 		return ses;
 	}
 	}
@@ -474,6 +510,50 @@ DO_LINE(line_msdp)
 	return ses;
 	return ses;
 }
 }
 
 
+DO_LINE(line_json)
+{
+	arg = sub_arg_in_braces(ses, arg, arg1, GET_ONE, SUB_VAR|SUB_FUN);
+	arg = sub_arg_in_braces(ses, arg, arg2, GET_ALL, SUB_VAR|SUB_FUN);
+
+	if (*arg1 == 0)
+	{
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {JSON} {command}.");
+
+		return ses;
+	}
+
+	char *str_sub = str_alloc_stack(0);
+
+	struct listroot *root = ses->list[LIST_VARIABLE];
+	struct listnode *node = search_nest_node(root, arg1);
+
+	if (node)
+	{
+		if (node->root)
+		{
+			view_nest_node_json(node, &str_sub, 0, TRUE);
+
+//			print_lines(ses, SUB_NONE, "%s\n", str_sub);
+		}
+		else
+		{
+			sprintf(str_sub, "\"%s\"\n", node->arg2);
+		}
+	}
+	else
+	{
+		show_error(ses, LIST_COMMAND, "#LINE JSON {%s}: VARIABLE NOT FOUND.", arg1);
+	}
+
+	RESTRING(gtd->cmds[0], str_sub);
+
+	substitute(ses, arg2, str_sub, SUB_CMD);
+
+	ses = script_driver(ses, LIST_COMMAND, str_sub);
+
+	return ses;
+}
+	
 DO_LINE(line_multishot)
 DO_LINE(line_multishot)
 {
 {
 	unsigned int shots;
 	unsigned int shots;

+ 86 - 3
src/list.c

@@ -43,6 +43,7 @@ extern DO_ARRAY(array_insert);
 extern DO_ARRAY(array_numerate);
 extern DO_ARRAY(array_numerate);
 extern DO_ARRAY(array_order);
 extern DO_ARRAY(array_order);
 extern DO_ARRAY(array_reverse);
 extern DO_ARRAY(array_reverse);
+extern DO_ARRAY(array_refine);
 extern DO_ARRAY(array_set);
 extern DO_ARRAY(array_set);
 extern DO_ARRAY(array_shuffle);
 extern DO_ARRAY(array_shuffle);
 extern DO_ARRAY(array_simplify);
 extern DO_ARRAY(array_simplify);
@@ -77,6 +78,7 @@ struct array_type array_table[] =
 	{     "NUMERATE",         array_numerate,    "Turn a table into a list"                },
 	{     "NUMERATE",         array_numerate,    "Turn a table into a list"                },
 	{     "ORDER",            array_order,       "Sort a list table numerically"           },
 	{     "ORDER",            array_order,       "Sort a list table numerically"           },
 	{     "LENGTH",           array_size,        NULL                                      },
 	{     "LENGTH",           array_size,        NULL                                      },
+	{     "REFINE",           array_refine,      "Filter a list with given math"           },
 	{     "REVERSE",          array_reverse,     "Sort a list table in reverse order"      },
 	{     "REVERSE",          array_reverse,     "Sort a list table in reverse order"      },
 	{     "SET",              array_set,         "Change a list item at given index"       },
 	{     "SET",              array_set,         "Change a list item at given index"       },
 	{     "SHUFFLE",          array_shuffle,     "Sort a list table in random order"       },
 	{     "SHUFFLE",          array_shuffle,     "Sort a list table in random order"       },
@@ -263,6 +265,13 @@ DO_ARRAY(array_create)
 
 
 	arg = buf;
 	arg = buf;
 
 
+	if (*arg == 0)
+	{
+		set_nest_node_ses(ses, arg1, "");
+
+		return ses;
+	}
+
 	if (list->root)
 	if (list->root)
 	{
 	{
 		free_list(list->root);
 		free_list(list->root);
@@ -284,13 +293,15 @@ DO_ARRAY(array_create)
 
 
 			if (*str == COMMAND_SEPARATOR)
 			if (*str == COMMAND_SEPARATOR)
 			{
 			{
-				str++;
+				*str = ' ';
+//				str++;
 			}
 			}
 		}
 		}
 
 
 		if (*arg == COMMAND_SEPARATOR)
 		if (*arg == COMMAND_SEPARATOR)
 		{
 		{
-			arg++;
+			*arg = ' ';
+//			arg++;
 		}
 		}
 	}
 	}
 	return ses;
 	return ses;
@@ -411,8 +422,11 @@ DO_ARRAY(array_filter)
 		return ses;
 		return ses;
 	}
 	}
 
 
-	if (list->root)
+	if (list->root && list->root->used)
 	{
 	{
+		int numerate = atoi(list->root->list[0]->arg1) == 1 && atoi(list->root->list[list->root->used - 1]->arg1) == list->root->used;
+		int found = 0;
+
 		if (*arg1)
 		if (*arg1)
 		{
 		{
 			for (index = 0 ; index < list->root->used ; index++)
 			for (index = 0 ; index < list->root->used ; index++)
@@ -420,6 +434,7 @@ DO_ARRAY(array_filter)
 				if (!match(ses, list->root->list[index]->arg2, arg1, SUB_NONE))
 				if (!match(ses, list->root->list[index]->arg2, arg1, SUB_NONE))
 				{
 				{
 					delete_index_list(list->root, index--);
 					delete_index_list(list->root, index--);
+					found = 1;
 				}
 				}
 			}
 			}
 		}
 		}
@@ -431,9 +446,14 @@ DO_ARRAY(array_filter)
 				if (match(ses, list->root->list[index]->arg2, arg2, SUB_NONE))
 				if (match(ses, list->root->list[index]->arg2, arg2, SUB_NONE))
 				{
 				{
 					delete_index_list(list->root, index--);
 					delete_index_list(list->root, index--);
+					found = 1;
 				}
 				}
 			}
 			}
 		}
 		}
+		if (found && numerate)
+		{
+			array_numerate(ses, list, arg, var, arg1, arg2);
+		}
 	}
 	}
 
 
 	return ses;
 	return ses;
@@ -685,6 +705,69 @@ DO_ARRAY(array_order)
 	return ses;
 	return ses;
 }
 }
 
 
+DO_ARRAY(array_refine)
+{
+	char arg3[BUFFER_SIZE];
+	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} REFINE {keep} {remove}");
+
+		return ses;
+	}
+
+	if (list->root && list->root->used)
+	{
+		int numerate = atoi(list->root->list[0]->arg1) == 1 && atoi(list->root->list[list->root->used - 1]->arg1) == list->root->used;
+		int found = 0;
+
+		if (*arg1)
+		{
+			for (index = 0 ; index < list->root->used ; index++)
+			{
+				RESTRING(gtd->cmds[0], list->root->list[index]->arg2);
+
+				substitute(ses, arg1, arg3, SUB_CMD);
+
+				if (!get_number(ses, arg3))
+				{
+					delete_index_list(list->root, index--);
+					found = 1;
+				}
+			}
+		}
+
+		if (*arg2)
+		{
+			for (index = 0 ; index < list->root->used ; index++)
+			{
+				RESTRING(gtd->cmds[0], list->root->list[index]->arg2);
+
+				substitute(ses, arg2, arg3, SUB_CMD);
+
+//				printf("debug: (%s) (%d)\n", arg3, (int) get_number(ses, arg3));
+
+				if (get_number(ses, arg3))
+				{
+					delete_index_list(list->root, index--);
+					found = 1;
+				}
+			}
+		}
+
+		if (found && numerate)
+		{
+			array_numerate(ses, list, arg, var, arg1, arg2);
+		}
+	}
+
+	return ses;
+}
+
 DO_ARRAY(array_reverse)
 DO_ARRAY(array_reverse)
 {
 {
 	struct listroot *toor;
 	struct listroot *toor;

+ 15 - 7
src/main.c

@@ -79,12 +79,16 @@ void winch_handler(int signal)
 	gtd->time_session = gtd->time;
 	gtd->time_session = gtd->time;
 }
 }
 
 
-
 void abort_handler(int signal)
 void abort_handler(int signal)
 {
 {
 	syserr_fatal(signal, "abort_handler");
 	syserr_fatal(signal, "abort_handler");
 }
 }
 
 
+void fpe_handler(int signal)
+{
+	syserr_fatal(signal, "fpe_handler");
+}
+
 void child_handler(int signal)
 void child_handler(int signal)
 {
 {
 	return;
 	return;
@@ -166,7 +170,12 @@ int main(int argc, char **argv)
 
 
 	if (signal(SIGABRT, abort_handler) == BADSIG)
 	if (signal(SIGABRT, abort_handler) == BADSIG)
 	{
 	{
-		syserr_fatal(-1, "signal SIGTERM");
+		syserr_fatal(-1, "signal SIGABRT");
+	}
+
+	if (signal(SIGFPE, fpe_handler) == BADSIG)
+	{
+		syserr_fatal(-1, "signal SIGFPE");
 	}
 	}
 
 
 /*	if (signal(SIGCHLD, child_handler) == BADSIG)
 /*	if (signal(SIGCHLD, child_handler) == BADSIG)
@@ -788,12 +797,12 @@ void syserr_signal(int signal, char *msg)
 
 
 void syserr_fatal(int signal, char *msg)
 void syserr_fatal(int signal, char *msg)
 {
 {
-	char buf[256], errstr[128];
+	char errstr[128];
 	static char crashed = FALSE;
 	static char crashed = FALSE;
 
 
 	if (crashed++)
 	if (crashed++)
 	{
 	{
-		print_stdout(0, 0, "syserr_fatal(crashed)");
+		print_stdout(0, 0, "\e[1;36msyserr_fatal(crashed) \e[0m\n");
 
 
 		fflush(NULL);
 		fflush(NULL);
 
 
@@ -833,9 +842,8 @@ void syserr_fatal(int signal, char *msg)
 
 
 	dump_stack();
 	dump_stack();
 
 
-	sprintf(buf, "\n\e[1;31mFATAL ERROR \e[1;32m%s %s\e[0m\n", msg, errstr);
-
-	print_stdout(0, 0, "%s", buf);
+	print_stdout(0, 0, "%*s", (unsigned char) gtd->screen->cols, "");
+	print_stdout(0, 0, "\n\e[1;31mFATAL ERROR \e[1;32m%s %s\e[0m\n", (unsigned char) gtd->screen->cols, "", msg, errstr);
 
 
 	reset_daemon();
 	reset_daemon();
 
 

文件差异内容过多而无法显示
+ 425 - 208
src/mapper.c


+ 5 - 6
src/math.c

@@ -157,7 +157,7 @@ unsigned long long get_ulong(struct session *ses, char *str)
 int get_ellipsis(struct session *ses, unsigned int size, char *name, int *min, int *max)
 int get_ellipsis(struct session *ses, unsigned int size, char *name, int *min, int *max)
 {
 {
 	size_t len;
 	size_t len;
-	unsigned long long range;
+	char strmin[BUFFER_SIZE], strmax[BUFFER_SIZE];
 
 
 	push_call("get_ellipsis(%p,%d,%p,%p,%p)",ses,size,name,min,max);
 	push_call("get_ellipsis(%p,%d,%p,%p,%p)",ses,size,name,min,max);
 
 
@@ -167,18 +167,17 @@ int get_ellipsis(struct session *ses, unsigned int size, char *name, int *min, i
 	{
 	{
 		strcpy(name + len, "-1");
 		strcpy(name + len, "-1");
 	}
 	}
-/*
+
 	sscanf(name, "%[^.]..%[^.]", strmin, strmax);
 	sscanf(name, "%[^.]..%[^.]", strmin, strmax);
 
 
 	*min = get_number(ses, strmin);
 	*min = get_number(ses, strmin);
 	*max = get_number(ses, strmax);
 	*max = get_number(ses, strmax);
-*/
-
-	range = get_ulong(ses, name);
+/*
+	unsigned long long range = get_ulong(ses, name);
 
 
 	*min = (int) (range / 1000000000 - 100000000);
 	*min = (int) (range / 1000000000 - 100000000);
 	*max = (int) (range % 1000000000 - 100000000);
 	*max = (int) (range % 1000000000 - 100000000);
-
+*/
 	*min = *min > 0 ? *min - 1 : size + *min;
 	*min = *min > 0 ? *min - 1 : size + *min;
 	*max = *max > 0 ? *max - 1 : size + *max;
 	*max = *max > 0 ? *max - 1 : size + *max;
 
 

+ 6 - 0
src/misc.c

@@ -166,6 +166,12 @@ DO_COMMAND(do_test)
 
 
 	if (!strcmp(arg1, "bla"))
 	if (!strcmp(arg1, "bla"))
 	{
 	{
+		int a = 1;
+		int b = 0;
+		int c = a / b;
+
+		printf("%d", c);
+
 		tintin_printf(ses, "len: %d", strip_color_strlen(ses, arg));
 		tintin_printf(ses, "len: %d", strip_color_strlen(ses, arg));
 //		tintin_printf(ses, "<118>\ufffd", arg2);
 //		tintin_printf(ses, "<118>\ufffd", arg2);
 	}
 	}

+ 4 - 3
src/msdp.c

@@ -705,13 +705,13 @@ void write_msdp_to_descriptor(struct session *ses, struct port_data *buddy, char
 	}
 	}
 	else
 	else
 	{
 	{
-		length = msdp2json((unsigned char *) src, length, out);
+		length = msdp2gmcp((unsigned char *) src, length, out);
 
 
 		port_telnet_printf(ses, buddy, length, "%s", out);
 		port_telnet_printf(ses, buddy, length, "%s", out);
 	}
 	}
 }
 }
 
 
-int msdp2json(unsigned char *src, int srclen, char *out)
+int msdp2gmcp(unsigned char *src, int srclen, char *out)
 {
 {
 	char *pto;
 	char *pto;
 	int i, nest, last;
 	int i, nest, last;
@@ -828,7 +828,7 @@ int msdp2json(unsigned char *src, int srclen, char *out)
 	return pto - out;
 	return pto - out;
 }
 }
 
 
-int json2msdp(unsigned char *src, int srclen, char *out)
+int gmcp2msdp(unsigned char *src, int srclen, char *out)
 {
 {
 	char *pto;
 	char *pto;
 	int i, nest, last, type, state[100];
 	int i, nest, last, type, state[100];
@@ -1098,3 +1098,4 @@ int tintin2msdp(char *str, char *out)
 
 
 	return pto - out;
 	return pto - out;
 }
 }
+

+ 77 - 2
src/nest.c

@@ -144,6 +144,11 @@ struct listnode *search_nest_node(struct listroot *root, char *variable)
 
 
 	arg = get_arg_to_brackets(root->ses, variable, name);
 	arg = get_arg_to_brackets(root->ses, variable, name);
 
 
+	if (*name == 0)
+	{
+		arg = get_arg_in_brackets(root->ses, arg, name);
+	}
+
 	while (root && *arg)
 	while (root && *arg)
 	{
 	{
 		root = search_nest_root(root, name);
 		root = search_nest_root(root, name);
@@ -400,6 +405,11 @@ int get_nest_size(struct listroot *root, char *variable)
 		}
 		}
 	}
 	}
 
 
+	if (*name == 0)
+	{
+		arg = get_arg_in_brackets(root->ses, arg, name);
+	}
+
 	while (root && *name)
 	while (root && *name)
 	{
 	{
 		// Handle regex queries
 		// Handle regex queries
@@ -482,6 +492,11 @@ int get_nest_size_index(struct listroot *root, char *variable, char **result)
 		}
 		}
 	}
 	}
 
 
+	if (*name == 0)
+	{
+		arg = get_arg_in_brackets(root->ses, arg, name);
+	}
+
 	while (root && *name)
 	while (root && *name)
 	{
 	{
 		// Handle regex queries
 		// Handle regex queries
@@ -567,6 +582,11 @@ int get_nest_size_key(struct listroot *root, char *variable, char **result)
 		}
 		}
 	}
 	}
 
 
+	if (*name == 0)
+	{
+		arg = get_arg_in_brackets(root->ses, arg, name);
+	}
+
 	while (root && *name)
 	while (root && *name)
 	{
 	{
 		// Handle regex queries
 		// Handle regex queries
@@ -624,7 +644,6 @@ int get_nest_size_key(struct listroot *root, char *variable, char **result)
 				}
 				}
 			}
 			}
 		}
 		}
-
 		root = search_nest_root(root, name);
 		root = search_nest_root(root, name);
 
 
 		if (root)
 		if (root)
@@ -659,7 +678,7 @@ int get_nest_size_val(struct listroot *root, char *variable, char **result)
 		{
 		{
 			for (index = 0 ; index < root->used ; index++)
 			for (index = 0 ; index < root->used ; index++)
 			{
 			{
-				str_cat_printf(result, "{%s}", root->list[index]->arg1);
+				str_cat_printf(result, "{%s}", root->list[index]->arg2);
 			}
 			}
 			return root->used + 1;
 			return root->used + 1;
 		}
 		}
@@ -673,6 +692,11 @@ int get_nest_size_val(struct listroot *root, char *variable, char **result)
 		}
 		}
 	}
 	}
 
 
+	if (*name == 0)
+	{
+		arg = get_arg_in_brackets(root->ses, arg, name);
+	}
+
 	while (root && *name)
 	while (root && *name)
 	{
 	{
 		// Handle regex queries
 		// Handle regex queries
@@ -983,6 +1007,57 @@ void view_nest_node(struct listnode *node, char **str_result, int nest, int init
 	}
 	}
 }
 }
 
 
+void view_nest_node_json(struct listnode *node, char **str_result, int nest, int initialize)
+{
+	if (initialize == TRUE)
+	{
+		str_cpy(str_result, "");
+	}
+
+	if (node->root == NULL)
+	{
+		str_cat_printf(str_result, "\"%s\"", node->arg2);
+	}
+	else
+	{
+		struct listroot *root = node->root;
+		int i;
+
+		if (initialize)
+		{
+			str_cat_printf(str_result, "%s{\n", indent(nest));
+		}
+		else
+		{
+			str_cat_printf(str_result, "\n%s{\n", indent(nest));
+		}
+
+		nest++;
+
+		for (i = 0 ; i < root->used ; i++)
+		{
+			if (i)
+			{
+				str_cat_printf(str_result, ",\n");
+			}
+			str_cat_printf(str_result, "%s\"%s\" : ", indent(nest), root->list[i]->arg1);
+
+			view_nest_node_json(root->list[i], str_result, nest, FALSE);
+		}
+
+		nest--;
+
+		if (initialize)
+		{
+			str_cat_printf(str_result, "\n%s}\n", indent(nest), "");
+		}
+		else
+		{
+			str_cat_printf(str_result, "\n%s}", indent(nest), "");
+		}
+	}
+}
+
 struct listnode *set_nest_node_ses(struct session *ses, char *arg1, char *format, ...)
 struct listnode *set_nest_node_ses(struct session *ses, char *arg1, char *format, ...)
 {
 {
 	struct listnode *node;
 	struct listnode *node;

+ 12 - 4
src/net.c

@@ -102,7 +102,7 @@ int wait_on_connect(struct session *ses, int sock, int connect_error)
 
 
 int connect_mud(struct session *ses, char *host, char *port)
 int connect_mud(struct session *ses, char *host, char *port)
 {
 {
-	int sock, error;
+	int sock, error, optval;
 	struct addrinfo *address;
 	struct addrinfo *address;
 	static struct addrinfo hints;
 	static struct addrinfo hints;
 	char ip[100];
 	char ip[100];
@@ -145,10 +145,11 @@ int connect_mud(struct session *ses, char *host, char *port)
 		return -1;
 		return -1;
 	}
 	}
 
 
-	int optval = 1;
+	optval = 1;
+
 	if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0)
 	if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0)
 	{
 	{
-		syserr_printf(ses, "connect_mud: unable to use tcp keepalive, continuing without");
+		syserr_printf(ses, "connect_mud: setsockopt:");
 	}
 	}
 
 
 	ses->connect_error = connect(sock, address->ai_addr, address->ai_addrlen);
 	ses->connect_error = connect(sock, address->ai_addr, address->ai_addrlen);
@@ -286,7 +287,12 @@ void write_line_mud(struct session *ses, char *line, int size)
 		}
 		}
 		else
 		else
 		{
 		{
-			tintin_printf2(ses, "#NO SESSION ACTIVE. USE: %csession {name} {host} {port} TO START ONE.", gtd->tintin_char);
+			check_all_events(ses, SUB_SEC|EVENT_FLAG_INPUT, 0, 2, "NO SESSION ACTIVE", line, ntos(size));
+
+			if (!check_all_events(ses, SUB_SEC|EVENT_FLAG_GAG, 0, 2, "GAG NO SESSION ACTIVE", line, ntos(size)))
+			{
+				tintin_printf2(ses, "#NO SESSION ACTIVE. USE: %csession {name} {host} {port} TO START ONE.", gtd->tintin_char);
+			}
 		}
 		}
 		pop_call();
 		pop_call();
 		return;
 		return;
@@ -533,6 +539,8 @@ void readmud(struct session *ses)
 			}
 			}
 			else
 			else
 			{
 			{
+				// clean this up some time.
+
 				strcpy(linebuf, line);
 				strcpy(linebuf, line);
 			}
 			}
 		}
 		}

+ 17 - 4
src/parse.c

@@ -37,8 +37,8 @@ int case_table[256] =
 	 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
 	 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
 	 64,
 	 64,
 	 65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
 	 65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
-	 91,  92,  93,  94,
-	 95,  96,
+	 91,  92,  93,  94,  95,
+	 96,
 	 65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
 	 65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,  90,
 	123, 124, 125, 126, 127,
 	123, 124, 125, 126, 127,
 	128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
 	128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
@@ -51,6 +51,20 @@ int case_table[256] =
 	240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
 	240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255
 };
 };
 
 
+int is_abbrev_cmp(char *str1, char *str2)
+{
+	while (TRUE)
+	{
+		if (*str1 == 0 || case_table[(int) *str1] != case_table[(int) *str2])
+		{
+			return (case_table[(int) *str1] > case_table[(int) *str2]) - (case_table[(int) *str1] < case_table[(int) *str2]);
+		}
+		str1++;
+		str2++;
+	}
+}
+
+
 int is_abbrev(char *str1, char *str2)
 int is_abbrev(char *str1, char *str2)
 {
 {
 	char buf[NUMBER_SIZE], *str3;
 	char buf[NUMBER_SIZE], *str3;
@@ -467,7 +481,7 @@ struct session *parse_tintin_command(struct session *ses, char *input)
 
 
 	if (*line == '!')
 	if (*line == '!')
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#!%s %s", line + 1, input);
+		show_message(ses, LIST_COMMAND, "#!%s %s", line + 1, input);
 
 
 		return ses;
 		return ses;
 	}
 	}
@@ -786,7 +800,6 @@ char *get_arg_stop_spaces(struct session *ses, char *string, char *result, int f
 			continue;
 			continue;
 		}
 		}
 
 
-
 		if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
 		if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
 		{
 		{
 			*pto++ = *pti++;
 			*pto++ = *pti++;

+ 106 - 129
src/regex.c

@@ -93,7 +93,7 @@ DO_COMMAND(do_regexp)
 int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, int option, int flag)
 int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, int option, int flag)
 {
 {
 	pcre *regex;
 	pcre *regex;
-	int i, j, matches, match[303];
+	int i, j, matches;
 
 
 	if (nodepcre == NULL)
 	if (nodepcre == NULL)
 	{
 	{
@@ -109,7 +109,7 @@ int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, in
 		return FALSE;
 		return FALSE;
 	}
 	}
 
 
-	matches = pcre_exec(regex, NULL, str, strlen(str), 0, 0, match, 303);
+	matches = pcre_exec(regex, NULL, str, strlen(str), 0, 0, gtd->match, 303);
 
 
 	if (matches <= 0)
 	if (matches <= 0)
 	{
 	{
@@ -127,12 +127,13 @@ int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, in
 		case REGEX_FLAG_CMD:
 		case REGEX_FLAG_CMD:
 			for (i = matches ; i < gtd->cmdc ; i++)
 			for (i = matches ; i < gtd->cmdc ; i++)
 			{
 			{
-				gtd->cmds[i] = restring(gtd->cmds[i], "");
+				*gtd->cmds[i] = 0;
+//				gtd->cmds[i] = restring(gtd->cmds[i], "");
 			}
 			}
 
 
 			for (i = 0 ; i < matches ; i++)
 			for (i = 0 ; i < matches ; i++)
 			{
 			{
-				gtd->cmds[i] = restringf(gtd->cmds[i], "%.*s", match[i*2+1] - match[i*2], &str[match[i*2]]);
+				gtd->cmds[i] = restringf(gtd->cmds[i], "%.*s", gtd->match[i*2+1] - gtd->match[i*2], &str[gtd->match[i*2]]);
 			}
 			}
 			gtd->cmdc = matches;
 			gtd->cmdc = matches;
 			break;
 			break;
@@ -140,14 +141,15 @@ int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, in
 		case REGEX_FLAG_CMD + REGEX_FLAG_FIX:
 		case REGEX_FLAG_CMD + REGEX_FLAG_FIX:
 			for (i = matches ; i < gtd->cmdc ; i++)
 			for (i = matches ; i < gtd->cmdc ; i++)
 			{
 			{
-				gtd->cmds[i] = restring(gtd->cmds[i], "");
+				*gtd->cmds[i] = 0;
+//				gtd->cmds[i] = restring(gtd->cmds[i], "");
 			}
 			}
 
 
 			for (i = 0 ; i < matches ; i++)
 			for (i = 0 ; i < matches ; i++)
 			{
 			{
 				j = gtd->args[i];
 				j = gtd->args[i];
 
 
-				gtd->cmds[j] = restringf(gtd->cmds[j], "%.*s", match[i*2+1] - match[i*2], &str[match[i*2]]);
+				gtd->cmds[j] = restringf(gtd->cmds[j], "%.*s", gtd->match[i*2+1] - gtd->match[i*2], &str[gtd->match[i*2]]);
 			}
 			}
 			gtd->cmdc = matches;
 			gtd->cmdc = matches;
 			break;
 			break;
@@ -155,12 +157,13 @@ int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, in
 		case REGEX_FLAG_ARG:
 		case REGEX_FLAG_ARG:
 			for (i = matches ; i < gtd->varc ; i++)
 			for (i = matches ; i < gtd->varc ; i++)
 			{
 			{
-				gtd->vars[i] = restring(gtd->vars[i], "");
+				*gtd->vars[i] = 0;
+//				gtd->vars[i] = restring(gtd->vars[i], "");
 			}
 			}
 
 
 			for (i = 0 ; i < matches ; i++)
 			for (i = 0 ; i < matches ; i++)
 			{
 			{
-				gtd->vars[i] = restringf(gtd->vars[i], "%.*s", match[i*2+1] - match[i*2], &str[match[i*2]]);
+				gtd->vars[i] = restringf(gtd->vars[i], "%.*s", gtd->match[i*2+1] - gtd->match[i*2], &str[gtd->match[i*2]]);
 			}
 			}
 			gtd->varc = matches;
 			gtd->varc = matches;
 			break;
 			break;
@@ -168,14 +171,15 @@ int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, in
 		case REGEX_FLAG_ARG + REGEX_FLAG_FIX:
 		case REGEX_FLAG_ARG + REGEX_FLAG_FIX:
 			for (i = matches ; i < gtd->varc ; i++)
 			for (i = matches ; i < gtd->varc ; i++)
 			{
 			{
-				gtd->vars[i] = restring(gtd->vars[i], "");
+				*gtd->vars[i] = 0;
+//				gtd->vars[i] = restring(gtd->vars[i], "");
 			}
 			}
 
 
 			for (i = 0 ; i < matches ; i++)
 			for (i = 0 ; i < matches ; i++)
 			{
 			{
 				j = gtd->args[i];
 				j = gtd->args[i];
 
 
-				gtd->vars[j] = restringf(gtd->vars[j], "%.*s", match[i*2+1] - match[i*2], &str[match[i*2]]);
+				gtd->vars[j] = restringf(gtd->vars[j], "%.*s", gtd->match[i*2+1] - gtd->match[i*2], &str[gtd->match[i*2]]);
 			}
 			}
 			gtd->varc = matches;
 			gtd->varc = matches;
 			break;
 			break;
@@ -302,40 +306,43 @@ int get_regex_range(char *in, char *out, int *var, int *arg)
 				continue;
 				continue;
 
 
 			case 'a':
 			case 'a':
-				pto += sprintf(pto, "([^\\0]");
+				pto += sprintf(pto, "%s", "([^\\0]");
 				break;
 				break;
 			case 'A':
 			case 'A':
-				pto += sprintf(pto, "(\\n");
+				pto += sprintf(pto, "%s", "(\\n");
+				break;
+			case 'c':
+				pto += sprintf(pto, "%s", "((?:\\e\\[[0-9;]*m)");
 				break;
 				break;
 			case 'd':
 			case 'd':
-				pto += sprintf(pto, "([0-9]");
+				pto += sprintf(pto, "%s", "([0-9]");
 				break;
 				break;
 			case 'D':
 			case 'D':
-				pto += sprintf(pto, "([^0-9]");
+				pto += sprintf(pto, "%s", "([^0-9]");
 				break;
 				break;
 			case 'p':
 			case 'p':
-				pto += sprintf(pto, "([\\x20-\\xfe]");
+				pto += sprintf(pto, "%s", "([\\x20-\\xfe]");
 				break;
 				break;
 			case 'P':
 			case 'P':
-				pto += sprintf(pto, "([^\\x20-\\xfe]");
+				pto += sprintf(pto, "%s", "([^\\x20-\\xfe]");
 				break;
 				break;
 			case 's':
 			case 's':
-				pto += sprintf(pto, "(\\s");
+				pto += sprintf(pto, "%s", "(\\s");
 				break;
 				break;
 			case 'S':
 			case 'S':
-				pto += sprintf(pto, "(\\S");
+				pto += sprintf(pto, "%s", "(\\S");
 				break;
 				break;
 			case 'u':
 			case 'u':
-				pto += sprintf(pto, "((?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})");
+				pto += sprintf(pto, "%s", "((?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})");
 				break;
 				break;
 			case 'U':
 			case 'U':
-				pto += sprintf(pto, "([\\x00-\\x7F\\xFF]");
+				pto += sprintf(pto, "%s", "([\\x00-\\x7F\\xFF]");
 				break;
 				break;
 			case 'w':
 			case 'w':
-				pto += sprintf(pto, "([a-zA-Z0-9_]");
+				pto += sprintf(pto, "%s", "(\\w");
 				break;
 				break;
 			case 'W':
 			case 'W':
-				pto += sprintf(pto, "([^a-zA-Z0-9_]");
+				pto += sprintf(pto, "%s", "(\\W");
 				break;
 				break;
 
 
 			default:
 			default:
@@ -405,6 +412,7 @@ int tintin_regexp_check(struct session *ses, char *exp)
 
 
 					case 'a':
 					case 'a':
 					case 'A':
 					case 'A':
+					case 'c':
 					case 'd':
 					case 'd':
 					case 'D':
 					case 'D':
 					case 'i':
 					case 'i':
@@ -429,6 +437,7 @@ int tintin_regexp_check(struct session *ses, char *exp)
 						{
 						{
 							case 'a':
 							case 'a':
 							case 'A':
 							case 'A':
+							case 'c':
 							case 'd':
 							case 'd':
 							case 'D':
 							case 'D':
 							case 'p':
 							case 'p':
@@ -559,48 +568,47 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 						arg = is_digit(pti[2]) ? (pti[1] - '0') * 10 + (pti[2] - '0') : pti[1] - '0';
 						arg = is_digit(pti[2]) ? (pti[1] - '0') * 10 + (pti[2] - '0') : pti[1] - '0';
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += is_digit(pti[2]) ? 3 : 2;
 						pti += is_digit(pti[2]) ? 3 : 2;
-						strcpy(pto, *pti == 0 ? "(.*)" : "(.*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.*)" : "(.*?)");
 						break;
 						break;
 
 
 					case 'a':
 					case 'a':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^\\0]*)" : "([^\\0]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([^\\0]*)" : "([^\\0]*?)");
 						break;
 						break;
 
 
 					case 'A':
 					case 'A':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\n*)" : "(\\n*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\n*)" : "(\\n*?)");
+						break;
+
+					case 'c':
+						gtd->args[next_arg(var)] = next_arg(arg);
+						pti += 2;
+						pto += sprintf(pto, "%s", *pti == 0 ? "((?:\\e\\[[0-9;]*m)*)" : "((?:\\e\\[[0-9;]*m)*?)");
 						break;
 						break;
 
 
 					case 'd':
 					case 'd':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([0-9]*)" : "([0-9]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([0-9]*)" : "([0-9]*?)");
 						break;
 						break;
 
 
 					case 'D':
 					case 'D':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^0-9]*)" : "([^0-9]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([^0-9]*)" : "([^0-9]*?)");
 						break;
 						break;
 
 
 					case 'i':
 					case 'i':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, "(?i)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(?i)");
 						break;
 						break;
 
 
 					case 'I':
 					case 'I':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, "(?-i)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(?-i)");
 						break;
 						break;
 
 
 					case 'p':
 					case 'p':
@@ -618,51 +626,44 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 					case 's':
 					case 's':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\s*)" : "(\\s*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\s*)" : "(\\s*?)");
 						break;
 						break;
 
 
 					case 'S':
 					case 'S':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\S*)" : "(\\S*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\S*)" : "(\\S*?)");
 						break;
 						break;
 
 
 					case 'u':
 					case 'u':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "((?:[\\x00-\\x7F|\\xC0-\\xFE][\\x80-\\xC0]{1,3})*)" : "((?:[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "((?:[\\x00-\\x7F|\\xC0-\\xFE][\\x80-\\xC0]{1,3})*)" : "((?:[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*?)");
 						break;
 						break;
 
 
 					case 'U':
 					case 'U':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(^[\\xF5-\\xFF]*)" : "([\\xF5-\\xFF]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(^[\\xF5-\\xFF]*)" : "([\\xF5-\\xFF]*?)");
 						break;
 						break;
 
 
 
 
 					case 'w':
 					case 'w':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([a-zA-Z]*)" : "([a-zA-Z]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\w*)" : "(\\w*?)");
 						break;
 						break;
 
 
 					case 'W':
 					case 'W':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^a-zA-Z]*)" : "([^a-zA-Z]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\W*)" : "(\\W*?)");
 						break;
 						break;
 
 
 					case '*':
 					case '*':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(.*)" : "(.*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.*)" : "(.*?)");
 						break;
 						break;
 
 
 					case '+':
 					case '+':
@@ -678,15 +679,13 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 					case '.':
 					case '.':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, "(.)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(.)");
 						break;
 						break;
 
 
 					case '?':
 					case '?':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(.?)" : "(.?" "?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.?)" : "(.?" "?)");
 						break;
 						break;
 
 
 					case '!':
 					case '!':
@@ -694,28 +693,29 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 						{
 						{
 							case 'a':
 							case 'a':
 								gtd->args[next_arg(var)] = next_arg(arg);
 								gtd->args[next_arg(var)] = next_arg(arg);
-								pti += 2;
-								strcpy(pto, *pti == 0 ? "[^\\0]*" : "[^\\0]*?");
-								pto += strlen(pto);
+								pti += 3;
+								pto += sprintf(pto, "%s", *pti == 0 ? "[^\\0]*" : "[^\\0]*?");
 								break;
 								break;
 
 
 							case 'A':
 							case 'A':
 								gtd->args[next_arg(var)] = next_arg(arg);
 								gtd->args[next_arg(var)] = next_arg(arg);
-								pti += 2;
-								strcpy(pto, *pti == 0 ? "\\n*" : "\\n*?");
-								pto += strlen(pto);
+								pti += 3;
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\n*" : "\\n*?");
+								break;
+
+							case 'c':
+								pti += 3;
+								pto += sprintf(pto, "%s", *pti == 0 ? "(?:\\e\\[[0-9;]*m)*" : "(?:\\e\\[[0-9;]*m)*?");
 								break;
 								break;
 
 
 							case 'd':
 							case 'd':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[0-9]*" : "[0-9]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[0-9]*" : "[0-9]*?");
 								break;
 								break;
 
 
 							case 'D':
 							case 'D':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[^0-9]*" : "[^0-9]*?");
-									pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[^0-9]*" : "[^0-9]*?");
 								break;
 								break;
 
 
 							case 'p':
 							case 'p':
@@ -730,52 +730,44 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 
 
 							case 's':
 							case 's':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "\\s*" : "\\s*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\s*" : "\\s*?");
 								break;
 								break;
 
 
 							case 'S':
 							case 'S':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "\\S*" : "\\S*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\S*" : "\\S*?");
 								break;
 								break;
 
 
 							case 'u':
 							case 'u':
 								gtd->args[next_arg(var)] = next_arg(arg);
 								gtd->args[next_arg(var)] = next_arg(arg);
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "(?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*" : "(?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "(?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*" : "(?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*?");
 								break;
 								break;
 
 
 							case 'U':
 							case 'U':
 								gtd->args[next_arg(var)] = next_arg(arg);
 								gtd->args[next_arg(var)] = next_arg(arg);
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[\\xF5-\\xFF]*" : "[\\xF5-\\xFF]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[\\xF5-\\xFF]*" : "[\\xF5-\\xFF]*?");
 								break;
 								break;
 
 
 							case 'w':
 							case 'w':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[a-zA-Z]*" : "[a-zA-Z]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\w*" : "\\w*?");
 								break;
 								break;
 
 
 							case 'W':
 							case 'W':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[^a-zA-Z]*" : "[^a-zA-Z]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\W*" : "\\W*?");
 								break;
 								break;
 
 
 							case '?':
 							case '?':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? ".?" : ".?" "?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? ".?" : ".?" "?");
 								break;
 								break;
 
 
 							case '*':
 							case '*':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? ".*" : ".*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? ".*" : ".*?");
 								break;
 								break;
 
 
 							case '+':
 							case '+':
@@ -785,8 +777,7 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 
 
 							case '.':
 							case '.':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, ".");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", ".");
 								break;
 								break;
 
 
 							case '{':
 							case '{':
@@ -949,32 +940,32 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 					case '8':
 					case '8':
 					case '9':
 					case '9':
 						pti += is_digit(pti[2]) ? 3 : 2;
 						pti += is_digit(pti[2]) ? 3 : 2;
-						strcpy(pto, *pti == 0 ? "(.*)" : "(.*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.*)" : "(.*?)");
+						break;
+
+					case 'c':
+						pti += 2;
+						pto += sprintf(pto, "%s", *pti == 0 ? "((?:\\e\\[[0-9;]*m)*)" : "((?:\\e\\[[0-9;]*m)*?)");
 						break;
 						break;
 
 
 					case 'd':
 					case 'd':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([0-9]*)" : "([0-9]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([0-9]*)" : "([0-9]*?)");
 						break;
 						break;
 
 
 					case 'D':
 					case 'D':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^0-9]*)" : "([^0-9]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([^0-9]*)" : "([^0-9]*?)");
 						break;
 						break;
 
 
 					case 'i':
 					case 'i':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, "(?i)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(?i)");
 						break;
 						break;
 
 
 					case 'I':
 					case 'I':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, "(?-i)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(?-i)");
 						break;
 						break;
 
 
 					case 'p':
 					case 'p':
@@ -989,50 +980,42 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 						
 						
 					case 's':
 					case 's':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\s*)" : "(\\s*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\s*)" : "(\\s*?)");
 						break;
 						break;
 
 
 					case 'S':
 					case 'S':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\S*)" : "(\\S*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\S*)" : "(\\S*?)");
 						break;
 						break;
 
 
 					case 'u':
 					case 'u':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "((?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*)" : "((?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "((?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*)" : "((?:[\\x00-\\x7F]|[\\xC0-\\xFE][\\x80-\\xC0]{1,3})*?)");
 						break;
 						break;
 
 
 					case 'U':
 					case 'U':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([\\xF5-\\xFF]*)" : "([\\xF5-\\xFF]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([\\xF5-\\xFF]*)" : "([\\xF5-\\xFF]*?)");
 						break;
 						break;
 
 
 					case 'w':
 					case 'w':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([a-zA-Z]*)" : "([a-zA-Z]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\w*)" : "(\\w*?)");
 						break;
 						break;
 
 
 					case 'W':
 					case 'W':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^a-zA-Z]*)" : "([^a-zA-Z]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\W*)" : "(\\W*?)");
 						break;
 						break;
 
 
 					case '?':
 					case '?':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(.?)" : "(.?" "?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.?)" : "(.?" "?)");
 						break;
 						break;
 
 
 					case '*':
 					case '*':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(.*)" : "(.*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.*)" : "(.*?)");
 						break;
 						break;
 
 
 					case '+':
 					case '+':
@@ -1042,8 +1025,7 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 
 
 					case '.':
 					case '.':
 						pti += 2;
 						pti += 2;
-						strcpy(pto, "(.)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(.)");
 						break;
 						break;
 
 
 					case '%':
 					case '%':
@@ -1054,16 +1036,19 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 					case '!':
 					case '!':
 						switch (pti[2])
 						switch (pti[2])
 						{
 						{
+							case 'c':
+								pti += 3;
+								pto += sprintf(pto, "%s", *pti == 0 ? "(?:\\e\\[[0-9;]*m)*" : "(?:\\e\\[[0-9;]*m)*?");
+								break;
+
 							case 'd':
 							case 'd':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[0-9]*" : "[0-9]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[0-9]*" : "[0-9]*?");
 								break;
 								break;
 
 
 							case 'D':
 							case 'D':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[^0-9]*" : "[^0-9]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[^0-9]*" : "[^0-9]*?");
 								break;
 								break;
 
 
 							case 'p':
 							case 'p':
@@ -1078,49 +1063,41 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 
 
 							case 's':
 							case 's':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "\\s*" : "\\s*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\s*" : "\\s*?");
 								break;
 								break;
 
 
 							case 'S':
 							case 'S':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "\\S*" : "\\S*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\S*" : "\\S*?");
 								break;
 								break;
 
 
 							case 'w':
 							case 'w':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[a-zA-Z]*" : "[a-zA-Z]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\w*" : "\\w*?");
 								break;
 								break;
 
 
 							case 'W':
 							case 'W':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[^a-zA-Z]*" : "[^a-zA-Z]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\W*" : "\\W*?");
 								break;
 								break;
 
 
 							case '?':
 							case '?':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? ".?" : ".?" "?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? ".?" : ".?" "?");
 								break;
 								break;
 
 
 							case '*':
 							case '*':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, *pti == 0 ? ".*" : ".*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? ".*" : ".*?");
 								break;
 								break;
 
 
 							case '+':
 							case '+':
 								pti += 3 + get_regex_range(&pti[3], pto, NULL, NULL);
 								pti += 3 + get_regex_range(&pti[3], pto, NULL, NULL);
-								pto += strlen(pto);
 								break;
 								break;
 
 
 							case '.':
 							case '.':
 								pti += 3;
 								pti += 3;
-								strcpy(pto, ".");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", ".");
 								break;
 								break;
 
 
 							case '{':
 							case '{':

+ 19 - 17
src/screen.c

@@ -1139,17 +1139,29 @@ DO_SCREEN(screen_set)
 	{
 	{
 		screen_osc("0", arg2);
 		screen_osc("0", arg2);
 	}
 	}
-	else if (is_abbrev(arg1, "COLS"))
+	else if (is_abbrev(arg1, "COLS") && is_math(ses, arg2))
 	{
 	{
-		gtd->screen->cols = get_number(ses, arg2);
+		init_resize(gts, gtd->screen->rows, get_number(ses, arg2), gtd->screen->height, gtd->screen->width / gtd->screen->cols * get_number(ses, arg2));
+
+		for (ses = gts->next ; ses ; ses = ses->next)
+		{
+			init_resize(ses, gtd->screen->rows, gtd->screen->cols, gtd->screen->height, gtd->screen->width);
+		}
+//		gtd->screen->cols = get_number(ses, arg2);
 	}
 	}
 	else if (is_abbrev(arg1, "LABEL"))
 	else if (is_abbrev(arg1, "LABEL"))
 	{
 	{
 		screen_osc("1", arg2);
 		screen_osc("1", arg2);
 	}
 	}
-	else if (is_abbrev(arg1, "ROWS"))
+	else if (is_abbrev(arg1, "ROWS") && is_math(ses, arg2))
 	{
 	{
-		gtd->screen->rows = get_number(ses, arg2);
+		init_resize(gts, get_number(ses, arg2), gtd->screen->cols, gtd->screen->height / gtd->screen->rows * get_number(ses, arg2), gtd->screen->width);
+
+		for (ses = gts->next ; ses ; ses = ses->next)
+		{
+			init_resize(ses, gtd->screen->rows, gtd->screen->cols, gtd->screen->height, gtd->screen->width);
+		}
+//		gtd->screen->rows = get_number(ses, arg2);
 	}
 	}
 	else if (is_abbrev(arg1, "TITLE"))
 	else if (is_abbrev(arg1, "TITLE"))
 	{
 	{
@@ -1157,7 +1169,7 @@ DO_SCREEN(screen_set)
 	}
 	}
 	else
 	else
 	{
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #SCREEN {SET} {COLS|ROWS|LABEL|NAME|TITLE}");
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #SCREEN {SET} {COLS|ROWS|LABEL|NAME|TITLE} {<ARG>}");
 	}
 	}
 }
 }
 
 
@@ -1243,12 +1255,7 @@ int get_row_index(struct session *ses, int val)
 		val = 1 + gtd->screen->rows + val;
 		val = 1 + gtd->screen->rows + val;
 	}
 	}
 
 
-	if (val > gtd->screen->rows)
-	{
-		val = gtd->screen->rows;
-	}
-
-	return val;
+	return URANGE(1, val, gtd->screen->rows);
 }
 }
 
 
 
 
@@ -1274,12 +1281,7 @@ int get_col_index(struct session *ses, int val)
 		val = 1 + gtd->screen->cols + val;
 		val = 1 + gtd->screen->cols + val;
 	}
 	}
 
 
-	if (val > gtd->screen->cols)
-	{
-		val = gtd->screen->cols;
-	}
-
-	return val;
+	return URANGE(1, val, gtd->screen->cols);
 }
 }
 
 
 
 

+ 12 - 3
src/show.c

@@ -84,9 +84,16 @@ DO_COMMAND(do_echo)
 
 
 	format_string(ses, arg1, arg, result);
 	format_string(ses, arg1, arg, result);
 
 
-	arg = get_arg_in_braces(ses, result, arg1, GET_ALL|GET_SPC);
+	if (*result == DEFAULT_OPEN)
+	{
+		arg = get_arg_in_braces(ses, result, arg1, GET_ALL|GET_SPC);
+	}
+	else
+	{
+		strcpy(arg1, result);
 
 
-	prompt = is_suffix(arg1, "\\") && !is_suffix(arg1, "\\\\");
+		arg += strlen(arg);
+	}
 
 
 	substitute(ses, arg1, arg1, SUB_COL|SUB_ESC);
 	substitute(ses, arg1, arg1, SUB_COL|SUB_ESC);
 
 
@@ -100,6 +107,8 @@ DO_COMMAND(do_echo)
 		return ses;
 		return ses;
 	}
 	}
 
 
+	prompt = is_suffix(arg1, "\\") && !is_suffix(arg1, "\\\\");
+
 	str_cpy_printf(&out, "%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
 	str_cpy_printf(&out, "%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
 
 
 	tintin_puts3(ses, out, prompt);
 	tintin_puts3(ses, out, prompt);
@@ -494,7 +503,7 @@ void tintin_puts(struct session *ses, char *string)
 
 
 	do_one_line(string, ses);
 	do_one_line(string, ses);
 
 
-	if (ses->gagline)
+	if (ses->gagline > 0)
 	{
 	{
 		ses->gagline--;
 		ses->gagline--;
 
 

+ 6 - 0
src/split.c

@@ -193,11 +193,17 @@ void init_split(struct session *ses, int top_row, int top_col, int bot_row, int
 			if (HAS_BIT(ses->config_flags, CONFIG_FLAG_VERBOSE) || gtd->level->verbose || gtd->level->quiet == 0)
 			if (HAS_BIT(ses->config_flags, CONFIG_FLAG_VERBOSE) || gtd->level->verbose || gtd->level->quiet == 0)
 			{
 			{
 				command(ses, do_screen, "FILL DEFAULT");
 				command(ses, do_screen, "FILL DEFAULT");
+
 			}
 			}
 		}
 		}
 
 
 	}
 	}
 
 
+	if (HAS_BIT(ses->flags, SES_FLAG_READMUD))
+	{
+		goto_pos(ses, ses->split->bot_row, 1);
+	}
+
 	check_all_events(ses, EVENT_FLAG_SCREEN, 0, 4, "SCREEN SPLIT", ntos(ses->split->top_row), ntos(ses->split->top_col), ntos(ses->split->bot_row), ntos(ses->split->bot_col));
 	check_all_events(ses, EVENT_FLAG_SCREEN, 0, 4, "SCREEN SPLIT", ntos(ses->split->top_row), ntos(ses->split->top_col), ntos(ses->split->bot_row), ntos(ses->split->bot_col));
 
 
 	pop_call();
 	pop_call();

+ 4 - 0
src/substitute.c

@@ -2179,6 +2179,10 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 				}
 				}
 				else
 				else
 				{
 				{
+					if (HAS_BIT(flags, SUB_COL))
+					{
+						old[0] = 0;
+					}
 					*pto++ = *pti++;
 					*pto++ = *pti++;
 				}
 				}
 				break;
 				break;

+ 27 - 44
src/tables.c

@@ -37,7 +37,7 @@ struct list_type list_table[LIST_MAX] =
 	{    "COMMAND",           "COMMANDS",           SORT_APPEND,      1, 0, 0, LIST_FLAG_MESSAGE                                                                  },
 	{    "COMMAND",           "COMMANDS",           SORT_APPEND,      1, 0, 0, LIST_FLAG_MESSAGE                                                                  },
 	{    "CONFIG",            "CONFIGS",            SORT_ALPHA,       2, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "CONFIG",            "CONFIGS",            SORT_ALPHA,       2, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "DELAY",             "DELAYS",             SORT_STABLE,      2, 2, 3, LIST_FLAG_MESSAGE|LIST_FLAG_READ                                                   },
 	{    "DELAY",             "DELAYS",             SORT_STABLE,      2, 2, 3, LIST_FLAG_MESSAGE|LIST_FLAG_READ                                                   },
-	{    "EVENT",             "EVENTS",             SORT_ALPHA,       2, 2, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
+	{    "EVENT",             "EVENTS",             SORT_ALPHA,       2, 2, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_CASE },
 	{    "FUNCTION",          "FUNCTIONS",          SORT_ALPHA,       2, 2, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "FUNCTION",          "FUNCTIONS",          SORT_ALPHA,       2, 2, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "GAG",               "GAGS",               SORT_ALPHA,       1, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "GAG",               "GAGS",               SORT_ALPHA,       1, 0, 0, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT },
 	{    "HIGHLIGHT",         "HIGHLIGHTS",         SORT_PRIORITY,    3, 0, 3, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX|LIST_FLAG_PRIORITY },
 	{    "HIGHLIGHT",         "HIGHLIGHTS",         SORT_PRIORITY,    3, 0, 3, LIST_FLAG_MESSAGE|LIST_FLAG_READ|LIST_FLAG_WRITE|LIST_FLAG_CLASS|LIST_FLAG_INHERIT|LIST_FLAG_REGEX|LIST_FLAG_PRIORITY },
@@ -72,22 +72,25 @@ struct substitution_type substitution_table[] =
 
 
 struct charset_type charset_table[] =
 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 },
-	{    "CP437TOUTF8",   "utf-8",       CHARSET_FLAG_UTF8|CHARSET_FLAG_FANSITOUTF8 },
-	{    "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 }
+	{    "ASCII",         "iso-8859-1",  "ASCII",      0                  },
+	{    "UTF-8",         "utf-8",       "UTF-8",      CHARSET_FLAG_UTF8  },
+	{    "BIG5",          "big5",        "BIG5",       CHARSET_FLAG_BIG5  },
+	{    "BIG-5",         "big5",        "BIG5",       CHARSET_FLAG_BIG5  },
+	{    "EUC-KR",        "euc-kr",      "EUC-KR",     CHARSET_FLAG_CP949 },
+	{    "CP949",         "euc-kr",      "EUC-KR",     CHARSET_FLAG_CP949 },
+	{    "GBK-1",         "gb18030",     "GB18030",    CHARSET_FLAG_GBK1  },
+	{    "GB18030",       "gb18030",     "GB18030",    CHARSET_FLAG_GBK1  },
+	{    "BIG5TOUTF8",    "utf-8",       "BIG5",       CHARSET_FLAG_UTF8|CHARSET_FLAG_BIG5TOUTF8   },
+	{    "CP437TOUTF8",   "utf-8",       "CP437",      CHARSET_FLAG_UTF8|CHARSET_FLAG_FANSITOUTF8  },
+	{    "FANSITOUTF8",   "utf-8",       "CP437",      CHARSET_FLAG_UTF8|CHARSET_FLAG_FANSITOUTF8  },
+	{    "CP1251TOUTF8",  "utf-8",       "CP1251",     CHARSET_FLAG_UTF8|CHARSET_FLAG_CP1251TOUTF8 },
+	{    "EUCKRTOUTF8",   "utf-8",       "EUC-KR",     CHARSET_FLAG_UTF8|CHARSET_FLAG_CP949TOUTF8  },
+	{    "CP949TOUTF8",   "utf-8",       "EUC-KR",     CHARSET_FLAG_UTF8|CHARSET_FLAG_CP949TOUTF8  },
+	{    "GBK1TOUTF8",    "utf-8",       "GB18030",    CHARSET_FLAG_UTF8|CHARSET_FLAG_GBK1TOUTF8   },
+	{    "ISO1TOUTF8",    "utf-8",       "ISO-8859-1", CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO1TOUTF8   },
+	{    "ISO2TOUTF8",    "utf-8",       "ISO-8859-2", CHARSET_FLAG_UTF8|CHARSET_FLAG_ISO2TOUTF8   },
+	{    "KOI8TOUTF8",    "utf-8",       "KOI8-R",     CHARSET_FLAG_UTF8|CHARSET_FLAG_KOI8TOUTF8   },
+	{    "",              "",            "",           0 }
 };
 };
 
 
 struct config_type config_table[] =
 struct config_type config_table[] =
@@ -327,9 +330,9 @@ char character_table[256] =
 	0,
 	0,
 	0,
 	0,
 	0,
 	0,
-	0,
+	0, // \a
 
 
-	0,
+	0, // \b
 	CHAR_FLAG_SPACE, // \t
 	CHAR_FLAG_SPACE, // \t
 	CHAR_FLAG_SPACE, // \n
 	CHAR_FLAG_SPACE, // \n
 	CHAR_FLAG_SPACE, // \v
 	CHAR_FLAG_SPACE, // \v
@@ -913,7 +916,7 @@ struct cursor_type cursor_table[] =
 	{     "PREV WORD",          "Move cursor to the previous word",               "\eb",         CURSOR_FLAG_GET_ALL,     cursor_move_left_word,        ""          },
 	{     "PREV WORD",          "Move cursor to the previous word",               "\eb",         CURSOR_FLAG_GET_ALL,     cursor_move_left_word,        ""          },
 	{     "REDRAW INPUT",       "Redraw the input line",                          "",           CURSOR_FLAG_GET_ALL,     cursor_redraw_input,          ""          },
 	{     "REDRAW INPUT",       "Redraw the input line",                          "",           CURSOR_FLAG_GET_ALL,     cursor_redraw_input,          ""          },
 	{     "RESET MACRO",        "",                                               "",            CURSOR_FLAG_GET_ALL,     cursor_macro,                 "RESET"     }, // obsolete
 	{     "RESET MACRO",        "",                                               "",            CURSOR_FLAG_GET_ALL,     cursor_macro,                 "RESET"     }, // obsolete
-	{     "SET",                "Copy given string to input line",                "",            CURSOR_FLAG_GET_ONE,     cursor_set,                   ""          },
+	{     "SET",                "Insert given string at cursor",                  "",            CURSOR_FLAG_GET_ONE,     cursor_set,                   ""          },
 	{     "SOFT ENTER",         "Create a new line in edit mode.",                "\e[13;2u",    CURSOR_FLAG_GET_ALL,     cursor_soft_enter,            ""          },
 	{     "SOFT ENTER",         "Create a new line in edit mode.",                "\e[13;2u",    CURSOR_FLAG_GET_ALL,     cursor_soft_enter,            ""          },
 	{     "SUSPEND",            "Suspend program, return with fg",                "",           CURSOR_FLAG_GET_ALL,     cursor_suspend,               ""          },
 	{     "SUSPEND",            "Suspend program, return with fg",                "",           CURSOR_FLAG_GET_ALL,     cursor_suspend,               ""          },
 	{     "TAB",                "<LIST|SCROLLBACK> <BACKWARD|FORWARD>",           "",            CURSOR_FLAG_GET_ONE,     cursor_tab,                   ""          },
 	{     "TAB",                "<LIST|SCROLLBACK> <BACKWARD|FORWARD>",           "",            CURSOR_FLAG_GET_ONE,     cursor_tab,                   ""          },
@@ -922,7 +925,9 @@ struct cursor_type cursor_table[] =
 	{     "UP",                 "Move cursor up",                                 "\e[A",        CURSOR_FLAG_GET_ALL,     cursor_move_up,               ""          },
 	{     "UP",                 "Move cursor up",                                 "\e[A",        CURSOR_FLAG_GET_ALL,     cursor_move_up,               ""          },
 	{     "",                   "",                                               "\e[6~",                          0,    cursor_buffer_down,           ""          },
 	{     "",                   "",                                               "\e[6~",                          0,    cursor_buffer_down,           ""          },
 	{     "",                   "",                                               "\e[1;5F",                        0,    cursor_buffer_end,            ""          },
 	{     "",                   "",                                               "\e[1;5F",                        0,    cursor_buffer_end,            ""          },
+//	{     "",                   "",                                               "\e[F",                           0,    cursor_buffer_end,            ""          },
 	{     "",                   "",                                               "\e[1;5H",                        0,    cursor_buffer_home,           ""          },
 	{     "",                   "",                                               "\e[1;5H",                        0,    cursor_buffer_home,           ""          },
+//	{     "",                   "",                                               "\e[H",                           0,    cursor_buffer_home,           ""          },
 	{     "",                   "",                                               "\e[5~",                          0,    cursor_buffer_up,             ""          },
 	{     "",                   "",                                               "\e[5~",                          0,    cursor_buffer_up,             ""          },
 	{     "",                   "",                                               "\eOa",                           0,    cursor_buffer_up,             "1"         },
 	{     "",                   "",                                               "\eOa",                           0,    cursor_buffer_up,             "1"         },
 	{     "",                   "",                                               "\eOb",                           0,    cursor_buffer_down,           "1"         },
 	{     "",                   "",                                               "\eOb",                           0,    cursor_buffer_down,           "1"         },
@@ -999,6 +1004,7 @@ struct event_type event_table[] =
 	{    "CLASS CREATED",                          0, EVENT_FLAG_CLASS,    "CLASS",     "class creation"             },
 	{    "CLASS CREATED",                          0, EVENT_FLAG_CLASS,    "CLASS",     "class creation"             },
 	{    "CLASS DEACTIVATED",                      0, EVENT_FLAG_CLASS,    "CLASS",     "class deactivations"        },
 	{    "CLASS DEACTIVATED",                      0, EVENT_FLAG_CLASS,    "CLASS",     "class deactivations"        },
 	{    "CLASS DESTROYED",                        0, EVENT_FLAG_CLASS,    "CLASS",     "class destruction"          },
 	{    "CLASS DESTROYED",                        0, EVENT_FLAG_CLASS,    "CLASS",     "class destruction"          },
+	{    "DAEMON ATTACH TIMEOUT",                  0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "daemon attachment timeout"  },
 	{    "DAEMON ATTACHED",                        0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "daemon attachment"          },
 	{    "DAEMON ATTACHED",                        0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "daemon attachment"          },
 	{    "DAEMON DETACHED",                        0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "daemon detachment"          },
 	{    "DAEMON DETACHED",                        0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "daemon detachment"          },
 	{    "DATE",                                   0, EVENT_FLAG_TIME,     "TIME",      "the given date"             },
 	{    "DATE",                                   0, EVENT_FLAG_TIME,     "TIME",      "the given date"             },
@@ -1036,6 +1042,7 @@ struct event_type event_table[] =
 	{    "MINUTE",                                 0, EVENT_FLAG_TIME,     "TIME",      "minute or given minute"     },
 	{    "MINUTE",                                 0, EVENT_FLAG_TIME,     "TIME",      "minute or given minute"     },
 	{    "MONTH",                                  0, EVENT_FLAG_TIME,     "TIME",      "month or given month"       },
 	{    "MONTH",                                  0, EVENT_FLAG_TIME,     "TIME",      "month or given month"       },
 	{    "MOVED ",                                 0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is moved"             },
 	{    "MOVED ",                                 0, EVENT_FLAG_MOUSE,    "MOUSE",     "mouse is moved"             },
+	{    "NO SESSION ACTIVE",                      0, EVENT_FLAG_INPUT,    "INPUT",     "input on startup session"   },
 	{    "PORT CONNECTION",                        0, EVENT_FLAG_PORT,     "PORT",      "socket connects"            },
 	{    "PORT CONNECTION",                        0, EVENT_FLAG_PORT,     "PORT",      "socket connects"            },
 	{    "PORT DISCONNECTION",                     0, EVENT_FLAG_PORT,     "PORT",      "socket disconnects"         },
 	{    "PORT DISCONNECTION",                     0, EVENT_FLAG_PORT,     "PORT",      "socket disconnects"         },
 	{    "PORT INITIALIZED",                       0, EVENT_FLAG_PORT,     "PORT",      "port is initialized"        },
 	{    "PORT INITIALIZED",                       0, EVENT_FLAG_PORT,     "PORT",      "port is initialized"        },
@@ -1141,30 +1148,6 @@ struct path_type path_table[] =
 	{    "",                  NULL,                ""                                               }
 	{    "",                  NULL,                ""                                               }
 };
 };
 
 
-struct line_type line_table[] =
-{
-	{    "BACKGROUND",        line_background,     "Execute line without stealing session focus."   },
-	{    "BENCHMARK",         line_benchmark,      "Execute line and provide timing information."   },
-	{    "CAPTURE",           line_capture,        "Capture output in the given variable."          },
-	{    "CONVERT",           line_convert,        "Execute line in convert meta data mode."        },
-	{    "DEBUG",             line_debug,          "Execute line in debug mode."                    },
-	{    "GAG",               line_gag,            "Gag the next line."                             },
-	{    "IGNORE",            line_ignore,         "Execute line with triggers ignored."            },
-	{    "LOCAL",             line_local,          "Execute line with local scope."                 },
-	{    "LOG",               line_log,            "Log the next line or given line."               },
-	{    "LOGMODE",           line_logmode,        "Execute line with given log mode."              },
-	{    "LOGVERBATIM",       line_logverbatim,    "Log the line as plain text verbatim."           },
-	{    "MSDP",              line_msdp,           "Execute line with msdp conversion."             },
-	{    "MULTISHOT",         line_multishot,      "Execute line creating multishot triggers."      },
-	{    "ONESHOT",           line_oneshot,        "Execute line creating oneshot triggers."        },
-	{    "QUIET",             line_quiet,          "Execute line with all system messages off."     },
-	{    "STRIP",             line_strip,          "Execute line with escape codes stripped."       },
-	{    "SUBSTITUTE",        line_substitute,     "Execute line with given substitution."          },
-	{    "VERBATIM",          line_verbatim,       "Execute line as plain text."                    },
-	{    "VERBOSE",           line_verbose,        "Execute line with all system messages on."      },
-	{    "",                  NULL,                ""                                               }
-};
-
 struct history_type history_table[] =
 struct history_type history_table[] =
 {
 {
 //	{    "CHARACTER",         history_character,   "Set the character used for repeating commands." },
 //	{    "CHARACTER",         history_character,   "Set the character used for repeating commands." },

+ 66 - 38
src/telopt_client.c

@@ -599,6 +599,23 @@ int client_recv_dont_ttype(struct session *ses, int cplen, unsigned char *cpsrc)
 	return 3;
 	return 3;
 }
 }
 
 
+int get_mtts_val(struct session *ses)
+{
+	return (0 + (ses->color > 0 ? 1 : 0)
+		+ (HAS_BIT(ses->flags, SES_FLAG_SPLIT) ? 0 : 2)
+		+ (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && !HAS_BIT(ses->charset, CHARSET_FLAG_ALL_TOUTF8) ? 4 : 0)
+		+ (ses->color > 16 ? 8 : 0)
+		+ (HAS_BIT(ses->flags, TINTIN_FLAG_MOUSETRACKING) ? 16 + 1024 : 0)
+		+ (HAS_BIT(ses->config_flags, CONFIG_FLAG_SCREENREADER) ? 64 : 0)
+//		+ proxy ? 128 : 0
+		+ (ses->color > 256 ? 256 : 0)
+		+ 512
+#ifdef HAVE_GNUTLS_H
+		+ 2048
+#endif
+		);
+}
+
 int client_recv_sb_ttype(struct session *ses, int cplen, unsigned char *cpsrc)
 int client_recv_sb_ttype(struct session *ses, int cplen, unsigned char *cpsrc)
 {
 {
 	check_all_events(ses, EVENT_FLAG_TELNET, 0, 1, "IAC SB TTYPE", ntos(cpsrc[3]));
 	check_all_events(ses, EVENT_FLAG_TELNET, 0, 1, "IAC SB TTYPE", ntos(cpsrc[3]));
@@ -611,14 +628,22 @@ int client_recv_sb_ttype(struct session *ses, int cplen, unsigned char *cpsrc)
 	if (HAS_BIT(ses->telopts, TELOPT_FLAG_MTTS))
 	if (HAS_BIT(ses->telopts, TELOPT_FLAG_MTTS))
 	{
 	{
 		char mtts[BUFFER_SIZE];
 		char mtts[BUFFER_SIZE];
-
-		sprintf(mtts, "MTTS %d",
-			(ses->color > 0 ? 1 : 0) +
-			(HAS_BIT(ses->flags, SES_FLAG_SPLIT) ? 0 : 2) +
-			(HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && !HAS_BIT(ses->charset, CHARSET_FLAG_ALL_TOUTF8) ? 4 : 0) +
-			(ses->color > 16 ? 8 : 0) +
-			(HAS_BIT(ses->config_flags, CONFIG_FLAG_SCREENREADER) ? 64 : 0) +
-			(ses->color > 256 ? 256 : 0));
+/*
+		sprintf(mtts, "MTTS %d", 0
+			+ (ses->color > 0 ? 1 : 0)
+			+ (HAS_BIT(ses->flags, SES_FLAG_SPLIT) ? 0 : 2)
+			+ (HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && !HAS_BIT(ses->charset, CHARSET_FLAG_ALL_TOUTF8) ? 4 : 0)
+			+ (ses->color > 16 ? 8 : 0)
+			+ (HAS_BIT(ses->flags, TINTIN_FLAG_MOUSETRACKING) ? 16 + 1024 : 0)
+			+ (HAS_BIT(ses->config_flags, CONFIG_FLAG_SCREENREADER) ? 64 : 0)
+			+ (ses->color > 256 ? 256 : 0)
+			+ 512
+#ifdef HAVE_GNUTLS_H
+			+ 2048
+#endif
+			);
+*/
+		sprintf(mtts, "MTTS %d", get_mtts_val(ses));
 
 
 		telnet_printf(ses, 6 + strlen(mtts), "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, 0, mtts, IAC, SE);
 		telnet_printf(ses, 6 + strlen(mtts), "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, 0, mtts, IAC, SE);
 
 
@@ -729,7 +754,7 @@ int client_send_sb_naws(struct session *ses, int cplen, unsigned char *cpsrc)
 		telnet_printf(ses, 9, "%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, cols / 256, cols % 256, rows / 256, rows % 256, IAC, SE);
 		telnet_printf(ses, 9, "%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_NAWS, cols / 256, cols % 256, rows / 256, rows % 256, IAC, SE);
 	}
 	}
 
 
-	client_telopt_debug(ses, "SENT IAC SB NAWS %d %d %d %d", cols / 256, cols % 256, gtd->screen->rows / 256, gtd->screen->rows % 256);
+	client_telopt_debug(ses, "SENT IAC SB NAWS %d %d %d %d", cols / 256, cols % 256, rows / 256, rows % 256);
 
 
 	return 3;
 	return 3;
 }
 }
@@ -1118,8 +1143,8 @@ int client_recv_sb_msdp(struct session *ses, int cplen, unsigned char *src)
 		{
 		{
 			strip_vt102_codes(val, plain);
 			strip_vt102_codes(val, plain);
 			client_telopt_debug(ses, "RCVD IAC SB MSDP VAR %-20s VAL %s", var, val);
 			client_telopt_debug(ses, "RCVD IAC SB MSDP VAR %-20s VAL %s", var, val);
-			check_all_events(ses, EVENT_FLAG_TELNET, 1, 3, "IAC SB MSDP %s", var, var, val, plain);
-			check_all_events(ses, EVENT_FLAG_TELNET, 0, 3, "IAC SB MSDP", var, val, plain);
+			check_all_events(ses, EVENT_FLAG_TELNET, 1, 4, "IAC SB MSDP %s", var, var, val, plain, ntos(nest));
+			check_all_events(ses, EVENT_FLAG_TELNET, 0, 4, "IAC SB MSDP", var, val, plain, ntos(nest));
 		}
 		}
 		i++;
 		i++;
 	}
 	}
@@ -1370,37 +1395,45 @@ int client_recv_sb_charset(struct session *ses, int cplen, unsigned char *src)
 				{
 				{
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && !HAS_BIT(ses->charset, CHARSET_FLAG_ALL_TOUTF8);
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && !HAS_BIT(ses->charset, CHARSET_FLAG_ALL_TOUTF8);
 				}
 				}
-				else if (!strcmp(var, "BIG-5"))
+				else if (!strcmp(var, "BIG5") || !strcmp(var, "BIG-5"))
 				{
 				{
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_BIG5) || HAS_BIT(ses->charset, CHARSET_FLAG_BIG5TOUTF8);
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_BIG5) || HAS_BIT(ses->charset, CHARSET_FLAG_BIG5TOUTF8);
 				}
 				}
-				else if (!strcmp(var, "CP949"))
+				else if (!strcmp(var, "CP437") || !strcmp(var, "FANSI"))
+				{
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_FANSITOUTF8);
+				}
+				else if (!strcmp(var, "EUC-KR") || !strcmp(var, "CP949"))
 				{
 				{
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_CP949) || HAS_BIT(ses->charset, CHARSET_FLAG_CP949TOUTF8);
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_CP949) || HAS_BIT(ses->charset, CHARSET_FLAG_CP949TOUTF8);
 				}
 				}
-				else if (!strcmp(var, "FANSI") || !strcmp(var, "CP437"))
+				else if (!strcmp(var, "CP1251"))
 				{
 				{
-					accept = HAS_BIT(ses->charset, CHARSET_FLAG_FANSITOUTF8);
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_CP1251TOUTF8);
 				}
 				}
-				else if (!strcmp(var, "ISO-8859-1") || !strcasecmp(var, "ISO-1"))
+				else if (!strcmp(var, "ISO-8859-1") || !strcasecmp(var, "LATIN-1"))
 				{
 				{
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_ISO1TOUTF8);
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_ISO1TOUTF8);
 				}
 				}
-				else if (!strcmp(var, "ISO-8859-2") || !strcasecmp(var, "ISO-2"))
+				else if (!strcmp(var, "ISO-8859-2") || !strcasecmp(var, "LATIN-2"))
 				{
 				{
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_ISO2TOUTF8);
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_ISO2TOUTF8);
 				}
 				}
-				else if (!strcmp(var, "GBK-1") || !strcmp(var, "GB18030"))
+				else if (!strcmp(var, "GBK") || !strcmp(var, "GB2312") || !strcmp(var, "GB18030"))
 				{
 				{
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_GBK1) || HAS_BIT(ses->charset, CHARSET_FLAG_GBK1TOUTF8);
 					accept = HAS_BIT(ses->charset, CHARSET_FLAG_GBK1) || HAS_BIT(ses->charset, CHARSET_FLAG_GBK1TOUTF8);
 				}
 				}
+				else if (!strcmp(var, "KOI8-R"))
+				{
+					accept = HAS_BIT(ses->charset, CHARSET_FLAG_KOI8TOUTF8);
+				}
 
 
 				if (!check_all_events(ses, EVENT_FLAG_CATCH, 2, 2, "CATCH IAC SB CHARSET %s %s", buf, var, buf, var))
 				if (!check_all_events(ses, EVENT_FLAG_CATCH, 2, 2, "CATCH IAC SB CHARSET %s %s", buf, var, buf, var))
 				{
 				{
 					if (accept > 0 && found == 0)
 					if (accept > 0 && found == 0)
 					{
 					{
 						telnet_printf(ses, -1, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_CHARSET, CHARSET_ACCEPTED, var, IAC, SE);
 						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);
 						client_telopt_debug(ses, "SENT IAC SB CHARSET ACCEPTED %s", var);
 
 
 						found = 1;
 						found = 1;
@@ -1428,24 +1461,19 @@ int client_recv_sb_charset(struct session *ses, int cplen, unsigned char *src)
 	NEW-ENVIRON
 	NEW-ENVIRON
 */
 */
 
 
-int get_mtts_val(struct session *ses)
+
+char *get_charset_mnes(struct session *ses)
 {
 {
-	return
-		(ses->color > 0 ? 1 : 0)
-		+
-		(HAS_BIT(ses->flags, SES_FLAG_SPLIT) ? 0 : 2)
-		+
-		(HAS_BIT(ses->charset, CHARSET_FLAG_UTF8) && !HAS_BIT(ses->charset, CHARSET_FLAG_ALL_TOUTF8) ? 4 : 0)
-		+
-		(ses->color > 16 ? 8 : 0)
-		+
-		(HAS_BIT(ses->config_flags, CONFIG_FLAG_SCREENREADER) ? 64 : 0)
-		+
-//		proxy ? 128 : 0
-//		+
-		(ses->color > 256 ? 256 : 0)
-		+
-		512;
+	int index;
+
+	for (index = 0 ; *charset_table[index].name ; index++)
+	{
+		if (ses->charset == charset_table[index].flags)
+		{
+			return charset_table[index].mnes;
+		}
+	}
+	return "ASCII";
 }
 }
 
 
 int client_recv_sb_new_environ(struct session *ses, int cplen, unsigned char *src)
 int client_recv_sb_new_environ(struct session *ses, int cplen, unsigned char *src)
@@ -1548,7 +1576,7 @@ int client_recv_sb_new_environ(struct session *ses, int cplen, unsigned char *sr
 							}
 							}
 							else if (!strcmp(var, "CHARSET"))
 							else if (!strcmp(var, "CHARSET"))
 							{
 							{
-								telnet_printf(ses, -1, "%c%c%c%c%c%s%c%s%c%c", IAC, SB, TELOPT_NEW_ENVIRON, ENV_IS, ENV_VAR, "CHARSET", ENV_VAL, get_charset(ses), IAC, SE);
+								telnet_printf(ses, -1, "%c%c%c%c%c%s%c%s%c%c", IAC, SB, TELOPT_NEW_ENVIRON, ENV_IS, ENV_VAR, "CHARSET", ENV_VAL, get_charset_mnes(ses), IAC, SE);
 
 
 								client_telopt_debug(ses, "SENT IAC SB NEW-ENVIRON IS VAR %s VAL %s", "CHARSET", get_charset(ses));
 								client_telopt_debug(ses, "SENT IAC SB NEW-ENVIRON IS VAR %s VAL %s", "CHARSET", get_charset(ses));
 							}
 							}
@@ -1932,7 +1960,7 @@ int client_recv_sb_gmcp(struct session *ses, int cplen, unsigned char *src)
 
 
 	check_all_events(ses, EVENT_FLAG_TELNET, 0, 3, "IAC SB GMCP", mod, val, json);
 	check_all_events(ses, EVENT_FLAG_TELNET, 0, 3, "IAC SB GMCP", mod, val, json);
 
 
-	check_all_events(ses, EVENT_FLAG_TELNET, 1, 2, "IAC SB GMCP %s IAC SE", mod, val, json);
+	check_all_events(ses, EVENT_FLAG_TELNET, 1, 3, "IAC SB GMCP %s IAC SE", mod, val, val, json);
 
 
 	pop_call();
 	pop_call();
 	return UMIN(i + 1, cplen);
 	return UMIN(i + 1, cplen);

+ 13 - 4
src/telopt_server.c

@@ -736,14 +736,23 @@ int process_sb_charset(struct session *ses, struct port_data *buddy, unsigned ch
 
 
 	val[0] = 0;
 	val[0] = 0;
 
 
-	i = 5;
+	i = 4;
 
 
-	while (i < srclen && src[i] != SE && src[i] != src[4])
+	if (src[3] == CHARSET_REQUEST)
+	{
+		i++;
+	}
+
+	while (i < srclen && src[i] != SE)
 	{
 	{
 		pto = val;
 		pto = val;
 
 
-		while (i < srclen && src[i] != src[4] && src[i] != IAC)
+		while (i < srclen && src[i] != IAC)
 		{
 		{
+			if (src[3] == CHARSET_REQUEST && src[i] == src[4])
+			{
+				break;
+			}
 			*pto++ = src[i++];
 			*pto++ = src[i++];
 		}
 		}
 		*pto = 0;
 		*pto = 0;
@@ -915,7 +924,7 @@ int process_sb_gmcp(struct session *ses, struct port_data *buddy, unsigned char
 		return srclen + 1;
 		return srclen + 1;
 	}
 	}
 
 
-	outlen = json2msdp(src, srclen, out);
+	outlen = gmcp2msdp(src, srclen, out);
 
 
 	process_sb_msdp(ses, buddy, (unsigned char *) out, outlen);
 	process_sb_msdp(ses, buddy, (unsigned char *) out, outlen);
 
 

+ 42 - 29
src/terminal.c

@@ -145,35 +145,50 @@ void echo_on(struct session *ses)
 
 
 void init_terminal_size(struct session *ses)
 void init_terminal_size(struct session *ses)
 {
 {
-	struct winsize screen;
-	static int old_rows, old_cols;
-
 	push_call("init_terminal_size(%p)",ses);
 	push_call("init_terminal_size(%p)",ses);
 
 
+	if (ses == gts)
+	{
+		struct winsize screen;
+
+		if (ioctl(1, TIOCGWINSZ, &screen) >= 0)
+		{
+			init_resize(gts, screen.ws_row, screen.ws_col, screen.ws_ypixel, screen.ws_xpixel);
+		}
+		else
+		{
+			init_resize(gts, SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT * 16, SCREEN_WIDTH * 10);
+		}
+	}
+	else
+	{
+		init_resize(ses, gtd->screen->rows, gtd->screen->cols, gtd->screen->height, gtd->screen->width);
+	}
+	pop_call();
+	return;
+}
+
+void init_resize(struct session *ses, int rows, int cols, int height, int width)
+{
+	static int old_rows, old_cols;
+
 	if (ses == gts)
 	if (ses == gts)
 	{
 	{
 		old_rows = gtd->screen->rows;
 		old_rows = gtd->screen->rows;
 		old_cols = gtd->screen->cols;
 		old_cols = gtd->screen->cols;
 
 
-		if (ioctl(1, TIOCGWINSZ, &screen) >= 0)
+		init_screen(rows, cols, height, width);
+
+		if (gtd->attach_sock)
 		{
 		{
-			init_screen(screen.ws_row, screen.ws_col, screen.ws_ypixel, screen.ws_xpixel);
+			char buf[100];
+			sprintf(buf, "\e[8;%d;%dt\e[4;%d;%dt\e[7t", rows, cols, height, width);
 
 
-			if (gtd->attach_sock)
+			if (write(gtd->attach_sock, buf, strlen(buf)) == -1)
 			{
 			{
-				char buf[100];
-				sprintf(buf, "\e[8;%d;%dt\e[4;%d;%dt\e[7t", screen.ws_row, screen.ws_col, screen.ws_ypixel, screen.ws_xpixel);
-
-				if (write(gtd->attach_sock, buf, strlen(buf)) == -1)
-				{
-					printf("error: init_terminal_size: write:\n");
-				}
+				printf("error: init_terminal_size: write:\n");
 			}
 			}
 		}
 		}
-		else
-		{
-			init_screen(SCREEN_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT * 16, SCREEN_WIDTH * 10);
-		}
 	}
 	}
 
 
 	if (ses->scroll)
 	if (ses->scroll)
@@ -188,24 +203,21 @@ void init_terminal_size(struct session *ses)
 
 
 	init_split(ses, ses->split->sav_top_row, ses->split->sav_top_col, ses->split->sav_bot_row, ses->split->sav_bot_col);
 	init_split(ses, ses->split->sav_top_row, ses->split->sav_top_col, ses->split->sav_bot_row, ses->split->sav_bot_col);
 
 
-	check_all_events(ses, EVENT_FLAG_SCREEN, 0, 4, "SCREEN RESIZE", ntos(gtd->screen->rows), ntos(gtd->screen->cols), ntos(gtd->screen->height), ntos(gtd->screen->width));
+	check_all_events(ses, EVENT_FLAG_SCREEN, 0, 4, "SCREEN RESIZE", ntos(rows), ntos(cols), ntos(height), ntos(width));
 
 
-	if (old_rows <= old_cols / 2 && gtd->screen->rows > gtd->screen->cols / 2)
+	if (old_rows <= old_cols / 2 && rows > cols / 2)
 	{
 	{
-		check_all_events(ses, EVENT_FLAG_SCREEN, 0, 4, "SCREEN ROTATE PORTRAIT", ntos(gtd->screen->rows), ntos(gtd->screen->cols), ntos(gtd->screen->height), ntos(gtd->screen->width));
+		check_all_events(ses, EVENT_FLAG_SCREEN, 0, 4, "SCREEN ROTATE PORTRAIT", ntos(rows), ntos(cols), ntos(height), ntos(width));
 	}
 	}
-	else if (old_rows >= old_cols / 2 && gtd->screen->rows < gtd->screen->cols / 2)
+	else if (old_rows >= old_cols / 2 && rows < cols / 2)
 	{
 	{
-		check_all_events(ses, EVENT_FLAG_SCREEN, 0, 4, "SCREEN ROTATE LANDSCAPE", ntos(gtd->screen->rows), ntos(gtd->screen->cols), ntos(gtd->screen->height), ntos(gtd->screen->width));
+		check_all_events(ses, EVENT_FLAG_SCREEN, 0, 4, "SCREEN ROTATE LANDSCAPE", ntos(rows), ntos(cols), ntos(height), ntos(width));
 	}
 	}
 
 
-	msdp_update_all("SCREEN_ROWS",   "%d", gtd->screen->rows);
-	msdp_update_all("SCREEN_COLS",   "%d", gtd->screen->cols);
-	msdp_update_all("SCREEN_HEIGHT", "%d", gtd->screen->height);
-	msdp_update_all("SCREEN_WIDTH",  "%d", gtd->screen->width);
-
-	pop_call();
-	return;
+	msdp_update_all("SCREEN_ROWS",   "%d", rows);
+	msdp_update_all("SCREEN_COLS",   "%d", cols);
+	msdp_update_all("SCREEN_HEIGHT", "%d", height);
+	msdp_update_all("SCREEN_WIDTH",  "%d", width);
 }
 }
 
 
 int get_scroll_rows(struct session *ses)
 int get_scroll_rows(struct session *ses)
@@ -231,3 +243,4 @@ char *get_charset(struct session *ses)
 	}
 	}
 	return "ASCII";
 	return "ASCII";
 }
 }
+

+ 2 - 1
src/text.c

@@ -103,7 +103,7 @@ void print_stdout(int row, int col, char *format, ...)
 		{
 		{
 			if (write(gtd->detach_sock, buffer, len) == -1)
 			if (write(gtd->detach_sock, buffer, len) == -1)
 			{
 			{
-				printf("error: print_stdout: write:\n");
+				syserr_printf(gtd->ses, "print_stdout: write:");
 			}
 			}
 		}
 		}
 	}
 	}
@@ -330,6 +330,7 @@ int word_wrap_split(struct session *ses, char *textin, char *textout, int wrap,
 	*width     = 0;
 	*width     = 0;
 	cur_col    = 1;
 	cur_col    = 1;
 	cur_space  = cur_col;
 	cur_space  = cur_col;
+	*pto       = 0;
 
 
 	if (HAS_BIT(flags, WRAP_FLAG_SPLIT) && end == 0)
 	if (HAS_BIT(flags, WRAP_FLAG_SPLIT) && end == 0)
 	{
 	{

+ 18 - 16
src/tintin.h

@@ -212,7 +212,7 @@
 
 
 
 
 #define CLIENT_NAME              "TinTin++"
 #define CLIENT_NAME              "TinTin++"
-#define CLIENT_VERSION           "2.02.20 "
+#define CLIENT_VERSION           "2.02.30 "
 
 
 
 
 #define XT_E                            0x27
 #define XT_E                            0x27
@@ -487,6 +487,7 @@ enum operators
 #define INPUT_FLAG_HISTORYBROWSE      BV02
 #define INPUT_FLAG_HISTORYBROWSE      BV02
 #define INPUT_FLAG_HISTORYSEARCH      BV03
 #define INPUT_FLAG_HISTORYSEARCH      BV03
 #define INPUT_FLAG_CONVERTMETACHAR    BV04
 #define INPUT_FLAG_CONVERTMETACHAR    BV04
+#define INPUT_FLAG_REDRAW             BV05
 
 
 #define PORT_FLAG_PRIVATE             BV01
 #define PORT_FLAG_PRIVATE             BV01
 #define PORT_FLAG_REQUEST             BV02
 #define PORT_FLAG_REQUEST             BV02
@@ -682,6 +683,7 @@ enum operators
 #define LIST_FLAG_INHERIT             BV11
 #define LIST_FLAG_INHERIT             BV11
 #define LIST_FLAG_REGEX               BV12
 #define LIST_FLAG_REGEX               BV12
 #define LIST_FLAG_NEST                BV13
 #define LIST_FLAG_NEST                BV13
+#define LIST_FLAG_CASE                BV14
 #define LIST_FLAG_DEFAULT             LIST_FLAG_MESSAGE
 #define LIST_FLAG_DEFAULT             LIST_FLAG_MESSAGE
 
 
 #define NODE_FLAG_ONESHOT             BV01 // unused
 #define NODE_FLAG_ONESHOT             BV01 // unused
@@ -764,6 +766,7 @@ enum operators
 #define MAP_FLAG_QUIET                BV17
 #define MAP_FLAG_QUIET                BV17
 #define MAP_FLAG_READ                 BV18
 #define MAP_FLAG_READ                 BV18
 #define MAP_FLAG_PANCAKE              BV19
 #define MAP_FLAG_PANCAKE              BV19
+#define MAP_FLAG_FAST                 BV20
 
 
 #define MAP_SEARCH_NAME                0
 #define MAP_SEARCH_NAME                0
 #define MAP_SEARCH_EXITS               1
 #define MAP_SEARCH_EXITS               1
@@ -1115,7 +1118,7 @@ struct tintin_data
 	char                 *  attach_file;
 	char                 *  attach_file;
 	int                     attach_pid;
 	int                     attach_pid;
 	int                     attach_sock;
 	int                     attach_sock;
-	int                     daemon;
+//	int                     daemon;
 	char                  * buf;
 	char                  * buf;
 	char                  * out;
 	char                  * out;
 	char                  * mud_output_buf;
 	char                  * mud_output_buf;
@@ -1145,6 +1148,7 @@ struct tintin_data
 	char                    tintin_char;
 	char                    tintin_char;
 	char                    verbatim_char;
 	char                    verbatim_char;
 	char                    repeat_char;
 	char                    repeat_char;
+	int                     match[303];
 	char                  * vars[100];
 	char                  * vars[100];
 	char                  * cmds[100];
 	char                  * cmds[100];
 	int                     args[100];
 	int                     args[100];
@@ -1626,7 +1630,7 @@ struct window_data
 #define DO_EDIT(edit)          struct session *edit (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_EDIT(edit)          struct session *edit (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_HISTORY(history)            void history (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_HISTORY(history)            void history (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_LINE(line)          struct session *line (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3)
 #define DO_LINE(line)          struct session *line (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3)
-#define DO_MAP(map)                        void map (struct session *ses, char *arg, char *arg1, char *arg2)
+#define DO_MAP(map)                        void map (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3)
 #define DO_PATH(path)                     void path (struct session *ses, char *arg)
 #define DO_PATH(path)                     void path (struct session *ses, char *arg)
 #define DO_PORT(port)          struct session *port (struct session *ses, char *arg, char *arg1, char *arg2)
 #define DO_PORT(port)          struct session *port (struct session *ses, char *arg, char *arg1, char *arg2)
 
 
@@ -1646,7 +1650,7 @@ typedef void            DAEMON  (struct session *ses, char *arg, char *arg1, cha
 typedef struct session *EDIT    (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef struct session *EDIT    (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef void            HISTORY (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef void            HISTORY (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef struct session *LINE    (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3);
 typedef struct session *LINE    (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3);
-typedef void            MAP     (struct session *ses, char *arg, char *arg1, char *arg2);
+typedef void            MAP     (struct session *ses, char *arg, char *arg1, char *arg2, char *arg3);
 typedef void            MSDP    (struct session *ses, struct port_data *buddy, int index);
 typedef void            MSDP    (struct session *ses, struct port_data *buddy, int index);
 typedef void            PATH    (struct session *ses, char *arg);
 typedef void            PATH    (struct session *ses, char *arg);
 typedef struct session *PORT    (struct session *ses, char *arg, char *arg1, char *arg2);
 typedef struct session *PORT    (struct session *ses, char *arg, char *arg1, char *arg2);
@@ -1667,6 +1671,7 @@ struct charset_type
 {
 {
 	char                  * name;
 	char                  * name;
 	char                  * html;
 	char                  * html;
+	char                  * mnes;
 	int                     flags;
 	int                     flags;
 };
 };
 
 
@@ -1753,14 +1758,6 @@ struct list_type
 	int                     flags;
 	int                     flags;
 };
 };
 
 
-
-struct line_type
-{
-	char                  * name;
-	LINE                  * fun;
-	char                  * desc;
-};
-
 struct map_type
 struct map_type
 {
 {
 	char                  * name;
 	char                  * name;
@@ -2072,7 +2069,7 @@ extern DO_COMMAND(do_map);
 
 
 extern void delete_room_data(struct room_data *room);
 extern void delete_room_data(struct room_data *room);
 extern  int follow_map(struct session *ses, char *argument);
 extern  int follow_map(struct session *ses, char *argument);
-extern void show_vtmap(struct session *ses);
+extern void show_vtmap(struct session *ses, int clear);
 extern void map_mouse_handler(struct session *ses, char *left, char *right, int row, int col, int rev_row, int rev_col, int height, int width);
 extern void map_mouse_handler(struct session *ses, char *left, char *right, int row, int col, int rev_row, int rev_col, int height, int width);
 extern  int delete_map(struct session *ses);
 extern  int delete_map(struct session *ses);
 
 
@@ -2359,6 +2356,7 @@ extern DO_LINE(line_convert);
 extern DO_LINE(line_debug);
 extern DO_LINE(line_debug);
 extern DO_LINE(line_gag);
 extern DO_LINE(line_gag);
 extern DO_LINE(line_ignore);
 extern DO_LINE(line_ignore);
+extern DO_LINE(line_json);
 extern DO_LINE(line_local);
 extern DO_LINE(line_local);
 extern DO_LINE(line_log);
 extern DO_LINE(line_log);
 extern DO_LINE(line_logmode);
 extern DO_LINE(line_logmode);
@@ -2490,8 +2488,8 @@ extern void msdp_command_send(struct session *ses, struct port_data *buddy, int
 extern void msdp_command_unreport(struct session *ses, struct port_data *buddy, int index);
 extern void msdp_command_unreport(struct session *ses, struct port_data *buddy, int index);
 extern void msdp_configure_arachnos(struct session *ses, struct port_data *buddy, int index);
 extern void msdp_configure_arachnos(struct session *ses, struct port_data *buddy, int index);
 extern void write_msdp_to_descriptor(struct session *ses, struct port_data *buddy, char *src, int length);
 extern void write_msdp_to_descriptor(struct session *ses, struct port_data *buddy, char *src, int length);
-extern  int msdp2json(unsigned char *src, int srclen, char *out);
-extern  int json2msdp(unsigned char *src, int srclen, char *out);
+extern  int msdp2gmcp(unsigned char *src, int srclen, char *out);
+extern  int gmcp2msdp(unsigned char *src, int srclen, char *out);
 extern  int tintin2msdp(char *src, char *out);
 extern  int tintin2msdp(char *src, char *out);
 extern void arachnos_devel(struct session *ses, char *fmt, ...);
 extern void arachnos_devel(struct session *ses, char *fmt, ...);
 extern void arachnos_mudlist(struct session *ses, char *fmt, ...);
 extern void arachnos_mudlist(struct session *ses, char *fmt, ...);
@@ -2519,6 +2517,8 @@ extern struct listnode *get_nest_node_key(struct listroot *root, char *variable,
 extern struct listnode *get_nest_node_val(struct listroot *root, char *variable, char **result, int def);
 extern struct listnode *get_nest_node_val(struct listroot *root, char *variable, char **result, int def);
 extern int get_nest_index(struct listroot *root, char *variable, char **result, int def);
 extern int get_nest_index(struct listroot *root, char *variable, char **result, int def);
 extern void show_nest_node(struct listnode *node, char **result, int initialize);
 extern void show_nest_node(struct listnode *node, char **result, int initialize);
+
+extern void view_nest_node_json(struct listnode *node, char **str_result, int nest, int initialize);
 extern void view_nest_node(struct listnode *node, char **str_result, int nest, int initialize, int color);
 extern void view_nest_node(struct listnode *node, char **str_result, int nest, int initialize, int color);
 extern struct listnode *set_nest_node_ses(struct session *ses, char *arg1, char *format, ...);
 extern struct listnode *set_nest_node_ses(struct session *ses, char *arg1, char *format, ...);
 extern struct listnode *add_nest_node_ses(struct session *ses, char *arg1, char *format, ...);
 extern struct listnode *add_nest_node_ses(struct session *ses, char *arg1, char *format, ...);
@@ -2544,6 +2544,7 @@ extern void process_mud_output(struct session *ses, char *linebuf, int prompt);
 #define __PARSE_H__
 #define __PARSE_H__
 
 
 extern  int is_abbrev(char *str1, char *str2);
 extern  int is_abbrev(char *str1, char *str2);
+extern  int is_abbrev_cmp(char *str1, char *str2);
 extern  int is_member(char *str1, char *str2);
 extern  int is_member(char *str1, char *str2);
 extern  int is_vowel(char *str);
 extern  int is_vowel(char *str);
 extern void filename_string(char *input, char *output);
 extern void filename_string(char *input, char *output);
@@ -2842,7 +2843,6 @@ extern struct daemon_type daemon_table[];
 extern struct edit_type edit_table[];
 extern struct edit_type edit_table[];
 extern struct event_type event_table[];
 extern struct event_type event_table[];
 extern struct history_type history_table[];
 extern struct history_type history_table[];
-extern struct line_type line_table[];
 extern struct list_type list_table[LIST_MAX];
 extern struct list_type list_table[LIST_MAX];
 extern struct map_type map_table[];
 extern struct map_type map_table[];
 extern struct path_type path_table[];
 extern struct path_type path_table[];
@@ -2888,6 +2888,7 @@ extern void  refresh_session_terminal(struct session *ses);
 extern void  echo_on(struct session *ses);
 extern void  echo_on(struct session *ses);
 extern void  echo_off(struct session *ses);
 extern void  echo_off(struct session *ses);
 extern void  init_terminal_size(struct session *ses);
 extern void  init_terminal_size(struct session *ses);
+extern void  init_resize(struct session *ses, int rows, int cols, int height, int width);
 extern  int  get_scroll_rows(struct session *ses);
 extern  int  get_scroll_rows(struct session *ses);
 extern  int  get_scroll_cols(struct session *ses);
 extern  int  get_scroll_cols(struct session *ses);
 extern char *get_charset(struct session *ses);
 extern char *get_charset(struct session *ses);
@@ -2945,6 +2946,7 @@ extern char *script_viewer(struct session *ses, char *str);
 #define __TRIGGER_H__
 #define __TRIGGER_H__
 
 
 extern DO_COMMAND(do_delay);
 extern DO_COMMAND(do_delay);
+extern DO_COMMAND(do_function);
 
 
 extern void check_all_actions(struct session *ses, char *original, char *line, char *buf);
 extern void check_all_actions(struct session *ses, char *original, char *line, char *buf);
 extern  int check_all_aliases(struct session *ses, char *input);
 extern  int check_all_aliases(struct session *ses, char *input);

+ 22 - 3
src/tokenize.c

@@ -313,8 +313,10 @@ char *get_arg_foreach(struct scriptroot *root, struct scriptnode *token)
 
 
 	if (*token->data->arg == COMMAND_SEPARATOR)
 	if (*token->data->arg == COMMAND_SEPARATOR)
 	{
 	{
-		token->data->arg++;
+		*token->data->arg = ' ';
+//		token->data->arg++;
 	}
 	}
+
 	return buf;
 	return buf;
 }
 }
 
 
@@ -1094,10 +1096,20 @@ char *write_script(struct session *ses, struct scriptroot *root)
 				break;
 				break;
 
 
 			case TOKEN_TYPE_COMMAND:
 			case TOKEN_TYPE_COMMAND:
-			case TOKEN_TYPE_RETURN:
 				cat_sprintf(buf, "%s%c%s%s%s", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, *token->str ? " " : "", token->str);
 				cat_sprintf(buf, "%s%c%s%s%s", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, *token->str ? " " : "", token->str);
 				break;
 				break;
 
 
+			case TOKEN_TYPE_RETURN:
+				if (*token->str)
+				{
+					cat_sprintf(buf, "%s%c%s {%s}", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, token->str);
+				}
+				else
+				{
+					cat_sprintf(buf, "%s%c%s", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name);
+				}
+				break;
+
 			case TOKEN_TYPE_ELSE:
 			case TOKEN_TYPE_ELSE:
 				cat_sprintf(buf, "%s%c%s\n%s{\n", indent(token->lvl), gtd->tintin_char, token->str, indent(token->lvl));
 				cat_sprintf(buf, "%s%c%s\n%s{\n", indent(token->lvl), gtd->tintin_char, token->str, indent(token->lvl));
 				break;
 				break;
@@ -1182,7 +1194,14 @@ char *view_script(struct session *ses, struct scriptroot *root)
 				break;
 				break;
 
 
 			case TOKEN_TYPE_RETURN:
 			case TOKEN_TYPE_RETURN:
-				cat_sprintf(buf, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s" COLOR_STRING "%s%s", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, *token->str ? " " : "", token->str);
+				if (*token->str)
+				{
+					cat_sprintf(buf, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s " COLOR_BRACE "{" COLOR_STRING "%s" COLOR_BRACE "}", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name, token->str);
+				}
+				else
+				{
+					cat_sprintf(buf, "%s" COLOR_TINTIN "%c" COLOR_STATEMENT "%s", indent(token->lvl), gtd->tintin_char, command_table[token->cmd].name);
+				}
 				break;
 				break;
 
 
 			case TOKEN_TYPE_COMMAND:
 			case TOKEN_TYPE_COMMAND:

+ 22 - 4
src/trigger.c

@@ -276,6 +276,15 @@ DO_COMMAND(do_button)
 
 
 			node->val16[index] = (short) get_number(ses, arg2);
 			node->val16[index] = (short) get_number(ses, arg2);
 
 
+			if (node->val16[index] == 0)
+			{
+				show_error(ses, LIST_BUTTON, "#ERROR: #BUTTON {%s} IS NOT A VALID SQUARE COORDINATE.", arg1);
+
+				delete_node_list(ses, LIST_BUTTON, node);
+
+				return ses;
+			}
+
 			if (*arg == COMMAND_SEPARATOR)
 			if (*arg == COMMAND_SEPARATOR)
 			{
 			{
 				arg++;
 				arg++;
@@ -544,8 +553,10 @@ void check_all_gags(struct session *ses, char *original, char *line)
 			{
 			{
 				delete_node_list(ses, LIST_GAG, node);
 				delete_node_list(ses, LIST_GAG, node);
 			}
 			}
-			ses->gagline++;
-
+			if (ses->gagline == 0)
+			{
+				ses->gagline = 1;
+			}
 			return;
 			return;
 		}
 		}
 	}
 	}
@@ -798,13 +809,20 @@ int check_all_prompts(struct session *ses, char *original, char *line)
 
 
 			show_debug(ses, LIST_PROMPT, "#DEBUG PROMPT {%s}", node->arg1);
 			show_debug(ses, LIST_PROMPT, "#DEBUG PROMPT {%s}", node->arg1);
 
 
-			split_show(ses, original, node->arg3, node->arg4);
+			if (strcmp(node->arg3, "0"))
+			{
+				split_show(ses, original, node->arg3, node->arg4);
+
+				if (ses->gagline == 0)
+				{
+					ses->gagline = 1;
+				}
+			}
 
 
 			if (node->shots && --node->shots == 0)
 			if (node->shots && --node->shots == 0)
 			{
 			{
 				delete_node_list(ses, LIST_PROMPT, node);
 				delete_node_list(ses, LIST_PROMPT, node);
 			}
 			}
-			ses->gagline = 1;
 		}
 		}
 	}
 	}
 	return 0;
 	return 0;

+ 5 - 1
src/update.c

@@ -733,6 +733,10 @@ void update_daemon(void)
 
 
 				if (rv <= 0)
 				if (rv <= 0)
 				{
 				{
+					if (rv < 0)
+					{
+						syserr_printf(gtd->ses, "update_daemon: attach_sock: read:");
+					}
 					gtd->attach_sock = close(gtd->attach_sock);
 					gtd->attach_sock = close(gtd->attach_sock);
 
 
 					winch_handler(0);
 					winch_handler(0);
@@ -1094,7 +1098,7 @@ void terminal_update(void)
 		{
 		{
 			DEL_BIT(ses->flags, SES_FLAG_UPDATEVTMAP);
 			DEL_BIT(ses->flags, SES_FLAG_UPDATEVTMAP);
 
 
-			show_vtmap(ses);
+			show_vtmap(ses, 0);
 
 
 			check_all_events(ses, EVENT_FLAG_MAP, 0, 0, "MAP UPDATED VTMAP");
 			check_all_events(ses, EVENT_FLAG_MAP, 0, 0, "MAP UPDATED VTMAP");
 		}
 		}

+ 4 - 10
src/variable.c

@@ -250,7 +250,7 @@ DO_COMMAND(do_cat)
 
 
 		if ((node = search_nest_node_ses(ses, arg1)) == NULL)
 		if ((node = search_nest_node_ses(ses, arg1)) == NULL)
 		{
 		{
-			arg = sub_arg_in_braces(ses, arg, str, GET_ALL, SUB_VAR|SUB_FUN);
+//			arg = sub_arg_in_braces(ses, arg, str, GET_ALL, SUB_VAR|SUB_FUN);
 
 
 			node = set_nest_node(ses->list[LIST_VARIABLE], arg1, "");
 			node = set_nest_node(ses->list[LIST_VARIABLE], arg1, "");
 		}
 		}
@@ -329,20 +329,14 @@ DO_COMMAND(do_replace)
 				break;
 				break;
 			}
 			}
 
 
-			ptm = strstr(pti, gtd->cmds[0]);
-
-			if (ptm == NULL)
-			{
-				break;
-			}
-
-			*ptm = 0;
+			ptm = pti + gtd->match[0]; *ptm = 0;
+			ptm = pti + gtd->match[1];
 
 
 			substitute(ses, arg3, tmp, SUB_CMD|SUB_FUN);
 			substitute(ses, arg3, tmp, SUB_CMD|SUB_FUN);
 
 
 			str_cat_printf(&str, "%s%s", pti, tmp);
 			str_cat_printf(&str, "%s%s", pti, tmp);
 
 
-			pti = ptm + strlen(gtd->cmds[0]);
+			pti = ptm;
 		}
 		}
 		while (tintin_regexp(ses, NULL, pti, arg2, 0, REGEX_FLAG_CMD));
 		while (tintin_regexp(ses, NULL, pti, arg2, 0, REGEX_FLAG_CMD));
 
 

+ 7 - 1
src/vt102.c

@@ -100,7 +100,8 @@ void goto_pos(struct session *ses, int row, int col)
 {
 {
 	if (row < 1 || col < 1)
 	if (row < 1 || col < 1)
 	{
 	{
-		print_stdout(0, 0, "debug: goto_pos(%d,%d)\n",row,col);
+		tintin_printf2(NULL, "\e[1;31merror: invalid row,col: goto_pos(%d,%d)\n",row,col);
+
 		dump_stack();
 		dump_stack();
 
 
 		return;
 		return;
@@ -658,6 +659,11 @@ char *strip_vt102_strstr(char *str, char *buf, int *len)
 
 
 	while (*pts)
 	while (*pts)
 	{
 	{
+		while (skip_vt102_codes(pts))
+		{
+			pts += skip_vt102_codes(pts);
+		}
+
 		pti = pts;
 		pti = pts;
 		ptm = buf;
 		ptm = buf;
 
 

部分文件因为文件数量过多而无法显示