Scandum 3 жил өмнө
parent
commit
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.
@@ -33,7 +45,7 @@ se room has #map set roomsymbol {<faa>\\}
 
   - 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.
 
@@ -65,8 +77,6 @@ se room has #map set roomsymbol {<faa>\\}
 
   - look into transparent drawing
 
-  - Add #line gag 2 +2 -2 support.
-
   - VT2020
 
   - 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.
 
+  - 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
   - look into writing script to drag rooms + void with mouse
   - 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>
 <pre>
 <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>
 
-</span><span style='color:#FF5'>         INDEX
+         INDEX
 
 </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,
          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>
 
 </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'>
          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>
 
 </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
          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>
 
 </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
          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>
 
 </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
          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>
 
 </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:#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
 
@@ -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.
          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>
 
 </span><span style='color:#FF5'>         GREETING
 
 </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'>      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'>#
@@ -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
          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>
 
 </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>
 
 </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.
 
 </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
 
@@ -1196,7 +1202,7 @@ on the right being the regex. For example {bla} == {%*a} would evaluate as 1.
          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>
 
 </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'>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
 
@@ -1527,7 +1533,7 @@ easiest way to accomplish that.
          #showme {@two{&dollar;test}} in session one would print the value of &dollar;test,
          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>
 
 </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'>: #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>
 
 </span><span style='color:#FF5'>         STATEMENTS
@@ -1584,7 +1590,7 @@ easiest way to accomplish that.
          #switch {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>
 
 </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.
           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>
 
 </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
          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>
 
 </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}.
 
          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  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
 ------------------------------------------------------------------------------
 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.
 
 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.
 
 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.
 
 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
                for now.
 

+ 139 - 132
src/banner.c

@@ -27,6 +27,8 @@
 
 #include "gui.h"
 
+#define BANNER_FLAG_DUPLICATE BV01
+
 void banner_create(struct session *ses, char *name, char *arg)
 {
 	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)
 {
 	struct listnode *node;
@@ -85,7 +97,7 @@ void banner_expires(struct session *ses, char *name, char *arg, char *arg1)
 
 	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"
 		"  -- 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_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);
 
@@ -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"
 		"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);
@@ -142,7 +172,8 @@ void banner_init(struct session *ses, char *arg1)
 
 	banner_website(ses, "3Kingdoms", "http://3k.org", arg1);
 	banner_address(ses, "3Kingdoms", "3K 3k.org 3000", arg1);
-	banner_expires(ses, "3Kingdoms", "2027", arg1);
+	banner_expires(ses, "3Kingdoms", "2028", 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_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);
 
@@ -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_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_desc(ses, "Carrion Fields",
@@ -322,6 +403,10 @@ void banner_save(struct session *ses, char *arg1)
 	{
 		node = gtd->banner_list->list[index];
 
+		if (HAS_BIT(node->shots, BANNER_FLAG_DUPLICATE))
+		{
+			continue;
+		}
 		sprintf(name, "info[BANNERS][%s]", node->arg1);
 
 		arg1 = node->arg4;
@@ -379,6 +464,30 @@ void banner_test(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];
 	FILE *fp;
 
@@ -396,6 +505,7 @@ struct session *banner_gui(struct session *ses, char *arg1)
 	fclose(fp);
 
 	return command(ses, do_line, "quiet #read %s", filename);
+*/
 }
 
 DO_COMMAND(do_banner)
@@ -426,10 +536,13 @@ DO_COMMAND(do_banner)
 	{
 		banner_save(ses, arg1);
 	}
+	else if (is_abbrev(arg1, "HELP"))
+	{
+		tintin_printf2(ses, "#SYNTAX: #BANNER {GUI|INIT|LIST|RANDOM|SAVE|TEST}");
+	}	
 	else
 	{
 		banner_list(ses, arg1);
-//		tintin_printf2(ses, "#SYNTAX: #BANNER {INIT|LIST|RANDOM|TEST}");
 	}
 	return ses;
 }
@@ -437,36 +550,6 @@ DO_COMMAND(do_banner)
 // 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,
  		1800000000,
@@ -496,25 +579,6 @@ DO_COMMAND(do_banner)
 		"\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 *
 		1323541590, * 10 Dec 2011 *
@@ -533,63 +597,6 @@ DO_COMMAND(do_banner)
 		"\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 *
 		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);
 
-			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++)
 			{

+ 57 - 5
src/command.c

@@ -27,15 +27,63 @@
 
 struct command_type command_table[];
 
+size_t command_size();
+
 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);
 
 	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))
 		{
@@ -57,7 +105,7 @@ DO_COMMAND(do_commands)
 			cat_sprintf(arg2, "%s%20s", COLOR_STATEMENT, command_table[cmd].name);
 		}
 	}
-
+*/
 	if (*arg2)
 	{
 		tintin_puts2(ses, arg2);
@@ -172,7 +220,6 @@ extern DO_COMMAND(do_debug);
 extern DO_COMMAND(do_echo);
 extern DO_COMMAND(do_event);
 extern DO_COMMAND(do_format);
-extern DO_COMMAND(do_function);
 extern DO_COMMAND(do_gag);
 extern DO_COMMAND(do_highlight);
 extern DO_COMMAND(do_ignore);
@@ -266,7 +313,7 @@ struct command_type command_table[] =
 	{    "log",               do_log,               2, TOKEN_TYPE_COMMAND },
 	{    "loop",              do_nop,               3, TOKEN_TYPE_LOOP    },
 	{    "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 },
 	{    "message",           do_message,           2, 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 },
 	{    "",                  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)
 			{
-				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;
 			}
@@ -881,6 +881,8 @@ DO_CONFIG(config_telnet)
 		}
 		else if (is_abbrev(arg2, "OFF"))
 		{
+			ses->read_len = 0;
+
 			DEL_BIT(ses->telopts, TELOPT_FLAG_DEBUG);
 			DEL_BIT(ses->config_flags, CONFIG_FLAG_TELNET);
 		}

+ 11 - 13
src/cursor.c

@@ -2021,23 +2021,21 @@ DO_CURSOR(cursor_redraw_line)
 		return;
 	}
 
+	SET_BIT(gtd->ses->input->flags, INPUT_FLAG_REDRAW);
+
 	if (inputline_editor())
 	{
 		cursor_redraw_singleline(ses, "");
-
-		pop_call();
-		return;
 	}
-
-	if (inputline_multiline())
+	else if (inputline_multiline())
 	{
 		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();
 	return;
@@ -2700,7 +2698,7 @@ DO_CURSOR(cursor_tab)
 
 		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
 		{
@@ -2722,7 +2720,7 @@ DO_CURSOR(cursor_tab)
 
 		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
 		{
@@ -2731,6 +2729,6 @@ DO_CURSOR(cursor_tab)
 	}
 	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");
 
-		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;
 	}
 
+	tintin_printf2(ses, "do_attach: succes");
+
 	return;
 }
 

+ 51 - 6
src/data.c

@@ -499,6 +499,31 @@ int bsearch_alpha_list(struct listroot *root, char *text, int seek)
 	bot = 0;
 	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)
 	{
 		mid = top / 2;
@@ -625,7 +650,7 @@ int bsearch_alnum_list(struct listroot *root, char *text, int seek)
 
 		if (noi)
 		{
-			srt = (toi < toj) ? -1 : (toi > toj) ? 1 : 0;
+			srt = !noj ? 1 : (toi < toj) ? -1 : (toi > toj) ? 1 : 0;
 		}
 		else if (noj)
 		{
@@ -650,7 +675,6 @@ int bsearch_alnum_list(struct listroot *root, char *text, int seek)
 		{
 			bot = val + 1;
 		}
-
 		val = bot + (top - bot) / 2;
 	}
 
@@ -1371,6 +1395,31 @@ DO_COMMAND(do_info)
 				}
 				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:
 				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: TERM           = %s", gtd->system->term);
 						tintin_printf2(ses, "#INFO SYSTEM: TINTIN         = %s", gtd->system->tt_dir);
-						tintin_printf2(ses, "#INFO SYSTEM: DETACH_PORT    = %d", gtd->detach_port);
-						tintin_printf2(ses, "#INFO SYSTEM: DETACH_FILE    = %s", gtd->detach_port ? gtd->detach_file : "");
-						tintin_printf2(ses, "#INFO SYSTEM: ATTACH_SOCK    = %d", gtd->attach_sock);
-						tintin_printf2(ses, "#INFO SYSTEM: ATTACH_FILE    = %s", gtd->attach_sock ? gtd->attach_file : "");
 					}
 				}
 				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;
 	}
 
+	if (HAS_BIT(flags, DRAW_FLAG_VER))
+	{
+		max_width = 1 + *bot_col - *top_col;
+	}
+
 	if (HAS_BIT(flags, DRAW_FLAG_SCROLL))
 	{
 		max_height = gtd->screen->rows * 10;
@@ -1754,7 +1759,7 @@ DO_DRAW(draw_map)
 	{
 		sprintf(arg, "{%d} {%d} {SAVE}", map_rows, map_cols);
 
-		map_map(ses, arg, arg1, arg2);
+		map_map(ses, arg, arg1, arg2, arg3);
 	}
 	else
 	{
@@ -2532,10 +2537,22 @@ DO_DRAW(draw_text)
 	{
 		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
 	{
-		while (*txt && height > rows)
+		while (*txt && height && height > rows)
 		{
 			txt = strchr(txt, '\n');
+
 			txt++;
 			height--;
 		}
@@ -2598,7 +2616,7 @@ DO_DRAW(draw_text)
 		}
 		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);
 			}

+ 177 - 152
src/gui.h

@@ -1,5 +1,5 @@
 char *tt_gui = "#line quiet #port init gui 0\n"
-"\n"
+
 "#function gui_link\n"
 "{\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"
 "	#return $gui[link]\n"
 "}\n"
-"\n"
+
 "#function gui_profile_link\n"
 "{\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"
 "	#return $gui[link]\n"
 "}\n"
-"\n"
+
 "#event {PRESSED SECURE LINK COMMAND MOUSE BUTTON ONE} {%4}\n"
-"\n"
+
 "#event {PRESSED SECURE LINK COMMAND MOUSE BUTTON THREE}\n"
 "{\n"
 "	#line ignore #showme {<138>Group<178>: %6 <138>Command<178>: %4}\n"
 "}\n"
-"\n"
+
 "#event {PRESSED SECURE LINK WORLD MOUSE BUTTON ONE}\n"
 "{\n"
 "	world_click {%4}\n"
 "}\n"
-"\n"
+
 "#event {PRESSED SECURE LINK WORLD MOUSE BUTTON THREE}\n"
 "{\n"
 "	#line ignore #showme {<138>Group<178>: %6 <138>Command<178>: %4}\n"
 "}\n"
-"\n"
+
 "#event {DOUBLE-CLICKED SECURE LINK WORLD MOUSE BUTTON ONE} {gui_connect}\n"
-"\n"
+
 "#button {-2 28 -2 -28;PRESSED MOUSE BUTTON ONE}\n"
 "{\n"
 "	profile_tab_update;\n"
-"\n"
+
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
-"\n"
+
 "	profile_tab_set INPUT\n"
 "}\n"
-"\n"
+
 "#alias {gui_worlds}   {world_tab worlds}\n"
 "#alias {gui_sponsors} {world_tab sponsors}\n"
-"\n"
+
 "#alias {world_tab}\n"
 "{\n"
 "	#var gui[world_tab] %1;\n"
-"\n"
+
 "	#class world_tab kill;\n"
-"\n"
+
 "	#if {{$gui[world_tab]} == {worlds}}\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"
 "	#else\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"
+
 "	#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"
 "}\n"
-"\n"
+
 "#alias {draw_world}\n"
 "{\n"
 "	#if {{%2} == {%3}}\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"
 "	#else\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"
+
 "#alias {world_click}\n"
 "{\n"
 "	#var gui[active] {%1};\n"
-"\n"
-"	profile_tab_cancel;\n"
-"\n"
+
+"	#nop profile_tab_cancel;\n"
+
 "	#if {{$gui[world_tab]} == {worlds}}\n"
 "	{\n"
 "		#var gui[new] {$worldlist[%1]};\n"
-"\n"
+
 "		draw_worlds {%1}\n"
 "	};\n"
 "	#else\n"
 "	{\n"
 "		#var gui[new] {$info[BANNERS][%1]} {{SSL}{off}} {{FILE}{}} {{CHARACTER}{}} {{PASSWORD}{}} {{INPUT}{}};\n"
-"\n"
-"		draw_sponsors {%1}\n"
+
+"		draw_sponsors\n"
 "	};\n"
 "	reload_profile_tab;\n"
-"\n"
+
 "	#buffer end\n"
 "}\n"
-"\n"
+
 "#function {gui_size_left}\n"
 "{\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"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {gui_draw_left}\n"
 "{\n"
 "	#if {{$gui[world_tab]} == {worlds}}\n"
@@ -126,68 +126,90 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		draw_sponsors\n"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {draw_worlds}\n"
 "{\n"
 "	#class world_tab kill;\n"
 "	#class profile_tab kill;\n"
-"\n"
+
 "	#draw tile 4 1 -4 26 { };\n"
-"\n"
+
 "	#if {&worldlist[] == 0}\n"
 "	{\n"
 "		#return;\n"
 "	};\n"
-"\n"
-"	#local index 1;\n"
+
+"	#local index $gui[index];\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"
 "	{\n"
-"		draw_world {$offset} {$worldlist[+$index][NAME]} {%1};\n"
-"\n"
+"		draw_world {$offset} {$worldlist[+$index][NAME]} {$gui[active]};\n"
+
 "		#math offset $offset + 1;\n"
-"\n"
-"		#if {$offset * 3 > $gui[rows] - 6}\n"
+
+"		#if {$offset * 2 + 1 > $gui[rows] - 6}\n"
 "		{\n"
 "			#break;\n"
 "		};\n"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {draw_sponsors}\n"
 "{\n"
 "	#class world_tab kill;\n"
 "	#class profile_tab kill;\n"
-"\n"
+
 "	#draw tile 4 1 -4 26 { };\n"
-"\n"
+
 "	#if {&info[BANNERS][] == 0}\n"
 "	{\n"
 "		#line ignore #showme <faa>Sponsors: No banners found.;\n"
 "		#return;\n"
 "	};\n"
-"\n"
-"	#local index 1;\n"
+
+"	#local index $gui[index];\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"
 "	{\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"
-"\n"
-"		#if {$offset * 3 > $gui[rows] - 6}\n"
+
+"		#if {$offset * 2 + 1 > $gui[rows] - 6}\n"
 "		{\n"
-"			#break;\n"
-"		};\n"
+"			#break\n"
+"		}\n"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {gui_tab_forward}\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#switch {{$input_name}}\n"
 "	{\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"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {gui_tab_backward}\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#switch {{$input_name}}\n"
 "	{\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"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_cycle}\n"
 "{\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"
-"\n"
+
 "	profile_tab_set %1;\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_pull}\n"
 "{\n"
 "	#if {{%1} == {PASSWORD}}\n"
@@ -242,17 +264,17 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#cursor clear;\n"
 "	profile_tab %1\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_update}\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|INPUT|HOST|PORT|FILE|CHARACTER|PASSWORD}}\n"
 "	{\n"
 "		profile_tab_pull &1\n"
 "	}\n"
 "}\n"
-"\n"
+
 "#function gui_toggle\n"
 "{\n"
 "	#if {{%1} == {%2}}\n"
@@ -261,7 +283,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	};\n"
 "	#return %2\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_set}\n"
 "{\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"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_input}\n"
 "{\n"
 "	#var gui[input][%5] {{top_row}{%1}{top_col}{%2}{bot_row}{%3}{bot_col}{%4}};\n"
-"\n"
+
 "	#if {{%6} == {toggle}}\n"
 "	{\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"
+
 "#function b64z\n"
 "{\n"
 "	#if {{%0} === {}}\n"
@@ -314,7 +336,7 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#format temp %+64z {%0};\n"
 "	#return $temp\n"
 "}\n"
-"\n"
+
 "#function b64Z\n"
 "{\n"
 "	#if {{%0} === {}}\n"
@@ -325,14 +347,14 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "	#format temp %+64Z {%0};\n"
 "	#return $temp\n"
 "}\n"
-"\n"
+
 "#function starout\n"
 "{\n"
 "	#local temp {%0};\n"
 "	#replace temp {%.} {*};\n"
 "	#return $temp\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_draw}\n"
 "{\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"
 "	};\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab}\n"
 "{\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"
 "	};\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_cancel}\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|HOST|PORT|SSL|FILE|CHARACTER|PASSWORD}}\n"
 "	{\n"
 "		profile_tab_cycle INPUT &1\n"
 "	};\n"
-"\n"
+
 "	#screen clear square 1 -26 -1 -1;\n"
 "	#var gui[profile_tab] 0;\n"
 "	#math gui[index] 1\n"
 "}\n"
-"\n"
+
 "#alias {profile_tab_save}\n"
 "{\n"
 "	#screen get INPUT_NAME input_name;\n"
-"\n"
+
 "	#regex {$input_name} {profile_tab_{NAME|ALIAS|INPUT|HOST|PORT|SSL|FILE|CHARACTER|PASSWORD}}\n"
 "	{\n"
 "		profile_tab_pull &1\n"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {gui_new}\n"
 "{\n"
 "	#class profile_tab kill;\n"
-"\n"
+
 "	#var gui[new] {{NAME}{} {ALIAS}{} {HOST}{} {PORT}{} {SSL}{off} {FILE}{} {CHARACTER}{} {PASSWORD}{} {INPUT}{}};\n"
-"\n"
+
 "	reload_profile_tab\n"
 "}\n"
-"\n"
+
 "#alias {gui_connect}\n"
 "{\n"
 "	#if {&gui[new] == 0}\n"
 "	{\n"
 "		#line ignore #showme <faa>Connect: No world selected;#return;\n"
 "	};\n"
-"\n"
+
 "	profile_tab_update;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
 "	#cursor clear;\n"
-"\n"
+
 "	#if {{$gui[new][ALIAS]} == {}}\n"
 "	{\n"
 "		#line ignore #showme <faa>Connect: No alias set;\n"
 "		#return\n"
 "	};\n"
-"\n"
+
 "	#if {{$gui[new][HOST]} == {}}\n"
 "	{\n"
 "		#line ignore #showme <faa>Connect: No host set;\n"
 "		#return\n"
 "	};\n"
-"\n"
+
 "	#if {{$gui[new][PORT]} == {}}\n"
 "	{\n"
 "		#line ignore #showme <faa>Connect: No port set;\n"
 "		#return\n"
 "	};\n"
-"\n"
+
 "	#line ignore #showme {<acf>Connecting to <ffa>$gui[new][NAME]<acf>..};\n"
-"\n"
+
 "	#config mouse off;\n"
-"\n"
+
 "	#buffer refresh;\n"
-"\n"
+
 "	#if {{$gui[new][SSL]} == {off}}\n"
 "	{\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"
 "		#ssl $gui[new][ALIAS] $gui[new][HOST] $gui[new][PORT] $gui[new][FILE];\n"
 "	};\n"
-"\n"
+
 "	#info SESSION save;\n"
-"\n"
+
 "	#if {{$info[SESSION][NAME]} !== {gui}}\n"
 "	{\n"
 "		#if {{@gui{$gui[new][CHARACTER]}} !== {}}\n"
 "		{\n"
 "			#send {@gui{$gui[new][CHARACTER]}};\n"
-"\n"
+
 "			#if {{@gui{$gui[new][PASSWORD]}} !== {}}\n"
 "			{\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"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {gui_save}\n"
 "{\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"
 "		#return;\n"
 "	};\n"
-"\n"
+
 "	profile_tab_update;\n"
-"\n"
+
 "	#if {{$gui[new][NAME]} === {}}\n"
 "	{\n"
 "		#showme {<faa>Save: No profile name set.};\n"
 "		#return;\n"
 "	};\n"
-"\n"
+
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
-"\n"
+
 "	#var {worldlist[$gui[new][NAME]]} {$gui[new]};\n"
-"\n"
+
 "	#unvar {worldlist[$gui[new][NAME]][DESC]};\n"
-"\n"
+
 "	gui_worlds;\n"
-"\n"
+
 "	draw_worlds {&worldlist[$gui[new][NAME]]};\n"
-"\n"
+
 "	reload_profile_tab;\n"
-"\n"
+
 "	#line ignore #showme {<acf>World <ffa>$gui[new][NAME]<acf> saved.};\n"
-"\n"
+
 "	#CLASS WORLDS WRITE $info[SYSTEM][TINTIN]/worlds.tin;\n"
 "}\n"
-"\n"
+
 "#alias {gui_remove}\n"
 "{\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"
 "		#return;\n"
 "	};\n"
-"\n"
+
 "	profile_tab_save;\n"
-"\n"
+
 "	#unvar {worldlist[$gui[new][NAME]]};\n"
-"\n"
+
 "	profile_tab_cancel;\n"
-"\n"
+
 "	draw_worlds 0;\n"
-"\n"
-"\n"
+
+
 "	#line ignore #showme {<acf>World <ffa>$gui[new][NAME]<acf> removed.};\n"
-"\n"
+
 "	#CLASS WORLDS WRITE $info[SYSTEM][TINTIN]/worlds.tin;\n"
 "}\n"
-"\n"
-"\n"
+
+
 "#alias {reload_profile_tab}\n"
 "{\n"
 "	#var gui[profile_tab] 1;\n"
-"\n"
+
 "	profile_tab NAME;\n"
 "	profile_tab ALIAS;\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 CHARACTER;\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"
-"		#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"
 "	};\n"
-"\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"
-"\n"
+
 "	#if {{$gui[world_tab]} !== {sponsors}}\n"
 "	{\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 {\e[Z} {gui_tab_backward};\n"
 "}\n"
-"\n"
+
 "#event {SESSION ACTIVATED}\n"
 "{\n"
 "	gui_reload\n"
 "}\n"
-"\n"
+
 "#alias {gui_reload}\n"
 "{\n"
 "	#split 1 3 27 27;\n"
 "	#config mouse on;\n"
-"\n"
+
 "	#screen clear split;\n"
 "	#screen inputregion -2 28 -2 -28 profile_tab_INPUT;\n"
-"\n"
+
 "	#screen get rows gui[rows];\n"
 "	#screen get cols gui[cols];\n"
-"\n"
+
 "	#math gui[cols] $gui[cols] - 54;\n"
-"\n"
+
 "	#var gui[index] 1;\n"
-"\n"
+
 "	#draw Orange rounded box -3 27 -1 -27;\n"
 "	#draw Orange rounded box 1 27 -4 -27;\n"
-"\n"
+
 "	world_tab $gui[world_tab];\n"
-"\n"
+
 "	#switch {{$gui[world_tab]}}\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"
+
 "	#if {$gui[profile_tab] == 1}\n"
 "	{\n"
 "		reload_profile_tab\n"
 "	}\n"
 "}\n"
-"\n"
+
 "#alias {gui_init}\n"
 "{\n"
 "	#config scroll_lock off;\n"
-"\n"
+
 "	#class WORLDS assign #variable {worldlist} {};\n"
-"\n"
+
 "	#info system save;\n"
-"\n"
+
 "	#banner save;\n"
-"\n"
+
 "	#line quiet #read $info[SYSTEM][TINTIN]/worlds.tin;\n"
-"\n"
+
 "	#var gui[pause] 0;\n"
 "	#var gui[profile_tab] 0;\n"
 "	#var gui[world_tab] worlds;\n"
-"\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"
-"\n"
+
 "	gui_reload;\n"
-"\n"
+
 "	#if {$gui[cols] > 75}\n"
 "	{\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"
 "	}\n"
 "}\n"
-"\n"
+
 "#EVENT {SCREEN RESIZE}\n"
 "{\n"
 "	#delay {gui_reload} {gui_reload;#buffer end} {0.1}\n"
 "}\n"
-"\n"
+
 "#EVENT {SESSION DESTROYED} {#gts #delay 0 #end}\n"
-"\n"
+
 "#event {SCROLLED MOUSE WHEEL UP}\n"
 "{\n"
 "	#if {%1 <= 26}\n"
 "	{\n"
-"		#if {$gui[profile_tab] && $gui[index] > 1}\n"
+"		#if {$gui[profile_tab] >= 0 && $gui[index] > 1}\n"
 "		{\n"
 "			#math gui[index] $gui[index] - 1;\n"
 "			gui_draw_left\n"
@@ -678,12 +703,12 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#buffer up 1\n"
 "	}\n"
 "}\n"
-"\n"
+
 "#event {SCROLLED MOUSE WHEEL DOWN}\n"
 "{\n"
 "	#if {%1 <= 26}\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"
 "			#math gui[index] $gui[index] + 1;\n"
 "			gui_draw_left\n"
@@ -704,5 +729,5 @@ char *tt_gui = "#line quiet #port init gui 0\n"
 "		#buffer down 1;\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)
 		{
+			case -1:
+				*pto++ = '\\';
+				*pto++ = 'x';
+				*pto++ = 'F';
+				*pto++ = 'F';
+				pti++;
+				break;
+
 			case ASCII_ESC:
 				*pto++ = '\\';
 				*pto++ = 'e';
@@ -908,19 +918,19 @@ char *str_convert_meta(char *input, int eol)
 
 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);
 
 	if (ses->check_output)
 	{
-		strcpy(output, ses->more_output);
+		strcpy(buffer, ses->more_output);
 
 		process_mud_output(ses, buffer, FALSE);
 	}
 	else
 	{
-		strcpy(output, "");
+		buffer[0] = 0;
 	}
 
 	if (ses->scroll->line != -1)
@@ -946,7 +956,8 @@ void echo_command(struct session *ses, char *line)
 	}
 	else
 	{
-		if (strip_vt102_strlen(ses, output) == 0)
+
+		if (strip_vt102_strlen(ses, buffer) == 0)
 		{
 			return;
 		}
@@ -1040,7 +1051,7 @@ void input_printf(char *format, ...)
 	char *buf;
 	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)
 		{

+ 82 - 2
src/line.c

@@ -25,6 +25,38 @@
 
 #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)
 {
 	int cnt;
@@ -205,7 +237,11 @@ DO_LINE(line_gag)
 			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);
 
@@ -462,7 +498,7 @@ DO_LINE(line_msdp)
 
 	if (*arg1 == 0)
 	{
-		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {STRIP} {command}.");
+		show_error(ses, LIST_COMMAND, "#SYNTAX: #LINE {MSDP} {command}.");
 
 		return ses;
 	}
@@ -474,6 +510,50 @@ DO_LINE(line_msdp)
 	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)
 {
 	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_order);
 extern DO_ARRAY(array_reverse);
+extern DO_ARRAY(array_refine);
 extern DO_ARRAY(array_set);
 extern DO_ARRAY(array_shuffle);
 extern DO_ARRAY(array_simplify);
@@ -77,6 +78,7 @@ struct array_type array_table[] =
 	{     "NUMERATE",         array_numerate,    "Turn a table into a list"                },
 	{     "ORDER",            array_order,       "Sort a list table numerically"           },
 	{     "LENGTH",           array_size,        NULL                                      },
+	{     "REFINE",           array_refine,      "Filter a list with given math"           },
 	{     "REVERSE",          array_reverse,     "Sort a list table in reverse order"      },
 	{     "SET",              array_set,         "Change a list item at given index"       },
 	{     "SHUFFLE",          array_shuffle,     "Sort a list table in random order"       },
@@ -263,6 +265,13 @@ DO_ARRAY(array_create)
 
 	arg = buf;
 
+	if (*arg == 0)
+	{
+		set_nest_node_ses(ses, arg1, "");
+
+		return ses;
+	}
+
 	if (list->root)
 	{
 		free_list(list->root);
@@ -284,13 +293,15 @@ DO_ARRAY(array_create)
 
 			if (*str == COMMAND_SEPARATOR)
 			{
-				str++;
+				*str = ' ';
+//				str++;
 			}
 		}
 
 		if (*arg == COMMAND_SEPARATOR)
 		{
-			arg++;
+			*arg = ' ';
+//			arg++;
 		}
 	}
 	return ses;
@@ -411,8 +422,11 @@ DO_ARRAY(array_filter)
 		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)
 		{
 			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))
 				{
 					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))
 				{
 					delete_index_list(list->root, index--);
+					found = 1;
 				}
 			}
 		}
+		if (found && numerate)
+		{
+			array_numerate(ses, list, arg, var, arg1, arg2);
+		}
 	}
 
 	return ses;
@@ -685,6 +705,69 @@ DO_ARRAY(array_order)
 	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)
 {
 	struct listroot *toor;

+ 15 - 7
src/main.c

@@ -79,12 +79,16 @@ void winch_handler(int signal)
 	gtd->time_session = gtd->time;
 }
 
-
 void abort_handler(int signal)
 {
 	syserr_fatal(signal, "abort_handler");
 }
 
+void fpe_handler(int signal)
+{
+	syserr_fatal(signal, "fpe_handler");
+}
+
 void child_handler(int signal)
 {
 	return;
@@ -166,7 +170,12 @@ int main(int argc, char **argv)
 
 	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)
@@ -788,12 +797,12 @@ void syserr_signal(int signal, char *msg)
 
 void syserr_fatal(int signal, char *msg)
 {
-	char buf[256], errstr[128];
+	char errstr[128];
 	static char crashed = FALSE;
 
 	if (crashed++)
 	{
-		print_stdout(0, 0, "syserr_fatal(crashed)");
+		print_stdout(0, 0, "\e[1;36msyserr_fatal(crashed) \e[0m\n");
 
 		fflush(NULL);
 
@@ -833,9 +842,8 @@ void syserr_fatal(int signal, char *msg)
 
 	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();
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 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)
 {
 	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);
 
@@ -167,18 +167,17 @@ int get_ellipsis(struct session *ses, unsigned int size, char *name, int *min, i
 	{
 		strcpy(name + len, "-1");
 	}
-/*
+
 	sscanf(name, "%[^.]..%[^.]", strmin, strmax);
 
 	*min = get_number(ses, strmin);
 	*max = get_number(ses, strmax);
-*/
-
-	range = get_ulong(ses, name);
+/*
+	unsigned long long range = get_ulong(ses, name);
 
 	*min = (int) (range / 1000000000 - 100000000);
 	*max = (int) (range % 1000000000 - 100000000);
-
+*/
 	*min = *min > 0 ? *min - 1 : size + *min;
 	*max = *max > 0 ? *max - 1 : size + *max;
 

+ 6 - 0
src/misc.c

@@ -166,6 +166,12 @@ DO_COMMAND(do_test)
 
 	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, "<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
 	{
-		length = msdp2json((unsigned char *) src, length, out);
+		length = msdp2gmcp((unsigned char *) src, length, 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;
 	int i, nest, last;
@@ -828,7 +828,7 @@ int msdp2json(unsigned char *src, int srclen, char *out)
 	return pto - out;
 }
 
-int json2msdp(unsigned char *src, int srclen, char *out)
+int gmcp2msdp(unsigned char *src, int srclen, char *out)
 {
 	char *pto;
 	int i, nest, last, type, state[100];
@@ -1098,3 +1098,4 @@ int tintin2msdp(char *str, char *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);
 
+	if (*name == 0)
+	{
+		arg = get_arg_in_brackets(root->ses, arg, name);
+	}
+
 	while (root && *arg)
 	{
 		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)
 	{
 		// 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)
 	{
 		// 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)
 	{
 		// 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);
 
 		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++)
 			{
-				str_cat_printf(result, "{%s}", root->list[index]->arg1);
+				str_cat_printf(result, "{%s}", root->list[index]->arg2);
 			}
 			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)
 	{
 		// 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 *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 sock, error;
+	int sock, error, optval;
 	struct addrinfo *address;
 	static struct addrinfo hints;
 	char ip[100];
@@ -145,10 +145,11 @@ int connect_mud(struct session *ses, char *host, char *port)
 		return -1;
 	}
 
-	int optval = 1;
+	optval = 1;
+
 	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);
@@ -286,7 +287,12 @@ void write_line_mud(struct session *ses, char *line, int size)
 		}
 		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();
 		return;
@@ -533,6 +539,8 @@ void readmud(struct session *ses)
 			}
 			else
 			{
+				// clean this up some time.
+
 				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,
 	 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,
-	 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,
 	123, 124, 125, 126, 127,
 	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
 };
 
+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)
 {
 	char buf[NUMBER_SIZE], *str3;
@@ -467,7 +481,7 @@ struct session *parse_tintin_command(struct session *ses, char *input)
 
 	if (*line == '!')
 	{
-		show_error(ses, LIST_COMMAND, "#!%s %s", line + 1, input);
+		show_message(ses, LIST_COMMAND, "#!%s %s", line + 1, input);
 
 		return ses;
 	}
@@ -786,7 +800,6 @@ char *get_arg_stop_spaces(struct session *ses, char *string, char *result, int f
 			continue;
 		}
 
-
 		if (*pti == '\\' && pti[1] == COMMAND_SEPARATOR)
 		{
 			*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)
 {
 	pcre *regex;
-	int i, j, matches, match[303];
+	int i, j, matches;
 
 	if (nodepcre == NULL)
 	{
@@ -109,7 +109,7 @@ int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, in
 		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)
 	{
@@ -127,12 +127,13 @@ int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, in
 		case REGEX_FLAG_CMD:
 			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++)
 			{
-				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;
 			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:
 			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++)
 			{
 				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;
 			break;
@@ -155,12 +157,13 @@ int regexp_compare(struct session *ses, pcre *nodepcre, char *str, char *exp, in
 		case REGEX_FLAG_ARG:
 			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++)
 			{
-				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;
 			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:
 			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++)
 			{
 				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;
 			break;
@@ -302,40 +306,43 @@ int get_regex_range(char *in, char *out, int *var, int *arg)
 				continue;
 
 			case 'a':
-				pto += sprintf(pto, "([^\\0]");
+				pto += sprintf(pto, "%s", "([^\\0]");
 				break;
 			case 'A':
-				pto += sprintf(pto, "(\\n");
+				pto += sprintf(pto, "%s", "(\\n");
+				break;
+			case 'c':
+				pto += sprintf(pto, "%s", "((?:\\e\\[[0-9;]*m)");
 				break;
 			case 'd':
-				pto += sprintf(pto, "([0-9]");
+				pto += sprintf(pto, "%s", "([0-9]");
 				break;
 			case 'D':
-				pto += sprintf(pto, "([^0-9]");
+				pto += sprintf(pto, "%s", "([^0-9]");
 				break;
 			case 'p':
-				pto += sprintf(pto, "([\\x20-\\xfe]");
+				pto += sprintf(pto, "%s", "([\\x20-\\xfe]");
 				break;
 			case 'P':
-				pto += sprintf(pto, "([^\\x20-\\xfe]");
+				pto += sprintf(pto, "%s", "([^\\x20-\\xfe]");
 				break;
 			case 's':
-				pto += sprintf(pto, "(\\s");
+				pto += sprintf(pto, "%s", "(\\s");
 				break;
 			case 'S':
-				pto += sprintf(pto, "(\\S");
+				pto += sprintf(pto, "%s", "(\\S");
 				break;
 			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;
 			case 'U':
-				pto += sprintf(pto, "([\\x00-\\x7F\\xFF]");
+				pto += sprintf(pto, "%s", "([\\x00-\\x7F\\xFF]");
 				break;
 			case 'w':
-				pto += sprintf(pto, "([a-zA-Z0-9_]");
+				pto += sprintf(pto, "%s", "(\\w");
 				break;
 			case 'W':
-				pto += sprintf(pto, "([^a-zA-Z0-9_]");
+				pto += sprintf(pto, "%s", "(\\W");
 				break;
 
 			default:
@@ -405,6 +412,7 @@ int tintin_regexp_check(struct session *ses, char *exp)
 
 					case 'a':
 					case 'A':
+					case 'c':
 					case 'd':
 					case 'D':
 					case 'i':
@@ -429,6 +437,7 @@ int tintin_regexp_check(struct session *ses, char *exp)
 						{
 							case 'a':
 							case 'A':
+							case 'c':
 							case 'd':
 							case 'D':
 							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';
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += is_digit(pti[2]) ? 3 : 2;
-						strcpy(pto, *pti == 0 ? "(.*)" : "(.*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.*)" : "(.*?)");
 						break;
 
 					case 'a':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^\\0]*)" : "([^\\0]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([^\\0]*)" : "([^\\0]*?)");
 						break;
 
 					case 'A':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						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;
 
 					case 'd':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([0-9]*)" : "([0-9]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([0-9]*)" : "([0-9]*?)");
 						break;
 
 					case 'D':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^0-9]*)" : "([^0-9]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([^0-9]*)" : "([^0-9]*?)");
 						break;
 
 					case 'i':
 						pti += 2;
-						strcpy(pto, "(?i)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(?i)");
 						break;
 
 					case 'I':
 						pti += 2;
-						strcpy(pto, "(?-i)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(?-i)");
 						break;
 
 					case 'p':
@@ -618,51 +626,44 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 					case 's':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\s*)" : "(\\s*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\s*)" : "(\\s*?)");
 						break;
 
 					case 'S':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\S*)" : "(\\S*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\S*)" : "(\\S*?)");
 						break;
 
 					case 'u':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						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;
 
 					case 'U':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(^[\\xF5-\\xFF]*)" : "([\\xF5-\\xFF]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(^[\\xF5-\\xFF]*)" : "([\\xF5-\\xFF]*?)");
 						break;
 
 
 					case 'w':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([a-zA-Z]*)" : "([a-zA-Z]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\w*)" : "(\\w*?)");
 						break;
 
 					case 'W':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^a-zA-Z]*)" : "([^a-zA-Z]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\W*)" : "(\\W*?)");
 						break;
 
 					case '*':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(.*)" : "(.*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.*)" : "(.*?)");
 						break;
 
 					case '+':
@@ -678,15 +679,13 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 					case '.':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, "(.)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(.)");
 						break;
 
 					case '?':
 						gtd->args[next_arg(var)] = next_arg(arg);
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(.?)" : "(.?" "?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.?)" : "(.?" "?)");
 						break;
 
 					case '!':
@@ -694,28 +693,29 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 						{
 							case 'a':
 								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;
 
 							case 'A':
 								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;
 
 							case 'd':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[0-9]*" : "[0-9]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[0-9]*" : "[0-9]*?");
 								break;
 
 							case 'D':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[^0-9]*" : "[^0-9]*?");
-									pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[^0-9]*" : "[^0-9]*?");
 								break;
 
 							case 'p':
@@ -730,52 +730,44 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 
 							case 's':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "\\s*" : "\\s*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\s*" : "\\s*?");
 								break;
 
 							case 'S':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "\\S*" : "\\S*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\S*" : "\\S*?");
 								break;
 
 							case 'u':
 								gtd->args[next_arg(var)] = next_arg(arg);
 								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;
 
 							case 'U':
 								gtd->args[next_arg(var)] = next_arg(arg);
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[\\xF5-\\xFF]*" : "[\\xF5-\\xFF]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[\\xF5-\\xFF]*" : "[\\xF5-\\xFF]*?");
 								break;
 
 							case 'w':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[a-zA-Z]*" : "[a-zA-Z]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\w*" : "\\w*?");
 								break;
 
 							case 'W':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[^a-zA-Z]*" : "[^a-zA-Z]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\W*" : "\\W*?");
 								break;
 
 							case '?':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? ".?" : ".?" "?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? ".?" : ".?" "?");
 								break;
 
 							case '*':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? ".*" : ".*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? ".*" : ".*?");
 								break;
 
 							case '+':
@@ -785,8 +777,7 @@ int tintin_regexp(struct session *ses, pcre *nodepcre, char *str, char *exp, int
 
 							case '.':
 								pti += 3;
-								strcpy(pto, ".");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", ".");
 								break;
 
 							case '{':
@@ -949,32 +940,32 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 					case '8':
 					case '9':
 						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;
 
 					case 'd':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([0-9]*)" : "([0-9]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([0-9]*)" : "([0-9]*?)");
 						break;
 
 					case 'D':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^0-9]*)" : "([^0-9]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([^0-9]*)" : "([^0-9]*?)");
 						break;
 
 					case 'i':
 						pti += 2;
-						strcpy(pto, "(?i)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(?i)");
 						break;
 
 					case 'I':
 						pti += 2;
-						strcpy(pto, "(?-i)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(?-i)");
 						break;
 
 					case 'p':
@@ -989,50 +980,42 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 						
 					case 's':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\s*)" : "(\\s*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\s*)" : "(\\s*?)");
 						break;
 
 					case 'S':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(\\S*)" : "(\\S*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\S*)" : "(\\S*?)");
 						break;
 
 					case 'u':
 						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;
 
 					case 'U':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([\\xF5-\\xFF]*)" : "([\\xF5-\\xFF]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "([\\xF5-\\xFF]*)" : "([\\xF5-\\xFF]*?)");
 						break;
 
 					case 'w':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([a-zA-Z]*)" : "([a-zA-Z]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\w*)" : "(\\w*?)");
 						break;
 
 					case 'W':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "([^a-zA-Z]*)" : "([^a-zA-Z]*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(\\W*)" : "(\\W*?)");
 						break;
 
 					case '?':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(.?)" : "(.?" "?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.?)" : "(.?" "?)");
 						break;
 
 					case '*':
 						pti += 2;
-						strcpy(pto, *pti == 0 ? "(.*)" : "(.*?)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", *pti == 0 ? "(.*)" : "(.*?)");
 						break;
 
 					case '+':
@@ -1042,8 +1025,7 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 
 					case '.':
 						pti += 2;
-						strcpy(pto, "(.)");
-						pto += strlen(pto);
+						pto += sprintf(pto, "%s", "(.)");
 						break;
 
 					case '%':
@@ -1054,16 +1036,19 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 					case '!':
 						switch (pti[2])
 						{
+							case 'c':
+								pti += 3;
+								pto += sprintf(pto, "%s", *pti == 0 ? "(?:\\e\\[[0-9;]*m)*" : "(?:\\e\\[[0-9;]*m)*?");
+								break;
+
 							case 'd':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[0-9]*" : "[0-9]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[0-9]*" : "[0-9]*?");
 								break;
 
 							case 'D':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[^0-9]*" : "[^0-9]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "[^0-9]*" : "[^0-9]*?");
 								break;
 
 							case 'p':
@@ -1078,49 +1063,41 @@ pcre *tintin_regexp_compile(struct session *ses, struct listnode *node, char *ex
 
 							case 's':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "\\s*" : "\\s*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\s*" : "\\s*?");
 								break;
 
 							case 'S':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "\\S*" : "\\S*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\S*" : "\\S*?");
 								break;
 
 							case 'w':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[a-zA-Z]*" : "[a-zA-Z]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\w*" : "\\w*?");
 								break;
 
 							case 'W':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? "[^a-zA-Z]*" : "[^a-zA-Z]*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? "\\W*" : "\\W*?");
 								break;
 
 							case '?':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? ".?" : ".?" "?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? ".?" : ".?" "?");
 								break;
 
 							case '*':
 								pti += 3;
-								strcpy(pto, *pti == 0 ? ".*" : ".*?");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", *pti == 0 ? ".*" : ".*?");
 								break;
 
 							case '+':
 								pti += 3 + get_regex_range(&pti[3], pto, NULL, NULL);
-								pto += strlen(pto);
 								break;
 
 							case '.':
 								pti += 3;
-								strcpy(pto, ".");
-								pto += strlen(pto);
+								pto += sprintf(pto, "%s", ".");
 								break;
 
 							case '{':

+ 19 - 17
src/screen.c

@@ -1139,17 +1139,29 @@ DO_SCREEN(screen_set)
 	{
 		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"))
 	{
 		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"))
 	{
@@ -1157,7 +1169,7 @@ DO_SCREEN(screen_set)
 	}
 	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;
 	}
 
-	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;
 	}
 
-	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);
 
-	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);
 
@@ -100,6 +107,8 @@ DO_COMMAND(do_echo)
 		return ses;
 	}
 
+	prompt = is_suffix(arg1, "\\") && !is_suffix(arg1, "\\\\");
+
 	str_cpy_printf(&out, "%s%s%s", COLOR_TEXT, arg1, COLOR_TEXT);
 
 	tintin_puts3(ses, out, prompt);
@@ -494,7 +503,7 @@ void tintin_puts(struct session *ses, char *string)
 
 	do_one_line(string, ses);
 
-	if (ses->gagline)
+	if (ses->gagline > 0)
 	{
 		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)
 			{
 				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));
 
 	pop_call();

+ 4 - 0
src/substitute.c

@@ -2179,6 +2179,10 @@ int substitute(struct session *ses, char *string, char *result, int flags)
 				}
 				else
 				{
+					if (HAS_BIT(flags, SUB_COL))
+					{
+						old[0] = 0;
+					}
 					*pto++ = *pti++;
 				}
 				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                                                                  },
 	{    "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                                                   },
-	{    "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 },
 	{    "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 },
@@ -72,22 +72,25 @@ struct substitution_type substitution_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[] =
@@ -327,9 +330,9 @@ char character_table[256] =
 	0,
 	0,
 	0,
-	0,
+	0, // \a
 
-	0,
+	0, // \b
 	CHAR_FLAG_SPACE, // \t
 	CHAR_FLAG_SPACE, // \n
 	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,        ""          },
 	{     "REDRAW INPUT",       "Redraw the input line",                          "",           CURSOR_FLAG_GET_ALL,     cursor_redraw_input,          ""          },
 	{     "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,            ""          },
 	{     "SUSPEND",            "Suspend program, return with fg",                "",           CURSOR_FLAG_GET_ALL,     cursor_suspend,               ""          },
 	{     "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,               ""          },
 	{     "",                   "",                                               "\e[6~",                          0,    cursor_buffer_down,           ""          },
 	{     "",                   "",                                               "\e[1;5F",                        0,    cursor_buffer_end,            ""          },
+//	{     "",                   "",                                               "\e[F",                           0,    cursor_buffer_end,            ""          },
 	{     "",                   "",                                               "\e[1;5H",                        0,    cursor_buffer_home,           ""          },
+//	{     "",                   "",                                               "\e[H",                           0,    cursor_buffer_home,           ""          },
 	{     "",                   "",                                               "\e[5~",                          0,    cursor_buffer_up,             ""          },
 	{     "",                   "",                                               "\eOa",                           0,    cursor_buffer_up,             "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 DEACTIVATED",                      0, EVENT_FLAG_CLASS,    "CLASS",     "class deactivations"        },
 	{    "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 DETACHED",                        0, EVENT_FLAG_SYSTEM,   "SYSTEM",    "daemon detachment"          },
 	{    "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"     },
 	{    "MONTH",                                  0, EVENT_FLAG_TIME,     "TIME",      "month or given month"       },
 	{    "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 DISCONNECTION",                     0, EVENT_FLAG_PORT,     "PORT",      "socket disconnects"         },
 	{    "PORT INITIALIZED",                       0, EVENT_FLAG_PORT,     "PORT",      "port is initialized"        },
@@ -1141,30 +1148,6 @@ struct path_type path_table[] =
 	{    "",                  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[] =
 {
 //	{    "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;
 }
 
+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)
 {
 	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))
 	{
 		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);
 
@@ -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);
 	}
 
-	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;
 }
@@ -1118,8 +1143,8 @@ int client_recv_sb_msdp(struct session *ses, int cplen, unsigned char *src)
 		{
 			strip_vt102_codes(val, plain);
 			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++;
 	}
@@ -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);
 				}
-				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);
 				}
-				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);
 				}
-				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);
 				}
-				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);
 				}
-				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);
 				}
+				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 (accept > 0 && found == 0)
 					{
 						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);
 
 						found = 1;
@@ -1428,24 +1461,19 @@ int client_recv_sb_charset(struct session *ses, int cplen, unsigned char *src)
 	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)
@@ -1548,7 +1576,7 @@ int client_recv_sb_new_environ(struct session *ses, int cplen, unsigned char *sr
 							}
 							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));
 							}
@@ -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, 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();
 	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;
 
-	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;
 
-		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 = 0;
@@ -915,7 +924,7 @@ int process_sb_gmcp(struct session *ses, struct port_data *buddy, unsigned char
 		return srclen + 1;
 	}
 
-	outlen = json2msdp(src, srclen, out);
+	outlen = gmcp2msdp(src, srclen, out);
 
 	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)
 {
-	struct winsize screen;
-	static int old_rows, old_cols;
-
 	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)
 	{
 		old_rows = gtd->screen->rows;
 		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)
@@ -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);
 
-	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)
@@ -231,3 +243,4 @@ char *get_charset(struct session *ses)
 	}
 	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)
 			{
-				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;
 	cur_col    = 1;
 	cur_space  = cur_col;
+	*pto       = 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_VERSION           "2.02.20 "
+#define CLIENT_VERSION           "2.02.30 "
 
 
 #define XT_E                            0x27
@@ -487,6 +487,7 @@ enum operators
 #define INPUT_FLAG_HISTORYBROWSE      BV02
 #define INPUT_FLAG_HISTORYSEARCH      BV03
 #define INPUT_FLAG_CONVERTMETACHAR    BV04
+#define INPUT_FLAG_REDRAW             BV05
 
 #define PORT_FLAG_PRIVATE             BV01
 #define PORT_FLAG_REQUEST             BV02
@@ -682,6 +683,7 @@ enum operators
 #define LIST_FLAG_INHERIT             BV11
 #define LIST_FLAG_REGEX               BV12
 #define LIST_FLAG_NEST                BV13
+#define LIST_FLAG_CASE                BV14
 #define LIST_FLAG_DEFAULT             LIST_FLAG_MESSAGE
 
 #define NODE_FLAG_ONESHOT             BV01 // unused
@@ -764,6 +766,7 @@ enum operators
 #define MAP_FLAG_QUIET                BV17
 #define MAP_FLAG_READ                 BV18
 #define MAP_FLAG_PANCAKE              BV19
+#define MAP_FLAG_FAST                 BV20
 
 #define MAP_SEARCH_NAME                0
 #define MAP_SEARCH_EXITS               1
@@ -1115,7 +1118,7 @@ struct tintin_data
 	char                 *  attach_file;
 	int                     attach_pid;
 	int                     attach_sock;
-	int                     daemon;
+//	int                     daemon;
 	char                  * buf;
 	char                  * out;
 	char                  * mud_output_buf;
@@ -1145,6 +1148,7 @@ struct tintin_data
 	char                    tintin_char;
 	char                    verbatim_char;
 	char                    repeat_char;
+	int                     match[303];
 	char                  * vars[100];
 	char                  * cmds[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_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_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_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 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 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            PATH    (struct session *ses, char *arg);
 typedef struct session *PORT    (struct session *ses, char *arg, char *arg1, char *arg2);
@@ -1667,6 +1671,7 @@ struct charset_type
 {
 	char                  * name;
 	char                  * html;
+	char                  * mnes;
 	int                     flags;
 };
 
@@ -1753,14 +1758,6 @@ struct list_type
 	int                     flags;
 };
 
-
-struct line_type
-{
-	char                  * name;
-	LINE                  * fun;
-	char                  * desc;
-};
-
 struct map_type
 {
 	char                  * name;
@@ -2072,7 +2069,7 @@ extern DO_COMMAND(do_map);
 
 extern void delete_room_data(struct room_data *room);
 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  int delete_map(struct session *ses);
 
@@ -2359,6 +2356,7 @@ extern DO_LINE(line_convert);
 extern DO_LINE(line_debug);
 extern DO_LINE(line_gag);
 extern DO_LINE(line_ignore);
+extern DO_LINE(line_json);
 extern DO_LINE(line_local);
 extern DO_LINE(line_log);
 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_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  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 void arachnos_devel(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 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 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 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, ...);
@@ -2544,6 +2544,7 @@ extern void process_mud_output(struct session *ses, char *linebuf, int prompt);
 #define __PARSE_H__
 
 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_vowel(char *str);
 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 event_type event_table[];
 extern struct history_type history_table[];
-extern struct line_type line_table[];
 extern struct list_type list_table[LIST_MAX];
 extern struct map_type map_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_off(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_cols(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__
 
 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  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)
 	{
-		token->data->arg++;
+		*token->data->arg = ' ';
+//		token->data->arg++;
 	}
+
 	return buf;
 }
 
@@ -1094,10 +1096,20 @@ char *write_script(struct session *ses, struct scriptroot *root)
 				break;
 
 			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);
 				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:
 				cat_sprintf(buf, "%s%c%s\n%s{\n", indent(token->lvl), gtd->tintin_char, token->str, indent(token->lvl));
 				break;
@@ -1182,7 +1194,14 @@ char *view_script(struct session *ses, struct scriptroot *root)
 				break;
 
 			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;
 
 			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);
 
+			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)
 			{
 				arg++;
@@ -544,8 +553,10 @@ void check_all_gags(struct session *ses, char *original, char *line)
 			{
 				delete_node_list(ses, LIST_GAG, node);
 			}
-			ses->gagline++;
-
+			if (ses->gagline == 0)
+			{
+				ses->gagline = 1;
+			}
 			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);
 
-			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)
 			{
 				delete_node_list(ses, LIST_PROMPT, node);
 			}
-			ses->gagline = 1;
 		}
 	}
 	return 0;

+ 5 - 1
src/update.c

@@ -733,6 +733,10 @@ void update_daemon(void)
 
 				if (rv <= 0)
 				{
+					if (rv < 0)
+					{
+						syserr_printf(gtd->ses, "update_daemon: attach_sock: read:");
+					}
 					gtd->attach_sock = close(gtd->attach_sock);
 
 					winch_handler(0);
@@ -1094,7 +1098,7 @@ void terminal_update(void)
 		{
 			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");
 		}

+ 4 - 10
src/variable.c

@@ -250,7 +250,7 @@ DO_COMMAND(do_cat)
 
 		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, "");
 		}
@@ -329,20 +329,14 @@ DO_COMMAND(do_replace)
 				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);
 
 			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));
 

+ 7 - 1
src/vt102.c

@@ -100,7 +100,8 @@ void goto_pos(struct session *ses, int row, int col)
 {
 	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();
 
 		return;
@@ -658,6 +659,11 @@ char *strip_vt102_strstr(char *str, char *buf, int *len)
 
 	while (*pts)
 	{
+		while (skip_vt102_codes(pts))
+		{
+			pts += skip_vt102_codes(pts);
+		}
+
 		pti = pts;
 		ptm = buf;
 

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно