home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / telecomm / terms / term-4.1-source.lha / Extras / Source / term-Source.lha / termEmulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-28  |  57.3 KB  |  3,162 lines

  1. /*
  2. **    termEmulation.c
  3. **
  4. **    Terminal emulation (parsing and processing) routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* One of the emulation callback routines. */
  13.  
  14. typedef VOID (*  EPTR)(STRPTR Buffer);
  15.  
  16.     /* This structure describes an ANSI control sequence. */
  17.  
  18. struct ControlCode
  19. {
  20.     UBYTE    FirstChar;
  21.     STRPTR    Match,
  22.         Terminator;
  23.     UBYTE    LastChar;
  24.  
  25.     BYTE    ExactSize;
  26.     EPTR    Func;
  27. };
  28.  
  29.     /* How many characters we will keep in the scan buffer. */
  30.  
  31. #define MAX_SCAN_SIZE    256
  32.  
  33.     /* Flag indicating whether the cursor has already been
  34.      * erased or not.
  35.      */
  36.  
  37. STATIC BYTE        CursorEnabled    = FALSE,
  38.             CursorInvisible    = FALSE;
  39.  
  40.     /* Cursor handling data. */
  41.  
  42. STATIC WORD        LastCursorX = -1,
  43.             LastCursorY = -1;
  44.  
  45. STATIC LONG        DestX,
  46.             DestY,
  47.             XSize,
  48.             FontByColumn;
  49.  
  50. STATIC BYTE        CursorGhosted = FALSE;
  51.  
  52.     /* Backup style. */
  53.  
  54. STATIC UBYTE        StyleType = FS_NORMAL;
  55.  
  56.     /* Cursor backup data. */
  57.  
  58. STATIC struct CursorData CursorBackup;
  59.  
  60.     /* A couple of internally referenced variables. */
  61.  
  62. STATIC BYTE        CharsInBuffer    = 0,
  63.             ScanStep    = 0;
  64. STATIC UBYTE __far    SaveBuffer[MAX_SCAN_SIZE + 1];
  65. STATIC STRPTR        Arnie        = NULL;
  66.  
  67. STATIC BYTE        PrintFormFeed    = FALSE,
  68.             PrintFullScreen    = FALSE;
  69.  
  70.     /* Character access tables. */
  71.  
  72. STATIC UBYTE __far Table0[256] =
  73. {
  74.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  75.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  76.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  77.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  78.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  79.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  80.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  81.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  82.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  83.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  84.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  85.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  86.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  87.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  88.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  89.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  90. };
  91.  
  92. STATIC UBYTE __far Table1[256] =
  93. {
  94.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  95.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  96.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.     1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
  98.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  99.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  100.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  101.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  102.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  103.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  104.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  105.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  106.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  107.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  108.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  109.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  110. };
  111.  
  112. STATIC UBYTE __far Table2[256] =
  113. {
  114.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  115.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  116.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  117.     1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,
  118.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  119.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  120.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  121.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  122.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  123.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  124.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  125.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  126.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  127.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  128.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  129.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  130. };
  131.  
  132. STATIC UBYTE __far Table3[256] =
  133. {
  134.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  135.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  136.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  137.     1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,
  138.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  139.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  140.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  141.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  142.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  143.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  144.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  145.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  146.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  147.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  148.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  149.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  150. };
  151.  
  152. STATIC UBYTE __far Table4[256] =
  153. {
  154.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  155.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  156.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  157.     1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,
  158.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  159.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  160.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  161.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  162.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  163.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  164.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  165.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  166.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  167.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  168.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  169.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  170. };
  171.  
  172. STATIC UBYTE __far Table5[256] =
  173. {
  174.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  175.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  176.     0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,
  177.     1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,
  178.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  179.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  180.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  181.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  182.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  183.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  184.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  185.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  186.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  187.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  188.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  189.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  190. };
  191.  
  192. STATIC UBYTE __far Table6[256] =
  193. {
  194.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  195.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  196.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  197.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  198.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  199.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  200.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  201.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  202.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  203.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  204.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  205.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  206.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  207.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  208.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  209.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  210. };
  211.  
  212. STATIC UBYTE __far Term0[256] =
  213. {
  214.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  215.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  216.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  217.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  218.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  219.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  220.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  221.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,
  222.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  223.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  224.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  225.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  226.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  227.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  228.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  229.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  230. };
  231.  
  232.     /* This follows the control code information. */
  233.  
  234. STATIC struct ControlCode ANSICode[] =
  235. {
  236.     /* Single Character Sequences. */
  237.  
  238.     'D',    Table0,    NULL,     0 ,    1,    (EPTR)CursorScrollDown,    // IND
  239.     'M',    Table0,    NULL,     0 ,    1,    (EPTR)CursorScrollUp,    // RI
  240.     'E',    Table0,    NULL,     0 ,    1,    (EPTR)NextLine,        // NEL
  241.     '7',    Table0,    NULL,     0 ,    1,    (EPTR)SaveCursor,    // DECSC
  242.     '8',    Table0,    NULL,     0 ,    1,    (EPTR)LoadCursor,    // DECRC
  243.     '=',    Table0,    NULL,     0 ,    1,    (EPTR)NumericAppMode,    // DECPAM
  244.     '>',    Table0,    NULL,     0 ,    1,    (EPTR)NumericAppMode,    // DECPNM
  245.     'N',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // SS2
  246.     'O',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // SS3
  247.     'H',    Table0,    NULL,     0 ,    1,    (EPTR)SetTab,        // HTS
  248.     'P',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // DCS
  249.     '/',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // ST
  250.     'Z',    Table0,    NULL,     0 ,    1,    (EPTR)RequestTerminal,    // DECID
  251.     'c',    Table0,    NULL,     0 ,    1,    (EPTR)Reset,        // RIS
  252.     '<',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // VT52 "Enter ANSI mode"
  253.     '~',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // LS1R
  254.     'n',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // LS2
  255.     0x7D,    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // LS2R
  256.     'o',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // LS3
  257.     '|',    Table0,    NULL,     0 ,    1,    (EPTR)Ignore,        // LS3R
  258.  
  259.     /* Double Character Sequences. */
  260.  
  261.     '[',    Table0,    NULL,    's',    2,    (EPTR)SaveCursor,
  262.     '[',    Table0,    NULL,    'u',    2,    (EPTR)LoadCursor,
  263.  
  264.     '(',    Table0,    NULL,    'A',    2,    (EPTR)FontStuff,    // SCS
  265.     '(',    Table0,    NULL,    'B',    2,    (EPTR)FontStuff,    // ASCII font
  266.     '(',    Table0,    NULL,    '0',    2,    (EPTR)FontStuff,    // DEC special graphics font
  267.     '(',    Table0,    NULL,    '<',    2,    (EPTR)Ignore,        // DEC supplemental font
  268.     '(',    Table0,    NULL,    '4',    2,    (EPTR)Ignore,        // Dutch font
  269.     '(',    Table0,    NULL,    '5',    2,    (EPTR)Ignore,        // Finnish font
  270.     '(',    Table0,    NULL,    'C',    2,    (EPTR)Ignore,        // Finnish font
  271.     '(',    Table0,    NULL,    'R',    2,    (EPTR)Ignore,        // French font
  272.     '(',    Table0,    NULL,    'Q',    2,    (EPTR)Ignore,        // French Canadian font
  273.     '(',    Table0,    NULL,    'K',    2,    (EPTR)Ignore,        // German font
  274.     '(',    Table0,    NULL,    'Y',    2,    (EPTR)Ignore,        // Italian font
  275.     '(',    Table0,    NULL,    '6',    2,    (EPTR)Ignore,        // Norwegian/Danish font
  276.     '(',    Table0,    NULL,    'E',    2,    (EPTR)Ignore,        // Norwegian/Danish font
  277.     '(',    Table0,    NULL,    'Z',    2,    (EPTR)Ignore,        // Spanish font
  278.     '(',    Table0,    NULL,    '7',    2,    (EPTR)Ignore,        // Swedish font
  279.     '(',    Table0,    NULL,    'H',    2,    (EPTR)Ignore,        // Swedish font
  280.     '(',    Table0,    NULL,    '=',    2,    (EPTR)Ignore,        // Swiss font
  281.  
  282.     ')',    Table0,    NULL,    'A',    2,    (EPTR)FontStuff,    // SCS
  283.     ')',    Table0,    NULL,    'B',    2,    (EPTR)FontStuff,    // ASCII font
  284.     ')',    Table0,    NULL,    '0',    2,    (EPTR)FontStuff,    // DEC special graphics font
  285.     ')',    Table0,    NULL,    '<',    2,    (EPTR)Ignore,        // DEC supplemental font
  286.     ')',    Table0,    NULL,    '4',    2,    (EPTR)Ignore,        // Dutch font
  287.     ')',    Table0,    NULL,    '5',    2,    (EPTR)Ignore,        // Finnish font
  288.     ')',    Table0,    NULL,    'C',    2,    (EPTR)Ignore,        // Finnish font
  289.     ')',    Table0,    NULL,    'R',    2,    (EPTR)Ignore,        // French font
  290.     ')',    Table0,    NULL,    'Q',    2,    (EPTR)Ignore,        // French Canadian font
  291.     ')',    Table0,    NULL,    'K',    2,    (EPTR)Ignore,        // German font
  292.     ')',    Table0,    NULL,    'Y',    2,    (EPTR)Ignore,        // Italian font
  293.     ')',    Table0,    NULL,    '6',    2,    (EPTR)Ignore,        // Norwegian/Danish font
  294.     ')',    Table0,    NULL,    'E',    2,    (EPTR)Ignore,        // Norwegian/Danish font
  295.     ')',    Table0,    NULL,    'Z',    2,    (EPTR)Ignore,        // Spanish font
  296.     ')',    Table0,    NULL,    '7',    2,    (EPTR)Ignore,        // Swedish font
  297.     ')',    Table0,    NULL,    'H',    2,    (EPTR)Ignore,        // Swedish font
  298.     ')',    Table0,    NULL,    '=',    2,    (EPTR)Ignore,        // Swiss font
  299.  
  300.     '+',    Table0,    NULL,    'A',    2,    (EPTR)Ignore,        // British font
  301.     '+',    Table0,    NULL,    'B',    2,    (EPTR)Ignore,        // ASCII font
  302.     '+',    Table0,    NULL,    '0',    2,    (EPTR)Ignore,        // DEC special graphics font
  303.     '+',    Table0,    NULL,    '<',    2,    (EPTR)Ignore,        // DEC supplemental font
  304.     '+',    Table0,    NULL,    '4',    2,    (EPTR)Ignore,        // Dutch font
  305.     '+',    Table0,    NULL,    '5',    2,    (EPTR)Ignore,        // Finnish font
  306.     '+',    Table0,    NULL,    'C',    2,    (EPTR)Ignore,        // Finnish font
  307.     '+',    Table0,    NULL,    'R',    2,    (EPTR)Ignore,        // French font
  308.     '+',    Table0,    NULL,    'Q',    2,    (EPTR)Ignore,        // French Canadian font
  309.     '+',    Table0,    NULL,    'K',    2,    (EPTR)Ignore,        // German font
  310.     '+',    Table0,    NULL,    'Y',    2,    (EPTR)Ignore,        // Italian font
  311.     '+',    Table0,    NULL,    '6',    2,    (EPTR)Ignore,        // Norwegian/Danish font
  312.     '+',    Table0,    NULL,    'E',    2,    (EPTR)Ignore,        // Norwegian/Danish font
  313.     '+',    Table0,    NULL,    'Z',    2,    (EPTR)Ignore,        // Spanish font
  314.     '+',    Table0,    NULL,    '7',    2,    (EPTR)Ignore,        // Swedish font
  315.     '+',    Table0,    NULL,    'H',    2,    (EPTR)Ignore,        // Swedish font
  316.     '+',    Table0,    NULL,    '=',    2,    (EPTR)Ignore,        // Swiss font
  317.  
  318.     '*',    Table0,    NULL,    'A',    2,    (EPTR)Ignore,        // British font
  319.     '*',    Table0,    NULL,    'B',    2,    (EPTR)Ignore,        // ASCII font
  320.     '*',    Table0,    NULL,    '0',    2,    (EPTR)Ignore,        // DEC special graphics font
  321.     '*',    Table0,    NULL,    '<',    2,    (EPTR)Ignore,        // DEC supplemental font
  322.     '*',    Table0,    NULL,    '4',    2,    (EPTR)Ignore,        // Dutch font
  323.     '*',    Table0,    NULL,    '5',    2,    (EPTR)Ignore,        // Finnish font
  324.     '*',    Table0,    NULL,    'C',    2,    (EPTR)Ignore,        // Finnish font
  325.     '*',    Table0,    NULL,    'R',    2,    (EPTR)Ignore,        // French font
  326.     '*',    Table0,    NULL,    'Q',    2,    (EPTR)Ignore,        // French Canadian font
  327.     '*',    Table0,    NULL,    'K',    2,    (EPTR)Ignore,        // German font
  328.     '*',    Table0,    NULL,    'Y',    2,    (EPTR)Ignore,        // Italian font
  329.     '*',    Table0,    NULL,    '6',    2,    (EPTR)Ignore,        // Norwegian/Danish font
  330.     '*',    Table0,    NULL,    'E',    2,    (EPTR)Ignore,        // Norwegian/Danish font
  331.     '*',    Table0,    NULL,    'Z',    2,    (EPTR)Ignore,        // Spanish font
  332.     '*',    Table0,    NULL,    '7',    2,    (EPTR)Ignore,        // Swedish font
  333.     '*',    Table0,    NULL,    'H',    2,    (EPTR)Ignore,        // Swedish font
  334.     '*',    Table0,    NULL,    '=',    2,    (EPTR)Ignore,        // Swiss font
  335.  
  336.     '#',    Table0,    NULL,    '3',    2,    (EPTR)ScaleFont,    // DECHDL (top half)
  337.     '#',    Table0,    NULL,    '4',    2,    (EPTR)ScaleFont,    // DECHDL (bottom half)
  338.     '#',    Table0,    NULL,    '5',    2,    (EPTR)ScaleFont,    // DECSWL
  339.     '#',    Table0,    NULL,    '6',    2,    (EPTR)ScaleFont,    // DECDWL
  340.     '#',    Table0,    NULL,    '8',    2,    (EPTR)AlignmentTest,    // DECALN
  341.     ' ',    Table0,    NULL,    'F',    2,    (EPTR)Ignore,        // S7C1T
  342.     ' ',    Table0,    NULL,    'G',    2,    (EPTR)Ignore,        // C8C1T
  343.  
  344.     /* Multiple Character Sequence. */
  345.  
  346.     '(',    Table6,    Term0,    'D',    0,    (EPTR)Ignore,        // SCS
  347.  
  348.     '[',    Table3,    NULL,    'i',    0,    (EPTR)PrinterController,    // Print mode
  349.  
  350.     '[',    Table3,    NULL,    'n',    0,    (EPTR)RequestInformation,    // DSR
  351.     '[',    Table3,    NULL,    'c',    0,    (EPTR)RequestTerminal,    // DA
  352.     '[',    Table3,    NULL,    'h',    0,    (EPTR)SetSomething,    // Terminal modes
  353.     '[',    Table3,    NULL,    'l',    0,    (EPTR)SetSomething,    // Terminal modes
  354.  
  355.     '[',    Table4,    NULL,    'h',    0,    (EPTR)Ignore,
  356.     '[',    Table5,    NULL,    'p',    0,    (EPTR)Ignore,        // DECSCL
  357.  
  358.     '[',    Table1,    NULL,    'A',    0,    (EPTR)MoveCursor,    // CUU
  359.     '[',    Table1,    NULL,    'B',    0,    (EPTR)MoveCursor,    // CUD
  360.     '[',    Table1,    NULL,    'C',    0,    (EPTR)MoveCursor,    // CUF
  361.     '[',    Table1,    NULL,    'D',    0,    (EPTR)MoveCursor,    // CUB
  362.     '[',    Table1,    NULL,    'G',    0,    (EPTR)MoveColumn,
  363.     '[',    Table3,    NULL,    'K',    0,    (EPTR)EraseLine,    // EL/DECSEL
  364.     '[',    Table3,    NULL,    'J',    0,    (EPTR)EraseScreen,    // ED/DECSED
  365.     '[',    Table1,    NULL,    'P',    0,    (EPTR)EraseCharacters,    // DCH
  366.     '[',    Table1,    NULL,    'X',    0,    (EPTR)EraseCharacters,    // ECH (sort of)
  367.     '[',    Table1,    NULL,    '@',    0,    (EPTR)InsertCharacters,    // ICH
  368.     '[',    Table1,    NULL,    'L',    0,    (EPTR)InsertLine,    // IL
  369.     '[',    Table1,    NULL,    'M',    0,    (EPTR)ClearLine,    // DL
  370.     '[',    Table1,    NULL,    'g',    0,    (EPTR)SetTabs,        // TBC
  371.     '[',    Table5,    NULL,    'q',    0,    (EPTR)Ignore,        // DECSCA
  372.  
  373.     '[',    Table2,    NULL,    'H',    0,    (EPTR)SetAbsolutePosition,    // CUP
  374.     '[',    Table2,    NULL,    'f',    0,    (EPTR)SetTopPosition,    // HVP
  375.     '[',    Table2,    NULL,    'm',    0,    (EPTR)SetAttributes,    // SGR
  376.     '[',    Table2,    NULL,    'y',    0,    (EPTR)Ignore,        // DECTST
  377.     '[',    Table2,    NULL,    'r',    0,    (EPTR)SetRegion,    // DECSTBM
  378.  
  379.     '[',    Table1,    NULL,    'S',    0,    (EPTR)ScrollUp,
  380.     '[',    Table1,    NULL,    'T',    0,    (EPTR)ScrollDown
  381. };
  382.  
  383. STATIC WORD NumCodes = sizeof(ANSICode) / sizeof(struct ControlCode);
  384.  
  385.     /* GetFontWidth():
  386.      *
  387.      *    Get the font width of the current line.
  388.      */
  389.  
  390. STATIC WORD
  391. GetFontWidth(VOID)
  392. {
  393.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  394.     {
  395.         if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
  396.             return((WORD)(TextFontWidth / 2));
  397.         else
  398.             return(TextFontWidth);
  399.     }
  400.     else
  401.     {
  402.         if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
  403.             return(TextFontWidth);
  404.         else
  405.             return((WORD)(TextFontWidth * 2));
  406.     }
  407. }
  408.  
  409.     /* ColourValue(UWORD Colour):
  410.      *
  411.      *    Calculate the value of a given colour (brightness).
  412.      */
  413.  
  414. STATIC WORD __inline
  415. ColourValue(UWORD Colour)
  416. {
  417.     BYTE    Red,Green,Blue;
  418.     WORD    Sum;
  419.  
  420.     Red    =  Colour >> 8;
  421.     Green    = (Colour >> 4) & 0xF;
  422.     Blue    =  Colour       & 0xF;
  423.  
  424.     Sum = (Red + Green + Blue) / 3;
  425.  
  426.     return(Sum);
  427. }
  428.  
  429.     /* RethinkRasterLimit():
  430.      *
  431.      *    Take care of the extreme left column position
  432.      *    permitted.
  433.      */
  434.  
  435. VOID
  436. RethinkRasterLimit()
  437. {
  438.     register LONG Y;
  439.  
  440.     if(CursorY > LastLine)
  441.         Y = LastLine;
  442.     else
  443.     {
  444.         if(CursorY < 0)
  445.             Y = 0;
  446.         else
  447.             Y = CursorY;
  448.     }
  449.  
  450.     if(RasterAttr[Y] == SCALE_ATTR_NORMAL)
  451.         FontByColumn = LastColumn;
  452.     else
  453.         FontByColumn = ((LastColumn + 1) / 2) - 1;
  454. }
  455.  
  456.     /* ScrollRegion(WORD Direction):
  457.      *
  458.      *    Scroll the current scroll region up or down.
  459.      */
  460.  
  461. VOID __regargs
  462. ScrollRegion(WORD Direction)
  463. {
  464.     WORD RegionTop,RegionBottom,RegionLines;
  465.     LONG Dir,MinY,MaxY;
  466.  
  467.     if(Direction < 0)
  468.         Dir = -Direction;
  469.     else
  470.         Dir = Direction;
  471.  
  472.     if(RegionSet)
  473.     {
  474.         MinY         = MUL_Y(Top);
  475.         MaxY        = MUL_Y(Bottom + 1) - 1;
  476.  
  477.         RegionTop    = Top;
  478.         RegionBottom    = Bottom + 1;
  479.         RegionLines    = Bottom - Top + 1;
  480.     }
  481.     else
  482.     {
  483.         MinY        = 0;
  484.         MaxY         = MUL_Y(LastLine + 1) - 1;
  485.  
  486.         RegionTop    = 0;
  487.         RegionBottom    = LastLine + 1;
  488.         RegionLines    = LastLine + 1;
  489.     }
  490.  
  491.     BackupRender();
  492.  
  493.     RasterScrollRegion(Direction,RegionTop,RegionBottom,RegionLines);
  494.  
  495.     if(Config -> EmulationConfig -> ScrollMode == SCROLL_JUMP || (TextFontHeight & 1))
  496.     {
  497.         if(Dir > RegionLines)
  498.             ScrollLineRectFill(RPort,0,MinY,LastPixel,MaxY);
  499.         else
  500.         {
  501.             if(Direction > 0)
  502.                 ScrollLineRaster(RPort,0,MUL_Y(Direction),0,MinY,LastPixel,MaxY,FALSE);
  503.             else
  504.                 ScrollLineRaster(RPort,0,-MUL_Y(-Direction),0,MinY,LastPixel,MaxY,FALSE);
  505.         }
  506.     }
  507.     else
  508.     {
  509.         if(Direction > 0)
  510.             ScrollLineRaster(RPort,0,MUL_Y(Direction),0,MinY,LastPixel,MaxY,TRUE);
  511.         else
  512.             ScrollLineRaster(RPort,0,-MUL_Y(-Direction),0,MinY,LastPixel,MaxY,TRUE);
  513.     }
  514.  
  515.     BackupRender();
  516. }
  517.  
  518.     /* LastChar(STRPTR Buffer):
  519.      *
  520.      *    Return the last character in a string.
  521.      */
  522.  
  523. STATIC UBYTE __inline
  524. LastChar(STRPTR Buffer)
  525. {
  526.     WORD Offset = 0;
  527.  
  528.     while(Buffer[Offset])
  529.         Offset++;
  530.  
  531.     return(Buffer[Offset - 1]);
  532. }
  533.  
  534.     /* ReadValue(STRPTR Buffer,BYTE *Value):
  535.      *
  536.      *    Parse a buffer for numbers and return a pointer
  537.      *    to the next buffer element to contain additional
  538.      *    information.
  539.      */
  540.  
  541. STATIC STRPTR __inline
  542. ReadValue(STRPTR Buffer,WORD *Value)
  543. {
  544.     while(*Buffer && *Buffer != ';' && (*Buffer < '0' || *Buffer > '9'))
  545.         Buffer++;
  546.  
  547.     if(*Buffer)
  548.     {
  549.         *Value = 0;
  550.  
  551.         while(*Buffer >= '0' && *Buffer <= '9')
  552.             *Value = (*Value * 10) + (*Buffer++ - '0');
  553.     }
  554.     else
  555.         *Value = -1;
  556.  
  557.     if(*Buffer == ';' || *Buffer == ' ')
  558.         return(Buffer + 1);
  559.     else
  560.         return(NULL);
  561. }
  562.  
  563.     /* EmulationSerWrite(STRPTR String,LONG Length):
  564.      *
  565.      *    Write text to the serial line.
  566.      */
  567.  
  568. STATIC VOID __regargs
  569. EmulationSerWrite(STRPTR String,LONG Length)
  570. {
  571.     if(SysBase -> ThisTask == SpecialQueue -> SigTask)
  572.         SerWrite(String,Length);
  573.     else
  574.     {
  575.         struct DataMsg *Msg;
  576.  
  577.         if(Length == -1)
  578.             Length = strlen(String);
  579.  
  580.         if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + Length + 1))
  581.         {
  582.             Msg -> Type = DATAMSGTYPE_WRITE;
  583.             Msg -> Data = (STRPTR)(Msg + 1);
  584.             Msg -> Size = Length;
  585.  
  586.             CopyMem(String,Msg -> Data,Length + 1);
  587.  
  588.             PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  589.         }
  590.     }
  591. }
  592.  
  593.     /* RethinkCursorPosition():
  594.      *
  595.      *    Calculate the new cursor position.
  596.      */
  597.  
  598. STATIC VOID
  599. RethinkCursorPosition(VOID)
  600. {
  601.     if(CursorY != LastCursorY || CursorX != LastCursorX)
  602.     {
  603.         STATIC LONG X,Y;
  604.  
  605.         if(CursorY != LastCursorY)
  606.         {
  607.             if(CursorY > LastLine)
  608.                 Y = LastLine;
  609.             else
  610.             {
  611.                 if(CursorY < 0)
  612.                     Y = 0;
  613.                 else
  614.                     Y = CursorY;
  615.             }
  616.  
  617.             if(RasterAttr[Y] == SCALE_ATTR_NORMAL)
  618.                 FontByColumn = LastColumn;
  619.             else
  620.                 FontByColumn = ((LastColumn + 1) / 2) - 1;
  621.  
  622.             DestY = MUL_Y(Y);
  623.  
  624.             LastCursorY = CursorY;
  625.         }
  626.  
  627.         LastCursorX = CursorX;
  628.  
  629.         if(CursorX > FontByColumn)
  630.             X = FontByColumn;
  631.         else
  632.         {
  633.             if(CursorX < 0)
  634.                 X = 0;
  635.             else
  636.                 X = CursorX;
  637.         }
  638.  
  639.         if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
  640.         {
  641.             if(RasterAttr[Y] == SCALE_ATTR_NORMAL)
  642.             {
  643.                 DestX = MUL_X(X);
  644.                 XSize = TextFontWidth;
  645.             }
  646.             else
  647.             {
  648.                 DestX = MUL_X(X) * 2;
  649.                 XSize = TextFontWidth * 2;
  650.  
  651.                 if(X > ((LastColumn + 1) / 2) - 1)
  652.                     X = ((LastColumn + 1) / 2) - 1;
  653.             }
  654.         }
  655.         else
  656.         {
  657.             if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  658.             {
  659.                 DestX = MUL_X(X) / 2;
  660.                 XSize = TextFontWidth / 2;
  661.             }
  662.             else
  663.             {
  664.                 DestX = MUL_X(X);
  665.                 XSize = TextFontWidth;
  666.  
  667.                 if(X > ((LastColumn + 1) / 2) - 1)
  668.                     X = ((LastColumn + 1) / 2) - 1;
  669.             }
  670.         }
  671.     }
  672. }
  673.  
  674.     /* ToggleCursor():
  675.      *
  676.      *    (Re)draw the cursor image.
  677.      */
  678.  
  679. STATIC VOID
  680. ToggleCursor(VOID)
  681. {
  682.     if(Config -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL)
  683.     {
  684.         UWORD    OldAPen    = ReadAPen(RPort),
  685.             OldBPen    = ReadBPen(RPort),
  686.             OldDrMd    = ReadDrMd(RPort),
  687.  
  688.             Left    = WindowLeft + DestX,
  689.             Top    = WindowTop + DestY;
  690.  
  691.         if(Kick30)
  692.         {
  693.             SetABPenDrMd(RPort,DepthMask,OldBPen,JAM1 | COMPLEMENT);
  694.  
  695.             if(UseMasking)
  696.             {
  697.                 UBYTE Mask = RPort -> Mask;
  698.  
  699.                 SetWrMsk(RPort,DepthMask);
  700.  
  701.                 RectFill(RPort,Left,Top,Left + XSize - 1,Top + TextFontHeight - 1);
  702.  
  703.                 SetWrMsk(RPort,Mask);
  704.             }
  705.             else
  706.                 RectFill(RPort,Left,Top,Left + XSize - 1,Top + TextFontHeight - 1);
  707.  
  708.             SetABPenDrMd(RPort,OldAPen,OldBPen,OldDrMd);
  709.         }
  710.         else
  711.         {
  712.             SetAPen(RPort,DepthMask);
  713.             SetDrMd(RPort,JAM1 | COMPLEMENT);
  714.  
  715.             if(UseMasking)
  716.             {
  717.                 UBYTE Mask = RPort -> Mask;
  718.  
  719.                 SetWrMsk(RPort,DepthMask);
  720.  
  721.                 RectFill(RPort,Left,Top,Left + XSize - 1,Top + TextFontHeight - 1);
  722.  
  723.                 SetWrMsk(RPort,Mask);
  724.             }
  725.             else
  726.                 RectFill(RPort,Left,Top,Left + XSize - 1,Top + TextFontHeight - 1);
  727.  
  728.             SetAPen(RPort,OldAPen);
  729.             SetDrMd(RPort,OldDrMd);
  730.         }
  731.     }
  732. }
  733.  
  734.     /* RedrawCursor():
  735.      *
  736.      *    Change the appearance of the cursor.
  737.      */
  738.  
  739. STATIC VOID
  740. RedrawCursor(VOID)
  741. {
  742.     ObtainSemaphore(&TerminalSemaphore);
  743.  
  744.     RethinkCursorPosition();
  745.  
  746.     if(CursorGhosted)
  747.     {
  748.         SetAfPt(RPort,(UWORD *)&Crosshatch,1);
  749.  
  750.         ToggleCursor();
  751.  
  752.         SetAfPt(RPort,NULL,0);
  753.     }
  754.     else
  755.         ToggleCursor();
  756.  
  757.     ReleaseSemaphore(&TerminalSemaphore);
  758. }
  759.  
  760.     /* DoCancel():
  761.      *
  762.      *    Cancel any currently scanned sequence.
  763.      */
  764.  
  765. BYTE 
  766. DoCancel()
  767. {
  768.     InSequence    = FALSE;
  769.     CharsInBuffer    = ScanStep = 0;
  770.  
  771.     return(FALSE);
  772. }
  773.  
  774.     /* CSIFake():
  775.      *
  776.      *    This routine was added to support 8-bit control
  777.      *    sequences introduced by a CSI character.
  778.      */
  779.  
  780. VOID
  781. CSIFake()
  782. {
  783.         /* Reset scanner */
  784.  
  785.     DoCancel();
  786.  
  787.         /* Perform as if ESC [ had been transmitted. */
  788.  
  789.     InSequence = ParseCode('[');
  790. }
  791.  
  792.     /* ParseCode(UBYTE c):
  793.      *
  794.      *    Input:    A character to be passed through the ANSI code
  795.      *        parser.
  796.      *
  797.      *    Output:    FALSE if input characters did form a valid ANSI
  798.      *        control sequence or if input characters did not
  799.      *        form an ANSI control sequence at all.
  800.      *
  801.      *        TRUE if input characters did possibly introduce
  802.      *        a valid ANSI control sequence.
  803.      */
  804.  
  805. BYTE 
  806. ParseCode(UBYTE c)
  807. {
  808.         /* ScanStep = 0:    This is the first character
  809.          *            to introduce a control sequence.
  810.          */
  811.  
  812.     if(!ScanStep)
  813.     {
  814.         register WORD i;
  815.  
  816.             /* Scan all available codes and try to find
  817.              * a match.
  818.              */
  819.  
  820.         for(i = 0 ; i < NumCodes ; i++)
  821.         {
  822.                 /* This character may introduce a
  823.                  * control sequence.
  824.                  */
  825.  
  826.             if(ANSICode[i] . FirstChar == c)
  827.             {
  828.                     /* If this is a single
  829.                      * character control sequence
  830.                      * call the approriate function
  831.                      * and exit immediately.
  832.                      */
  833.  
  834.                 if(ANSICode[i] . ExactSize == 1)
  835.                 {
  836.                     if(Config -> TerminalConfig -> EmulationMode != EMULATION_ATOMIC)
  837.                     {
  838.                         SaveBuffer[CharsInBuffer++] = c;
  839.                         SaveBuffer[CharsInBuffer  ] = 0;
  840.  
  841.                         (*ANSICode[i] . Func)(SaveBuffer);
  842.                     }
  843.  
  844.                     CharsInBuffer = ScanStep = 0;
  845.  
  846.                     return(FALSE);
  847.                 }
  848.                 else
  849.                 {
  850.                         /* The length of this control
  851.                          * sequence is greater than
  852.                          * a single character. Save
  853.                          * the input character and
  854.                          * return.
  855.                          */
  856.  
  857.                     ScanStep = i;
  858.  
  859.                     SaveBuffer[CharsInBuffer++] = c;
  860.  
  861.                         /* Where to stop. */
  862.  
  863.                     Arnie = ANSICode[i] . Terminator;
  864.  
  865.                     return(TRUE);
  866.                 }
  867.             }
  868.         }
  869.     }
  870.     else
  871.     {
  872.         if(CharsInBuffer < MAX_SCAN_SIZE)
  873.         {
  874.             if(Arnie)
  875.             {
  876.                 register WORD i;
  877.  
  878.                     /* Scan the remaining codes for a match. */
  879.     
  880.                 for(i = ScanStep ; i < NumCodes ; i++)
  881.                 {
  882.                         /* This sequence begins with the
  883.                          * same character the parser was
  884.                          * initialized with, so let's take
  885.                          * a look at it.
  886.                          */
  887.     
  888.                     if(ANSICode[i] . FirstChar == SaveBuffer[0])
  889.                     {
  890.                             /* This character is supposed to
  891.                              * terminate the sequence, so exit.
  892.                              */
  893.     
  894.                         if(Arnie[c])
  895.                         {
  896.                             if(Config -> TerminalConfig -> EmulationMode != EMULATION_ATOMIC)
  897.                             {
  898.                                 SaveBuffer[CharsInBuffer++] = c;
  899.                                 SaveBuffer[CharsInBuffer  ] = 0;
  900.     
  901.                                 (*ANSICode[i] . Func)(SaveBuffer);
  902.                             }
  903.     
  904.                             CharsInBuffer = ScanStep = 0;
  905.  
  906.                             Arnie = NULL;
  907.     
  908.                             return(FALSE);
  909.                         }
  910.                         else
  911.                         {
  912.                                 /* If this character is part of
  913.                                  * a legal sequence store it
  914.                                  * and return.
  915.                                  */
  916.     
  917.                             if(ANSICode[i] . Match[c])
  918.                             {
  919.                                 ScanStep = i;
  920.     
  921.                                 SaveBuffer[CharsInBuffer++] = c;
  922.     
  923.                                 return(TRUE);
  924.                             }
  925.                         }
  926.                     }
  927.                 }
  928.             }
  929.             else
  930.             {
  931.                 register WORD i;
  932.  
  933.                 for(i = ScanStep ; i < NumCodes ; i++)
  934.                 {
  935.                         /* This sequence begins with the
  936.                          * same character the parser was
  937.                          * initialized with, so let's take
  938.                          * a look at it.
  939.                          */
  940.     
  941.                     if(ANSICode[i] . FirstChar == SaveBuffer[0])
  942.                     {
  943.                             /* This character is supposed to
  944.                              * terminate the sequence, so exit.
  945.                              */
  946.     
  947.                         if(ANSICode[i] . LastChar == c)
  948.                         {
  949.                             if(Config -> TerminalConfig -> EmulationMode != EMULATION_ATOMIC)
  950.                             {
  951.                                 SaveBuffer[CharsInBuffer++] = c;
  952.                                 SaveBuffer[CharsInBuffer  ] = 0;
  953.     
  954.                                 (*ANSICode[i] . Func)(SaveBuffer);
  955.                             }
  956.     
  957.                             CharsInBuffer = ScanStep = 0;
  958.     
  959.                             return(FALSE);
  960.                         }
  961.                         else
  962.                         {
  963.                                 /* If this character is part of
  964.                                  * a legal sequence store it
  965.                                  * and return.
  966.                                  */
  967.     
  968.                             if(ANSICode[i] . Match[c])
  969.                             {
  970.                                 ScanStep = i;
  971.     
  972.                                 SaveBuffer[CharsInBuffer++] = c;
  973.     
  974.                                 return(TRUE);
  975.                             }
  976.                         }
  977.                     }
  978.                 }
  979.             }
  980.         }
  981.     }
  982.  
  983.         /* Return failure. */
  984.  
  985.     CharsInBuffer = ScanStep = 0;
  986.  
  987.     Arnie = NULL;
  988.  
  989.     return(FALSE);
  990. }
  991.  
  992.     /* NormalCursor():
  993.      *
  994.      *    Enable normal (filled) cursor image.
  995.      */
  996.  
  997. VOID
  998. NormalCursor()
  999. {
  1000.     ObtainSemaphore(&TerminalSemaphore);
  1001.  
  1002.     if(CursorGhosted)
  1003.     {
  1004.         if(CursorEnabled && !CursorInvisible)
  1005.         {
  1006.             SetAfPt(RPort,(UWORD *)&Crosshatch,1);
  1007.  
  1008.             ToggleCursor();
  1009.  
  1010.             SetAfPt(RPort,NULL,0);
  1011.  
  1012.             ToggleCursor();
  1013.         }
  1014.  
  1015.         CursorGhosted = FALSE;
  1016.     }
  1017.  
  1018.     ReleaseSemaphore(&TerminalSemaphore);
  1019. }
  1020.  
  1021.     /* GhostCursor():
  1022.      *
  1023.      *    Enable ghosted (checkered) cursor image.
  1024.      */
  1025.  
  1026. VOID
  1027. GhostCursor()
  1028. {
  1029.     ObtainSemaphore(&TerminalSemaphore);
  1030.  
  1031.     if(!CursorGhosted)
  1032.     {
  1033.         if(CursorEnabled && !CursorInvisible)
  1034.         {
  1035.             ToggleCursor();
  1036.  
  1037.             SetAfPt(RPort,(UWORD *)&Crosshatch,1);
  1038.  
  1039.             ToggleCursor();
  1040.  
  1041.             SetAfPt(RPort,NULL,0);
  1042.         }
  1043.  
  1044.         CursorGhosted = TRUE;
  1045.     }
  1046.  
  1047.     ReleaseSemaphore(&TerminalSemaphore);
  1048. }
  1049.  
  1050.     /* RepositionCursor():
  1051.      *
  1052.      *    Redraw the cursor at the new position.
  1053.      */
  1054.  
  1055. VOID
  1056. RepositionCursor()
  1057. {
  1058.     ObtainSemaphore(&TerminalSemaphore);
  1059.  
  1060.     RethinkCursorPosition();
  1061.  
  1062.     Move(RPort,WindowLeft + DestX,WindowTop + DestY + TextFontBase);
  1063.  
  1064.     ReleaseSemaphore(&TerminalSemaphore);
  1065. }
  1066.  
  1067.     /* ClearCursor():
  1068.      *
  1069.      *    Clear the cursor image.
  1070.      */
  1071.  
  1072. VOID
  1073. ClearCursor()
  1074. {
  1075.     ObtainSemaphore(&TerminalSemaphore);
  1076.  
  1077.     if(CursorEnabled && !CursorInvisible)
  1078.     {
  1079.         RedrawCursor();
  1080.  
  1081.         CursorEnabled = FALSE;
  1082.     }
  1083.  
  1084.     ReleaseSemaphore(&TerminalSemaphore);
  1085. }
  1086.  
  1087.     /* DrawCursor():
  1088.      *
  1089.      *    Explicitely (re-)draw the cursor image.
  1090.      */
  1091.  
  1092. VOID
  1093. DrawCursor()
  1094. {
  1095.     ObtainSemaphore(&TerminalSemaphore);
  1096.  
  1097.     if(!CursorEnabled && !CursorInvisible)
  1098.     {
  1099.         RedrawCursor();
  1100.  
  1101.         CursorEnabled = TRUE;
  1102.     }
  1103.  
  1104.     ReleaseSemaphore(&TerminalSemaphore);
  1105. }
  1106.  
  1107.     /* BackupRender():
  1108.      *
  1109.      *    Save current draw modes, pen and position or restore
  1110.      *    the data.
  1111.      */
  1112.  
  1113. VOID
  1114. BackupRender()
  1115. {
  1116.     STATIC BYTE    Called = FALSE;
  1117.     STATIC UBYTE    DrMd,
  1118.             FgPen,
  1119.             BgPen;
  1120.     STATIC UWORD    OldX,OldY;
  1121.     STATIC UBYTE    Style;
  1122.  
  1123.     if(!Called)
  1124.     {
  1125.         DrMd    = ReadDrMd(RPort);
  1126.         FgPen    = ReadAPen(RPort);
  1127.         BgPen    = ReadBPen(RPort);
  1128.  
  1129.         OldX    = RPort -> cp_x - WindowLeft;
  1130.         OldY    = RPort -> cp_y - WindowTop;
  1131.  
  1132.         Style    = StyleType;
  1133.  
  1134.         Called    = TRUE;
  1135.     }
  1136.     else
  1137.     {
  1138.         if(ReadDrMd(RPort) != DrMd)
  1139.             SetDrMd(RPort,DrMd);
  1140.  
  1141.         if(ReadAPen(RPort) != FgPen)
  1142.             SetAPen(RPort,FgPen);
  1143.  
  1144.         if(ReadBPen(RPort) != BgPen)
  1145.             SetBPen(RPort,BgPen);
  1146.  
  1147.         Move(RPort,OldX + WindowLeft,OldY + WindowTop);
  1148.  
  1149.         if(Style != StyleType)
  1150.         {
  1151.             SetSoftStyle(RPort,Style,0xFF);
  1152.  
  1153.             StyleType = Style;
  1154.         }
  1155.  
  1156.         Called = FALSE;
  1157.     }
  1158. }
  1159.  
  1160.     /* ShiftChar(LONG Size):
  1161.      *
  1162.      *    Simulate character insertion at the current cursor
  1163.      *    position by shifting the whole line Size times eight pixels
  1164.      *    to the right.
  1165.      */
  1166.  
  1167. VOID __regargs
  1168. ShiftChar(LONG Size)
  1169. {
  1170.     LONG DeltaX,MinX,MinY;
  1171.  
  1172.     MinY = MUL_Y(CursorY);
  1173.  
  1174.     if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
  1175.     {
  1176.         if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  1177.         {
  1178.             DeltaX    = MUL_X(Size);
  1179.             MinX    = MUL_X(CursorX);
  1180.         }
  1181.         else
  1182.         {
  1183.             DeltaX    = MUL_X(Size) * 2;
  1184.             MinX    = MUL_X(CursorX) * 2;
  1185.         }
  1186.     }
  1187.     else
  1188.     {
  1189.         if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  1190.         {
  1191.             DeltaX    = MUL_X(Size) / 2;
  1192.             MinX    = MUL_X(CursorX) / 2;
  1193.         }
  1194.         else
  1195.         {
  1196.             DeltaX    = MUL_X(Size);
  1197.             MinX    = MUL_X(CursorX);
  1198.         }
  1199.     }
  1200.  
  1201.     if(MinX < WindowWidth)
  1202.     {
  1203.         BackupRender();
  1204.  
  1205.         ScrollLineRaster(RPort,-DeltaX,0,MinX,MinY,LastPixel,MinY + TextFontHeight - 1,FALSE);
  1206.  
  1207.         BackupRender();
  1208.     }
  1209. }
  1210.  
  1211.     /* Ignore():
  1212.      *
  1213.      *    Do nothing, return immediately.
  1214.      */
  1215.  
  1216. VOID
  1217. Ignore()
  1218. {
  1219. }
  1220.  
  1221.     /* ScrollDown(STRPTR Buffer):
  1222.      *
  1223.      *    Scroll the current region down.
  1224.      */
  1225.  
  1226. VOID
  1227. ScrollDown(STRPTR Buffer)
  1228. {
  1229.     WORD Value;
  1230.  
  1231.     ReadValue(Buffer,&Value);
  1232.  
  1233.     if(Value < 1)
  1234.         Value = 1;
  1235.  
  1236.     ScrollRegion(-Value);
  1237. }
  1238.  
  1239.     /* ScrollUp(STRPTR Buffer):
  1240.      *
  1241.      *    Scroll the current region up.
  1242.      */
  1243.  
  1244. VOID
  1245. ScrollUp(STRPTR Buffer)
  1246. {
  1247.     WORD Value;
  1248.  
  1249.     ReadValue(Buffer,&Value);
  1250.  
  1251.     if(Value < 1)
  1252.         Value = 1;
  1253.  
  1254.     ScrollRegion(Value);
  1255. }
  1256.  
  1257.     /* CursorScrollDown():
  1258.      *
  1259.      *    Move cursor down and scroll region if necessary.
  1260.      */
  1261.  
  1262. VOID
  1263. CursorScrollDown()
  1264. {
  1265.     DownLine();
  1266.  
  1267.     RepositionCursor();
  1268. }
  1269.  
  1270. VOID
  1271. DownLine()
  1272. {
  1273.     UBYTE InRegion = TRUE;
  1274.     WORD  Hit      = LastLine;
  1275.  
  1276.     if(RegionSet)
  1277.     {
  1278.         if(CursorY <= Bottom)
  1279.             Hit = Bottom;
  1280.         else
  1281.             InRegion = FALSE;
  1282.     }
  1283.  
  1284.     if(CursorY == Hit)
  1285.     {
  1286.         if(InRegion)
  1287.             ScrollRegion(1);
  1288.     }
  1289.     else
  1290.     {
  1291.         CursorY++;
  1292.  
  1293.         if(CursorY > LastLine)
  1294.             CursorY = LastLine;
  1295.  
  1296.         ConFontScaleUpdate();
  1297.     }
  1298. }
  1299.  
  1300.     /* CursorScrollUp():
  1301.      *
  1302.      *    Move cursor up and scroll region if necessary.
  1303.      */
  1304.  
  1305. VOID
  1306. CursorScrollUp()
  1307. {
  1308.     BYTE InRegion    = TRUE;
  1309.     WORD Hit    = 0;
  1310.  
  1311.     if(RegionSet)
  1312.     {
  1313.         if(CursorY >= Top)
  1314.             Hit = Top;
  1315.         else
  1316.             InRegion = FALSE;
  1317.     }
  1318.  
  1319.     if(CursorY == Hit)
  1320.     {
  1321.         if(InRegion)
  1322.             ScrollRegion(-1);
  1323.     }
  1324.     else
  1325.     {
  1326.         if(--CursorY < 0)
  1327.             CursorY = 0;
  1328.  
  1329.         ConFontScaleUpdate();
  1330.     }
  1331.  
  1332.     RepositionCursor();
  1333. }
  1334.  
  1335.     /* NextLine():
  1336.      *
  1337.      *    Do something like CR+LF.
  1338.      */
  1339.  
  1340. VOID
  1341. NextLine()
  1342. {
  1343.     CursorX = 0;
  1344.  
  1345.     DownLine();
  1346.  
  1347.     RepositionCursor();
  1348. }
  1349.  
  1350.     /* SaveCursor():
  1351.      *
  1352.      *    Save cursor position and rendering attributes.
  1353.      */
  1354.  
  1355. VOID
  1356. SaveCursor()
  1357. {
  1358.     CursorBackup . Charset        = Charset;
  1359.     CursorBackup . Attributes    = Attributes;
  1360.     CursorBackup . CursorX        = CursorX;
  1361.     CursorBackup . CursorY        = CursorY;
  1362.     CursorBackup . Style        = StyleType;
  1363.     CursorBackup . FgPen        = GetPenIndex(ReadAPen(RPort));
  1364.     CursorBackup . BgPen        = GetPenIndex(ReadBPen(RPort));
  1365.     CursorBackup . CurrentFont    = CurrentFont;
  1366.     CursorBackup . CharMode[0]    = CharMode[0];
  1367.     CursorBackup . CharMode[1]    = CharMode[1];
  1368. }
  1369.  
  1370.     /* FontStuff(STRPTR Buffer):
  1371.      *
  1372.      *    Set the drawing font (standard characters/line).
  1373.      */
  1374.  
  1375. VOID 
  1376. FontStuff(STRPTR Buffer)
  1377. {
  1378.     BYTE Changed = FALSE;
  1379.  
  1380.     if(Buffer[0] == '(')
  1381.     {
  1382.         switch(LastChar(Buffer))
  1383.         {
  1384.             case 'A':
  1385.             case 'B':
  1386.  
  1387.                 if(CharMode[0] != TABLE_ASCII && !Charset)
  1388.                     Changed = TRUE;
  1389.  
  1390.                 CharMode[0] = TABLE_ASCII;
  1391.  
  1392.                 break;
  1393.  
  1394.             case '0':
  1395.  
  1396.                 if(CharMode[0] != TABLE_GFX && !Charset)
  1397.                     Changed = TRUE;
  1398.  
  1399.                 CharMode[0] = TABLE_GFX;
  1400.  
  1401.                 break;
  1402.         }
  1403.     }
  1404.  
  1405.     if(Buffer[0] == ')')
  1406.     {
  1407.         switch(LastChar(Buffer))
  1408.         {
  1409.             case 'A':
  1410.             case 'B':
  1411.  
  1412.                 if(CharMode[1] != TABLE_ASCII && Charset == 1)
  1413.                     Changed = TRUE;
  1414.  
  1415.                 CharMode[1] = TABLE_ASCII;
  1416.  
  1417.                 break;
  1418.  
  1419.             case '0':
  1420.  
  1421.                 if(CharMode[1] != TABLE_GFX && Charset == 1)
  1422.                     Changed = TRUE;
  1423.  
  1424.                 CharMode[1] = TABLE_GFX;
  1425.  
  1426.                 break;
  1427.         }
  1428.     }
  1429.  
  1430.     if(Changed)
  1431.     {
  1432.         BackupRender();
  1433.  
  1434.         if(Charset)
  1435.             DoShiftIn();
  1436.         else
  1437.             DoShiftOut();
  1438.  
  1439.         BackupRender();
  1440.     }
  1441. }
  1442.  
  1443.     /* LoadCursor():
  1444.      *
  1445.      *    Load cursor position and rendering attributes.
  1446.      */
  1447.  
  1448. VOID
  1449. LoadCursor()
  1450. {
  1451.     Charset        = CursorBackup . Charset;
  1452.  
  1453.     CharMode[0]    = CursorBackup . CharMode[0];
  1454.     CharMode[1]    = CursorBackup . CharMode[1];
  1455.  
  1456.     if(CurrentFont != CursorBackup . CurrentFont)
  1457.     {
  1458.         CurrentFont = CursorBackup . CurrentFont;
  1459.  
  1460.         SetFont(RPort,CurrentFont);
  1461.  
  1462.         ConOutputUpdate();
  1463.     }
  1464.  
  1465.     if(StyleType != CursorBackup . Style)
  1466.     {
  1467.         SetSoftStyle(RPort,CursorBackup . Style,0xFF);
  1468.  
  1469.         StyleType = CursorBackup . Style;
  1470.     }
  1471.  
  1472.     if(ReadAPen(RPort) != MappedPens[0][CursorBackup . FgPen])
  1473.         SetAPen(RPort,MappedPens[0][CursorBackup . FgPen]);
  1474.  
  1475.     if(ReadBPen(RPort) != MappedPens[0][CursorBackup . BgPen])
  1476.         SetBPen(RPort,MappedPens[0][CursorBackup . BgPen]);
  1477.  
  1478.     Attributes    = CursorBackup . Attributes;
  1479.     CursorX        = CursorBackup . CursorX;
  1480.     CursorY        = CursorBackup . CursorY;
  1481.  
  1482.     ConFontScaleUpdate();
  1483.  
  1484.     RepositionCursor();
  1485. }
  1486.  
  1487.     /* ScaleFont(STRPTR Buffer):
  1488.      *
  1489.      *    Select a new font scale.
  1490.      */
  1491.  
  1492. VOID 
  1493. ScaleFont(STRPTR Buffer)
  1494. {
  1495.     if(!Config -> EmulationConfig -> FontLocked)
  1496.     {
  1497.         WORD NewScale,Scale;
  1498.  
  1499.         Scale = RasterAttr[CursorY];
  1500.  
  1501.         NewScale = Scale;
  1502.  
  1503.         switch(LastChar(Buffer))
  1504.         {
  1505.             case '3':
  1506.  
  1507.                 NewScale = SCALE_ATTR_TOP2X;
  1508.  
  1509.                 break;
  1510.  
  1511.             case '4':
  1512.  
  1513.                 NewScale = SCALE_ATTR_BOT2X;
  1514.  
  1515.                 break;
  1516.  
  1517.             case '5':
  1518.  
  1519.                 NewScale = SCALE_NORMAL;
  1520.  
  1521.                 break;
  1522.  
  1523.             case '6':
  1524.  
  1525.                 NewScale = SCALE_ATTR_2X;
  1526.  
  1527.                 break;
  1528.         }
  1529.  
  1530.         if(Scale != NewScale)
  1531.         {
  1532.             UBYTE    *RasterPtr    = &Raster[CursorY * RasterWidth];
  1533.             WORD     RightMargin    = LastColumn + 1,
  1534.                  CursorXSave    = CursorX;
  1535.  
  1536.             if(NewScale != SCALE_ATTR_NORMAL)
  1537.                 RightMargin /= 2;
  1538.  
  1539.             RasterAttr[CursorY] = NewScale;
  1540.  
  1541.             RethinkRasterLimit();
  1542.  
  1543.             ConFontScaleUpdate();
  1544.  
  1545.             if(((Config -> EmulationConfig -> FontScale == SCALE_NORMAL) && (NewScale == SCALE_ATTR_NORMAL)) || ((Config -> EmulationConfig -> FontScale == SCALE_HALF) && (NewScale == SCALE_ATTR_2X)))
  1546.             {
  1547.                 Move(RPort,WindowLeft,WindowTop + MUL_Y(CursorY) + TextFontBase);
  1548.                 Text(RPort,RasterPtr,RightMargin);
  1549.             }
  1550.             else
  1551.             {
  1552.                 CursorX = 0;
  1553.  
  1554.                 PrintScaled(RasterPtr,RightMargin,NewScale);
  1555.             }
  1556.  
  1557.             if(CursorXSave >= RightMargin)
  1558.                 CursorX = RightMargin - 1;
  1559.             else
  1560.                 CursorX = CursorXSave;
  1561.         }
  1562.  
  1563.         RepositionCursor();
  1564.     }
  1565. }
  1566.  
  1567.     /* AlignmentTest():
  1568.      *
  1569.      *    Perform screen alignment test, fill the screen with `E's.
  1570.      */
  1571.  
  1572. VOID
  1573. AlignmentTest()
  1574. {
  1575.     STRPTR Buffer;
  1576.  
  1577.     if(Buffer = AllocVecPooled(LastColumn + 1,MEMF_ANY))
  1578.     {
  1579.         WORD i;
  1580.  
  1581.         memset(Buffer,'E',LastColumn + 1);
  1582.  
  1583.         EraseScreen("2");
  1584.  
  1585.         if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
  1586.         {
  1587.             for(i = 0 ; i <= LastLine ; i++)
  1588.             {
  1589.                 CursorX = 0;
  1590.                 CursorY = i;
  1591.  
  1592.                 RasterAttr[i] = SCALE_ATTR_NORMAL;
  1593.  
  1594.                 RasterPutString(Buffer,LastColumn + 1);
  1595.                 ScrollLinePutString(LastColumn + 1);
  1596.  
  1597.                 Move(RPort,WindowLeft,WindowTop + MUL_Y(i) + TextFontBase);
  1598.                 PrintScaled(Buffer,LastColumn + 1,SCALE_ATTR_NORMAL);
  1599.             }
  1600.         }
  1601.         else
  1602.         {
  1603.             for(i = 0 ; i <= LastLine ; i++)
  1604.             {
  1605.                 CursorX = 0;
  1606.                 CursorY = i;
  1607.  
  1608.                 RasterAttr[i] = SCALE_ATTR_NORMAL;
  1609.  
  1610.                 RasterPutString(Buffer,LastColumn + 1);
  1611.                 ScrollLinePutString(LastColumn + 1);
  1612.  
  1613.                 Move(RPort,WindowLeft,WindowTop + MUL_Y(i) + TextFontBase);
  1614.                 Text(RPort,Buffer,LastColumn + 1);
  1615.             }
  1616.         }
  1617.  
  1618.         CursorX = CursorY = 0;
  1619.  
  1620.         RethinkRasterLimit();
  1621.  
  1622.         RepositionCursor();
  1623.  
  1624.         FreeVecPooled(Buffer);
  1625.  
  1626.         ConFontScaleUpdate();
  1627.     }
  1628. }
  1629.  
  1630.     /* SetTab():
  1631.      *
  1632.      *    Set a tabulator stop at the current position.
  1633.      */
  1634.  
  1635. VOID
  1636. SetTab()
  1637. {
  1638.     if(CursorX < TabStopMax)
  1639.         TabStops[CursorX] = TRUE;
  1640. }
  1641.  
  1642.     /* RequestTerminal(STRPTR Buffer):
  1643.      *
  1644.      *    Return the current terminal position.
  1645.      */
  1646.  
  1647. VOID 
  1648. RequestTerminal(STRPTR Buffer)
  1649. {
  1650.     switch(Buffer[0])
  1651.     {
  1652.             /* Make ourselves known as a VT200
  1653.              * terminal.
  1654.              */
  1655.  
  1656.         case '[':
  1657.  
  1658.             if(Buffer[1] != '>')
  1659.                 EmulationSerWrite("\033[?62;1;2;6;7;8;9c",-1);
  1660.             else
  1661.                 EmulationSerWrite("\033[>1;10;0c",-1);
  1662.  
  1663.             break;
  1664.  
  1665.             /* This is an old status request type,
  1666.              * we will return the standard `I am a
  1667.              * VT101' sequence.
  1668.              */
  1669.  
  1670.         case 'Z':
  1671.  
  1672.             EmulationSerWrite("\033[?1;0c",-1);
  1673.             break;
  1674.     }
  1675. }
  1676.  
  1677.     /* SoftReset():
  1678.      *
  1679.      *    Plain and simple: reset the text rendering colours, style and the
  1680.      *    font being used. This works similar to the Reset() call which
  1681.      *    also clears the screen.
  1682.      */
  1683.  
  1684. VOID
  1685. SoftReset()
  1686. {
  1687.     ObtainSemaphore(&TerminalSemaphore);
  1688.  
  1689.         /* Are we running on an external emulation? */
  1690.  
  1691.     if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  1692.     {
  1693.         XEmulatorResetTextStyles(XEM_IO);
  1694.         XEmulatorResetCharset(XEM_IO);
  1695.     }
  1696.     else
  1697.     {
  1698.             /* Reset the text rendering styles. */
  1699.  
  1700.         SetAttributes("0m");
  1701.  
  1702.         if(!Config -> EmulationConfig -> FontLocked)
  1703.             Config -> EmulationConfig -> FontScale = SCALE_NORMAL;
  1704.  
  1705.         ConFontScaleUpdate();
  1706.  
  1707.             /* Reset the text rendering colours. */
  1708.  
  1709.         FgPen = GetPenIndex(SafeTextPen);
  1710.         BgPen = 0;
  1711.  
  1712.         if(ReadAPen(RPort) != MappedPens[0][FgPen])
  1713.             SetAPen(RPort,MappedPens[0][FgPen]);
  1714.  
  1715.         if(ReadBPen(RPort) != MappedPens[0][BgPen])
  1716.             SetBPen(RPort,MappedPens[0][BgPen]);
  1717.  
  1718.         SetWrMsk(RPort,DepthMask);
  1719.  
  1720.         CurrentFont = TextFont;
  1721.  
  1722.         SetFont(RPort,CurrentFont);
  1723.  
  1724.         ConOutputUpdate();
  1725.     }
  1726.  
  1727.     ReleaseSemaphore(&TerminalSemaphore);
  1728. }
  1729.  
  1730.     /* Reset():
  1731.      *
  1732.      *    Reset terminal to initial state.
  1733.      */
  1734.  
  1735. VOID
  1736. Reset()
  1737. {
  1738.     LONG    MaxColumns,MaxLines,
  1739.         Columns,Lines,
  1740.         i;
  1741.  
  1742.     ObtainSemaphore(&TerminalSemaphore);
  1743.  
  1744.     CursorEnabled = CursorInvisible = FALSE;
  1745.  
  1746.     if(Window -> Flags & WFLG_WINDOWACTIVE)
  1747.         CursorGhosted = FALSE;
  1748.     else
  1749.         CursorGhosted = TRUE;
  1750.  
  1751.         /* Determine window inner dimensions and top/left edge offsets. */
  1752.  
  1753.     WindowLeft    = Window -> BorderLeft;
  1754.     WindowTop    = Window -> BorderTop;
  1755.  
  1756.     WindowWidth    = Window -> Width - (Window -> BorderLeft + Window -> BorderRight);
  1757.     WindowHeight    = Window -> Height - (Window -> BorderTop + Window -> BorderBottom);
  1758.  
  1759.     MaxColumns    = WindowWidth / TextFontWidth;
  1760.     MaxLines    = WindowHeight / TextFontHeight;
  1761.  
  1762.         /* Set up the new screen width. */
  1763.  
  1764.     if(Config -> TerminalConfig -> NumColumns < 20)
  1765.         Columns = MaxColumns;
  1766.     else
  1767.         Columns = Config -> TerminalConfig -> NumColumns;
  1768.  
  1769.         /* Set up the new screen height. */
  1770.  
  1771.     if(Config -> TerminalConfig -> NumLines < 20)
  1772.         Lines = MaxLines;
  1773.     else
  1774.         Lines = Config -> TerminalConfig -> NumLines;
  1775.  
  1776.         /* More columns than we will be able to display? */
  1777.  
  1778.     if(Columns > MaxColumns)
  1779.         Columns = MaxColumns;
  1780.  
  1781.         /* More lines than we will be able to display? */
  1782.  
  1783.     if(Lines > MaxLines)
  1784.         Lines = MaxLines;
  1785.  
  1786.         /* Set up the central data. */
  1787.  
  1788.     LastColumn    = Columns - 1;
  1789.     LastLine    = Lines - 1;
  1790.     LastPixel    = MUL_X(Columns) - 1;
  1791.  
  1792.     memset(TabStops,FALSE,TabStopMax);
  1793.  
  1794.     for(i = 8 ; i < TabStopMax ; i += 8)
  1795.         TabStops[i] = TRUE;
  1796.  
  1797.     CharMode[0] = TABLE_ASCII;
  1798.     CharMode[1] = TABLE_GFX;
  1799.  
  1800.     Charset = 0;
  1801.  
  1802.     SetAPen(RPort,MappedPens[0][0]);
  1803.  
  1804.     SetWrMsk(RPort,DepthMask);
  1805.  
  1806.     RectFill(RPort,WindowLeft,WindowTop,WindowLeft + WindowWidth - 1,WindowTop + WindowHeight - 1);
  1807.  
  1808.     ScrollLineEraseScreen(2);
  1809.  
  1810.     RasterEraseScreen(2);
  1811.  
  1812.     FgPen = GetPenIndex(SafeTextPen);
  1813.     BgPen = 0;
  1814.  
  1815.     if(ReadAPen(RPort) != MappedPens[0][FgPen])
  1816.         SetAPen(RPort,MappedPens[0][FgPen]);
  1817.  
  1818.     if(ReadBPen(RPort) != MappedPens[0][BgPen])
  1819.         SetBPen(RPort,MappedPens[0][BgPen]);
  1820.  
  1821.     if(StyleType != FS_NORMAL)
  1822.     {
  1823.         SetSoftStyle(RPort,FS_NORMAL,0xFF);
  1824.  
  1825.         StyleType = FS_NORMAL;
  1826.     }
  1827.  
  1828.     CurrentFont = TextFont;
  1829.  
  1830.     SetFont(RPort,CurrentFont);
  1831.  
  1832.     ConOutputUpdate();
  1833.  
  1834.     UseRegion = FALSE;
  1835.     RegionSet = FALSE;
  1836.  
  1837.     if(!Config -> EmulationConfig -> CursorLocked)
  1838.         Config -> EmulationConfig -> CursorMode = KEYMODE_STANDARD;
  1839.  
  1840.     if(!Config -> EmulationConfig -> KeysLocked)
  1841.         Config -> EmulationConfig -> NumericMode = KEYMODE_STANDARD;
  1842.  
  1843.     Config -> EmulationConfig -> NewLineMode    = FALSE;
  1844.     Config -> EmulationConfig -> InsertMode        = FALSE;
  1845.     Config -> EmulationConfig -> LineWrap        = TRUE;
  1846.     Config -> EmulationConfig -> ScrollMode        = SCROLL_JUMP;
  1847.  
  1848.     if(!Config -> EmulationConfig -> FontLocked)
  1849.         Config -> EmulationConfig -> FontScale = SCALE_NORMAL;
  1850.  
  1851.     Attributes    = 0;
  1852.     Top        = 0;
  1853.     Bottom        = LastLine;
  1854.     CursorX        = 0;
  1855.     CursorY        = 0;
  1856.  
  1857.     CursorBackup . Charset        = Charset;
  1858.     CursorBackup . Attributes    = Attributes;
  1859.     CursorBackup . CursorX        = CursorX;
  1860.     CursorBackup . CursorY        = CursorY;
  1861.     CursorBackup . Style        = StyleType;
  1862.     CursorBackup . FgPen        = FgPen;
  1863.     CursorBackup . BgPen        = BgPen;
  1864.     CursorBackup . CurrentFont    = CurrentFont;
  1865.     CursorBackup . CharMode[0]    = CharMode[0];
  1866.     CursorBackup . CharMode[1]    = CharMode[1];
  1867.  
  1868.     ConFontScaleUpdate();
  1869.  
  1870.     RepositionCursor();
  1871.  
  1872.     ReleaseSemaphore(&TerminalSemaphore);
  1873. }
  1874.  
  1875.     /* PrinterController(STRPTR Buffer):
  1876.      *
  1877.      *    Controls various screen dump and capture functions.
  1878.      */
  1879.  
  1880. VOID 
  1881. PrinterController(STRPTR Buffer)
  1882. {
  1883.     if(Config -> EmulationConfig -> PrinterEnabled)
  1884.     {
  1885.         switch(Buffer[1])
  1886.         {
  1887.             case 'i':    // Print screen
  1888.             case '0':
  1889.  
  1890.                 if(PrintFullScreen)
  1891.                     PrintRegion(0,LastLine + 1,PrintFormFeed);
  1892.                 else
  1893.                     PrintRegion(Top,Bottom + 1,PrintFormFeed);
  1894.  
  1895.                 break;
  1896.  
  1897.             case '5':    // Turn on printer controller mode
  1898.  
  1899.                 OpenPrinterCapture(TRUE);
  1900.                 break;
  1901.  
  1902.             case '4':    // Turn off printer controller mode
  1903.  
  1904.                 ClosePrinterCapture(FALSE);
  1905.                 break;
  1906.  
  1907.             case '?':
  1908.  
  1909.                 if(Buffer[2] == '1')    // Print current line
  1910.                     PrintRegion(CursorY,CursorY + 1,FALSE);
  1911.  
  1912.                 if(Buffer[2] == '5')    // Turn on auto print mode
  1913.                     OpenPrinterCapture(FALSE);
  1914.  
  1915.                 if(Buffer[2] == '4')    // Turn off auto print mode
  1916.                     ClosePrinterCapture(FALSE);
  1917.  
  1918.                 break;
  1919.         }
  1920.     }
  1921. }
  1922.  
  1923.     /* RequestInformation(STRPTR Buffer):
  1924.      *
  1925.      *    Request miscellaneous information (state & cursor position).
  1926.      */
  1927.  
  1928. VOID 
  1929. RequestInformation(STRPTR Buffer)
  1930. {
  1931.     UBYTE    LocalBuffer[40];
  1932.     WORD    Value;
  1933.  
  1934.     ReadValue(Buffer,&Value);
  1935.  
  1936.     switch(Value)
  1937.     {
  1938.             /* Terminal status report, return code
  1939.              * for `no malfunction'.
  1940.              */
  1941.  
  1942.         case 5:
  1943.  
  1944.             EmulationSerWrite("\033[0n",-1);
  1945.             break;
  1946.  
  1947.             /* The origin is placed at 0/0 and the first
  1948.              * cursor position is 1/1. We'll have to add
  1949.              * 1 to our internal positions since our
  1950.              * universe has been shifted one field to the
  1951.              * left top corner.
  1952.              */
  1953.  
  1954.         case 6:
  1955.  
  1956.             SPrintf(LocalBuffer,"\033[%ld;%ldR",CursorY + 1,CursorX + 1);
  1957.  
  1958.             EmulationSerWrite(LocalBuffer,-1);
  1959.  
  1960.             break;
  1961.  
  1962.             /* A VT200 command: request printer status.
  1963.              * We will return `the printer is ready' in
  1964.              * case the printer control commands are
  1965.              * enabled, else return `no printer connected'.
  1966.              */
  1967.  
  1968.         case 15:
  1969.  
  1970.             if(Config -> EmulationConfig -> PrinterEnabled)
  1971.                 EmulationSerWrite("\033[?10n",-1);
  1972.             else
  1973.                 EmulationSerWrite("\033[?11n",-1);
  1974.  
  1975.             break;
  1976.  
  1977.             /* VT200 command: request user defined
  1978.              * key status. We will return `user
  1979.              * defined keys are locked'.
  1980.              */
  1981.  
  1982.         case 25:
  1983.  
  1984.             EmulationSerWrite("\033[?21n",-1);
  1985.             break;
  1986.  
  1987.             /* Another VT200 command: request
  1988.              * keyboard language. We will return
  1989.              * `keyboard language unknown'.
  1990.              */
  1991.  
  1992.         case 26:
  1993.  
  1994.             EmulationSerWrite("\033[?27;0n",-1);
  1995.             break;
  1996.     }
  1997. }
  1998.  
  1999.     /* SetSomething(STRPTR Buffer):
  2000.      *
  2001.      *    Set a terminal option.
  2002.      */
  2003.  
  2004. VOID 
  2005. SetSomething(STRPTR Buffer)
  2006. {
  2007.     WORD    Value;
  2008.     UBYTE    Last;
  2009.     BOOLEAN    TurnOn;
  2010.  
  2011.     ReadValue(Buffer,&Value);
  2012.     Last = LastChar(Buffer);
  2013.  
  2014.     if(Buffer[1] == '?')
  2015.     {
  2016.         switch(Value)
  2017.         {
  2018.                 /* Set cursor keys applications mode. */
  2019.  
  2020.             case 1:        // DECCKM
  2021.  
  2022.                 if(!Config -> EmulationConfig -> CursorLocked)
  2023.                 {
  2024.                     if(Last == 'h')
  2025.                         Config -> EmulationConfig -> CursorMode = KEYMODE_APPLICATION;
  2026.  
  2027.                     if(Last == 'l')
  2028.                         Config -> EmulationConfig -> CursorMode = KEYMODE_STANDARD;
  2029.                 }
  2030.  
  2031.                 break;
  2032.  
  2033.                 /* ANSI/VT52 mode */
  2034.  
  2035.             case 2:        // DECANM
  2036.  
  2037.                 break;
  2038.  
  2039.                 /* Set line length (132 or 80). */
  2040.  
  2041.             case 3:        // DECCOLM
  2042.  
  2043.                 if(!Config -> EmulationConfig -> FontLocked)
  2044.                 {
  2045.                     if(CursorEnabled)
  2046.                     {
  2047.                         ClearCursor();
  2048.  
  2049.                         TurnOn = TRUE;
  2050.                     }
  2051.                     else
  2052.                         TurnOn = FALSE;
  2053.  
  2054.                     if(Last == 'h')
  2055.                     {
  2056.                         if(Config -> EmulationConfig -> FontScale != SCALE_HALF)
  2057.                         {
  2058.                             CursorX = CursorY = 0;
  2059.  
  2060.                             RepositionCursor();
  2061.  
  2062.                             BackupRender();
  2063.  
  2064.                             SetAPen(RPort,MappedPens[0][0]);
  2065.  
  2066.                             ScrollLineRectFill(RPort,0,0,LastPixel,MUL_Y(LastLine + 1) - 1);
  2067.  
  2068.                             ScrollLineEraseScreen(2);
  2069.  
  2070.                             RasterEraseScreen(2);
  2071.  
  2072.                             SaveConfig(Config,PrivateConfig);
  2073.  
  2074.                             Config -> EmulationConfig -> FontScale = SCALE_HALF;
  2075.  
  2076.                             BackupRender();
  2077.  
  2078.                             ScreenSizeStuff();
  2079.                         }
  2080.                     }
  2081.  
  2082.                     if(Last == 'l')
  2083.                     {
  2084.                         if(Config -> EmulationConfig -> FontScale != SCALE_NORMAL)
  2085.                         {
  2086.                             CursorX = CursorY = 0;
  2087.  
  2088.                             RepositionCursor();
  2089.  
  2090.                             BackupRender();
  2091.  
  2092.                             SetAPen(RPort,MappedPens[0][0]);
  2093.  
  2094.                             ScrollLineRectFill(RPort,0,0,LastPixel,MUL_Y(LastLine + 1) - 1);
  2095.  
  2096.                             ScrollLineEraseScreen(2);
  2097.  
  2098.                             RasterEraseScreen(2);
  2099.  
  2100.                             SaveConfig(Config,PrivateConfig);
  2101.  
  2102.                             Config -> EmulationConfig -> FontScale = SCALE_NORMAL;
  2103.  
  2104.                             BackupRender();
  2105.  
  2106.                             ScreenSizeStuff();
  2107.                         }
  2108.                     }
  2109.  
  2110.                     if(TurnOn)
  2111.                         DrawCursor();
  2112.                 }
  2113.  
  2114.                 break;
  2115.  
  2116.                 /* Set scroll mode (jump or smooth). */
  2117.  
  2118.             case 4:        // DECSCLM
  2119.  
  2120.                 if(Last == 'h')
  2121.                     Config -> EmulationConfig -> ScrollMode = SCROLL_SMOOTH;
  2122.  
  2123.                 if(Last == 'l')
  2124.                     Config -> EmulationConfig -> ScrollMode = SCROLL_JUMP;
  2125.  
  2126.                 break;
  2127.  
  2128.                 /* Reverse/normal screen. */
  2129.  
  2130.             case 5:        // DECSCNM
  2131.  
  2132.                 break;
  2133.  
  2134.                 /* Turn region on or off. */
  2135.  
  2136.             case 6:
  2137.  
  2138.                 if(Last == 'h')
  2139.                     UseRegion = TRUE;
  2140.  
  2141.                 if(Last == 'l')
  2142.                     UseRegion = FALSE;
  2143.  
  2144.                 break;
  2145.  
  2146.                 /* Turn character wrapping on or off. */
  2147.  
  2148.             case 7:        // DECAWM
  2149.  
  2150.                 if(Last == 'h')
  2151.                     Config -> EmulationConfig -> LineWrap = TRUE;
  2152.  
  2153.                 if(Last == 'l')
  2154.                     Config -> EmulationConfig -> LineWrap = FALSE;
  2155.  
  2156.                 break;
  2157.  
  2158.                 /* Turn auto repeat on or off. */
  2159.  
  2160.             case 8:        // DECARM
  2161.  
  2162.                 break;
  2163.  
  2164.                 /* Set 240/480 line mode. */
  2165.  
  2166.             case 9:
  2167.  
  2168.                 break;
  2169.  
  2170.                 /* Print form feed after `print screen command'. */
  2171.  
  2172.             case 18:    // DECPFF
  2173.  
  2174.                 if(Last == 'h')
  2175.                     PrintFormFeed = TRUE;
  2176.  
  2177.                 if(Last == 'l')
  2178.                     PrintFormFeed = FALSE;
  2179.  
  2180.                 break;
  2181.  
  2182.                 /* Print full screen or just region. */
  2183.  
  2184.             case 19:    // DECPEX
  2185.  
  2186.                 if(Last == 'h')
  2187.                     PrintFullScreen = TRUE;
  2188.  
  2189.                 if(Last == 'l')
  2190.                     PrintFullScreen = FALSE;
  2191.  
  2192.                 break;
  2193.  
  2194.                 /* Text cursor enable. */
  2195.  
  2196.             case 25:    // DECTCEM
  2197.  
  2198.                 TurnOn = CursorEnabled;
  2199.  
  2200.                 ClearCursor();
  2201.  
  2202.                 if(Last == 'h')
  2203.                     CursorInvisible = FALSE;
  2204.  
  2205.                 if(Last == 'l')
  2206.                     CursorInvisible = TRUE;
  2207.  
  2208.                 if(TurnOn)
  2209.                     DrawCursor();
  2210.  
  2211.                 break;
  2212.  
  2213.                 /* National/multinational character set. */
  2214.  
  2215.             case 42:    // DECNRCM
  2216.  
  2217.                 break;
  2218.         }
  2219.     }
  2220.     else
  2221.     {
  2222.         switch(Value)
  2223.         {
  2224.                 /* Keyboard action unlocked/locked. */
  2225.  
  2226.             case 2:        // KAM
  2227.  
  2228.                 break;
  2229.  
  2230.                 /* Insertion/replacement. */
  2231.  
  2232.             case 4:        // IRM
  2233.  
  2234.                 if(Last == 'h')
  2235.                     Config -> EmulationConfig -> InsertMode = TRUE;
  2236.  
  2237.                 if(Last == 'l')
  2238.                     Config -> EmulationConfig -> InsertMode = FALSE;
  2239.  
  2240.                 break;
  2241.  
  2242.                 /* Echo on/off. */
  2243.  
  2244.             case 12:    // SRM
  2245.  
  2246.                 if(Last == 'h')
  2247.                     Config -> SerialConfig -> Duplex = DUPLEX_FULL;
  2248.  
  2249.                 if(Last == 'l')
  2250.                     Config -> SerialConfig -> Duplex = DUPLEX_HALF;
  2251.  
  2252.                 break;
  2253.  
  2254.                 /* Line feed/new line. */
  2255.  
  2256.             case 20:    // LNM
  2257.  
  2258.                 if(Last == 'h')
  2259.                     Config -> EmulationConfig -> NewLineMode = TRUE;
  2260.  
  2261.                 if(Last == 'l')
  2262.                     Config -> EmulationConfig -> NewLineMode = FALSE;
  2263.  
  2264.                 break;
  2265.         }
  2266.     }
  2267. }
  2268.  
  2269.     /* NumericAppMode(STRPTR Buffer):
  2270.      *
  2271.      *    Set the numeric pad applications mode.
  2272.      */
  2273.  
  2274. VOID 
  2275. NumericAppMode(STRPTR Buffer)
  2276. {
  2277.     if(!Config -> EmulationConfig -> KeysLocked)
  2278.     {
  2279.         if(*Buffer == '=')
  2280.             Config -> EmulationConfig -> NumericMode = KEYMODE_APPLICATION;
  2281.         else
  2282.         {
  2283.             if(*Buffer == '>')
  2284.                 Config -> EmulationConfig -> NumericMode = KEYMODE_STANDARD;
  2285.         }
  2286.     }
  2287. }
  2288.  
  2289.     /* MoveCursor(STRPTR Buffer):
  2290.      *
  2291.      *    Move the cursor in some direction and stop at
  2292.      *    top/bottom/margin if necessary.
  2293.      */
  2294.  
  2295. VOID 
  2296. MoveCursor(STRPTR Buffer)
  2297. {
  2298.     WORD Value,Hit,LastCharPosition;
  2299.     BYTE InRegion = TRUE;
  2300.  
  2301.     ReadValue(Buffer,&Value);
  2302.  
  2303.     if(Value < 1)
  2304.         Value = 1;
  2305.  
  2306.     switch(LastChar(Buffer))
  2307.     {
  2308.             /* Move cursor Up value lines */
  2309.  
  2310.         case 'A':
  2311.  
  2312. ScrollUp:        Hit = 0;
  2313.  
  2314.             if(RegionSet)
  2315.             {
  2316.                 if(CursorY >= Top)
  2317.                     Hit = Top;
  2318.                 else
  2319.                     InRegion = FALSE;
  2320.             }
  2321.  
  2322.             CursorY -= Value;
  2323.  
  2324.             if(CursorY < Hit)
  2325.             {
  2326.                 Value = CursorY - Hit;
  2327.  
  2328.                 CursorY = Hit;
  2329.  
  2330.                 if(Config -> EmulationConfig -> CursorWrap && InRegion)
  2331.                     ScrollRegion(Value);
  2332.             }
  2333.  
  2334.             ConFontScaleUpdate();
  2335.  
  2336.             break;
  2337.  
  2338.             /* Move cursor Down value lines */
  2339.  
  2340.         case 'B':
  2341.  
  2342. ScrollDown:        Hit = LastLine;
  2343.  
  2344.             if(RegionSet)
  2345.             {
  2346.                 if(CursorY <= Bottom)
  2347.                     Hit = Bottom;
  2348.                 else
  2349.                     InRegion = FALSE;
  2350.             }
  2351.  
  2352.             CursorY += Value;
  2353.  
  2354.             if(CursorY > Hit)
  2355.             {
  2356.                 Value = CursorY - Hit;
  2357.  
  2358.                 CursorY = Hit;
  2359.  
  2360.                 if(Config -> EmulationConfig -> CursorWrap && InRegion)
  2361.                     ScrollRegion(Value);
  2362.             }
  2363.  
  2364.             ConFontScaleUpdate();
  2365.  
  2366.             break;
  2367.  
  2368.             /* Move cursor Right value columns */
  2369.  
  2370.         case 'C':
  2371.  
  2372.             CursorX += Value;
  2373.  
  2374.             if(CursorX > LastColumn)
  2375.             {
  2376.                 if(Config -> EmulationConfig -> CursorWrap)
  2377.                 {
  2378.                     Value     = CursorX / (LastColumn + 1);
  2379.  
  2380.                     CursorX    -= Value * (LastColumn + 1);
  2381.  
  2382.                     goto ScrollDown;
  2383.                 }
  2384.                 else
  2385.                     CursorX = LastColumn;
  2386.             }
  2387.  
  2388.             break;
  2389.  
  2390.             /* Move cursor Left value columns */
  2391.  
  2392.         case 'D':
  2393.  
  2394.             CursorX -= Value;
  2395.  
  2396.             if(CursorX < 0)
  2397.             {
  2398.                 if(Config -> EmulationConfig -> CursorWrap)
  2399.                 {
  2400.                     Value     = CursorX / (LastColumn + 1);
  2401.                     CursorX    -= Value * (LastColumn + 1);
  2402.                     Value     = -Value;
  2403.  
  2404.                     goto ScrollDown;
  2405.                 }
  2406.                 else
  2407.                     CursorX = 0;
  2408.             }
  2409.  
  2410.             break;
  2411.     }
  2412.  
  2413.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2414.         LastCharPosition = LastColumn;
  2415.     else
  2416.         LastCharPosition = ((LastColumn + 1) / 2) - 1;
  2417.  
  2418.     if(CursorX > LastCharPosition)
  2419.         CursorX = LastCharPosition;
  2420.  
  2421.     RepositionCursor();
  2422. }
  2423.  
  2424.     /* MoveColumn(STRPTR Buffer):
  2425.      *
  2426.      *    Move the cursor to a certain column.
  2427.      */
  2428.  
  2429. VOID 
  2430. MoveColumn(STRPTR Buffer)
  2431. {
  2432.     WORD Value,LastCharPosition;
  2433.  
  2434.     ReadValue(Buffer,&Value);
  2435.  
  2436.     if(Value < 1)
  2437.         Value = 1;
  2438.  
  2439.     CursorX = Value - 1;
  2440.  
  2441.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2442.         LastCharPosition = LastColumn;
  2443.     else
  2444.         LastCharPosition = ((LastColumn + 1) / 2) - 1;
  2445.  
  2446.     if(CursorX > LastColumn)
  2447.         CursorX = LastColumn;
  2448.  
  2449.     if(CursorX > LastCharPosition)
  2450.         CursorX = LastCharPosition;
  2451.  
  2452.     RepositionCursor();
  2453. }
  2454.  
  2455.     /* EraseLine(STRPTR Buffer):
  2456.      *
  2457.      *    Erase a line on the display.
  2458.      */
  2459.  
  2460. VOID 
  2461. EraseLine(STRPTR Buffer)
  2462. {
  2463.     WORD Value,Width = GetFontWidth();
  2464.  
  2465.     if(*Buffer == '?')
  2466.         Buffer++;
  2467.  
  2468.     ReadValue(Buffer,&Value);
  2469.  
  2470.     BackupRender();
  2471.  
  2472.     SetAPen(RPort,MappedPens[0][0]);
  2473.  
  2474.     switch(Value)
  2475.     {
  2476.         case 1:
  2477.  
  2478.             ScrollLineRectFill(RPort,0,MUL_Y(CursorY),((CursorX + 1) * Width) - 1,MUL_Y(CursorY + 1) - 1);
  2479.             break;
  2480.  
  2481.         case 2:
  2482.  
  2483.             ScrollLineRectFill(RPort,0,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1);
  2484.             break;
  2485.  
  2486.         default:
  2487.  
  2488.             ScrollLineRectFill(RPort,CursorX * Width,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1);
  2489.             break;
  2490.     }
  2491.  
  2492.     ScrollLineEraseLine(Value);
  2493.  
  2494.     RasterEraseLine(Value);
  2495.  
  2496.     BackupRender();
  2497. }
  2498.  
  2499.     /* EraseScreen(STRPTR Buffer):
  2500.      *
  2501.      *    Erase parts of the screen.
  2502.      */
  2503.  
  2504. VOID 
  2505. EraseScreen(STRPTR Buffer)
  2506. {
  2507.     WORD Value,Width = GetFontWidth();
  2508.  
  2509.     if(*Buffer == '?')
  2510.         Buffer++;
  2511.  
  2512.     ReadValue(Buffer,&Value);
  2513.  
  2514.     BackupRender();
  2515.  
  2516.     SetAPen(RPort,MappedPens[0][0]);
  2517.  
  2518.     switch(Value)
  2519.     {
  2520.         case 1:
  2521.  
  2522.             if(CursorY)
  2523.                 ScrollLineRectFill(RPort,0,0,LastPixel,MUL_Y(CursorY) - 1);
  2524.  
  2525.             ScrollLineRectFill(RPort,0,MUL_Y(TextFontHeight),((CursorX + 1) * Width) - 1,MUL_Y(CursorY + 1) - 1);
  2526.  
  2527.             break;
  2528.  
  2529.         case 2:
  2530.  
  2531.             ScrollLineRectFill(RPort,0,0,LastPixel,MUL_Y(LastLine + 1) - 1);
  2532.  
  2533.             if(Config -> EmulationConfig -> CLSResetsCursor)
  2534.                 CursorX = CursorY = 0;
  2535.  
  2536.             break;
  2537.  
  2538.         default:
  2539.  
  2540.             ScrollLineRectFill(RPort,CursorX * Width,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1);
  2541.  
  2542.             if(CursorY != LastLine)
  2543.                 ScrollLineRectFill(RPort,0,MUL_Y(CursorY + 1),LastPixel,MUL_Y(LastLine + 1) - 1);
  2544.  
  2545.             break;
  2546.     }
  2547.  
  2548.     ScrollLineEraseScreen(Value);
  2549.  
  2550.     RasterEraseScreen(Value);
  2551.  
  2552.     BackupRender();
  2553. }
  2554.  
  2555.     /* EraseCharacters(STRPTR Buffer):
  2556.      *
  2557.      *    Erase a number of characters.
  2558.      */
  2559.  
  2560. VOID 
  2561. EraseCharacters(STRPTR Buffer)
  2562. {
  2563.     WORD Value,Width = GetFontWidth();
  2564.  
  2565.     if(*Buffer == '?')
  2566.         Buffer++;
  2567.  
  2568.     ReadValue(Buffer,&Value);
  2569.  
  2570.     BackupRender();
  2571.  
  2572.     if(Value < 1)
  2573.         Value = 1;
  2574.  
  2575.     RasterEraseCharacters(Value);
  2576.  
  2577.     ScrollLineEraseCharacters(Value);
  2578.  
  2579.     ScrollLineRaster(RPort,Value * Width,0,CursorX * Width,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2580.  
  2581.     BackupRender();
  2582. }
  2583.  
  2584.     /* InsertCharacters(STRPTR Buffer):
  2585.      *
  2586.      *    Insert a number of characters.
  2587.      */
  2588.  
  2589. VOID 
  2590. InsertCharacters(STRPTR Buffer)
  2591. {
  2592.     WORD Value,Width = GetFontWidth();
  2593.  
  2594.     ReadValue(Buffer,&Value);
  2595.  
  2596.     BackupRender();
  2597.  
  2598.     if(Value < 1)
  2599.         Value = 1;
  2600.  
  2601.     RasterShiftChar(Value);
  2602.  
  2603.     ScrollLineShiftChar(Value);
  2604.  
  2605.     ScrollLineRaster(RPort,-Value * Width,0,CursorX * Width,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2606.  
  2607.     BackupRender();
  2608. }
  2609.  
  2610.     /* InsertLine(STRPTR Buffer):
  2611.      *
  2612.      *    Insert a number of lines and scroll the rest of the
  2613.      *    display down.
  2614.      */
  2615.  
  2616. VOID 
  2617. InsertLine(STRPTR Buffer)
  2618. {
  2619.     WORD Value,RegionBottom,RegionTop,TheTop = CursorY;
  2620.  
  2621.     ReadValue(Buffer,&Value);
  2622.  
  2623.     BackupRender();
  2624.  
  2625.     SetAPen(RPort,MappedPens[0][0]);
  2626.  
  2627.     if(Value < 1)
  2628.         Value = 1;
  2629.  
  2630.     if(RegionSet)
  2631.     {
  2632.         RegionTop    = Top;
  2633.         RegionBottom    = Bottom + 1;
  2634.     }
  2635.     else
  2636.     {
  2637.         RegionTop    = 0;
  2638.         RegionBottom    = LastLine + 1;
  2639.     }
  2640.  
  2641.     if(TheTop < RegionTop)
  2642.         TheTop = RegionTop;
  2643.  
  2644.     RasterInsertLine(Value,TheTop);
  2645.  
  2646.     ScrollLineRaster(RPort,0,-MUL_Y(Value),0,MUL_Y(TheTop),LastPixel,MUL_Y(RegionBottom) - 1,FALSE);
  2647.  
  2648.     BackupRender();
  2649. }
  2650.  
  2651.     /* ClearLine(STRPTR Buffer):
  2652.      *
  2653.      *    Clear a number of lines and scroll up the ones below it.
  2654.      */
  2655.  
  2656. VOID 
  2657. ClearLine(STRPTR Buffer)
  2658. {
  2659.     WORD Value,RegionBottom,RegionTop,TheTop = CursorY;
  2660.  
  2661.     ReadValue(Buffer,&Value);
  2662.  
  2663.     BackupRender();
  2664.  
  2665.     SetAPen(RPort,MappedPens[0][0]);
  2666.  
  2667.     if(Value < 1)
  2668.         Value = 1;
  2669.  
  2670.     if(RegionSet)
  2671.     {
  2672.         RegionTop    = Top;
  2673.         RegionBottom    = Bottom + 1;
  2674.     }
  2675.     else
  2676.     {
  2677.         RegionTop    = 0;
  2678.         RegionBottom    = LastLine + 1;
  2679.     }
  2680.  
  2681.     if(TheTop < RegionTop)
  2682.         TheTop = RegionTop;
  2683.  
  2684.     RasterClearLine(Value,TheTop);
  2685.  
  2686.     ScrollLineRaster(RPort,0,MUL_Y(Value),0,MUL_Y(TheTop),LastPixel,MUL_Y(RegionBottom) - 1,FALSE);
  2687.  
  2688.     BackupRender();
  2689. }
  2690.  
  2691.     /* SetTabs(STRPTR Buffer):
  2692.      *
  2693.      *    Set the current tab stops.
  2694.      */
  2695.  
  2696. VOID 
  2697. SetTabs(STRPTR Buffer)
  2698. {
  2699.     WORD Value;
  2700.  
  2701.     ReadValue(Buffer,&Value);
  2702.  
  2703.     if(Value < 1)
  2704.         Value = 0;
  2705.  
  2706.     switch(Value)
  2707.     {
  2708.         case 0:
  2709.  
  2710.             if(CursorX < TabStopMax)
  2711.                 TabStops[CursorX] = FALSE;
  2712.  
  2713.             break;
  2714.  
  2715.         case 3:
  2716.  
  2717.             memset(TabStops,FALSE,TabStopMax);
  2718.  
  2719.             break;
  2720.  
  2721.         default:
  2722.  
  2723.             break;
  2724.     }
  2725. }
  2726.  
  2727.     /* SetAbsolutePosition(STRPTR Buffer):
  2728.      *
  2729.      *    Move the cursor to a given location on the display,
  2730.      *    this routine ignores the current scroll region
  2731.      *    settings.
  2732.      */
  2733.  
  2734. VOID 
  2735. SetAbsolutePosition(STRPTR Buffer)
  2736. {
  2737.     WORD Value;
  2738.  
  2739.     Buffer = ReadValue(Buffer,&Value);
  2740.  
  2741.     CursorY = 0;
  2742.     CursorX = 0;
  2743.  
  2744.     if(Value != -1)
  2745.     {
  2746.             /* Our raster origin is 0/0 instead of 1/1. */
  2747.  
  2748.         if(Value)
  2749.             Value--;
  2750.  
  2751.         CursorY = Value;
  2752.  
  2753.         if(Buffer)
  2754.         {
  2755.             ReadValue(Buffer,&Value);
  2756.  
  2757.             if(Value > 0)
  2758.                 CursorX = Value - 1;
  2759.             else
  2760.                 CursorX = 0;
  2761.         }
  2762.  
  2763.             /* Truncate illegal positions. */
  2764.  
  2765.         if(CursorX > LastColumn)
  2766.             CursorX = LastColumn;
  2767.  
  2768.         if(CursorY > LastLine)
  2769.             CursorY = LastLine;
  2770.     }
  2771.  
  2772.     ConFontScaleUpdate();
  2773.  
  2774.     RepositionCursor();
  2775. }
  2776.  
  2777.     /* SetTopPosition(STRPTR Buffer):
  2778.      *
  2779.      *    Move the cursor to a given location on the display,
  2780.      *    this routine respects the current scroll region
  2781.      *    settings.
  2782.      */
  2783.  
  2784. VOID 
  2785. SetTopPosition(STRPTR Buffer)
  2786. {
  2787.     WORD Value;
  2788.  
  2789.     Buffer = ReadValue(Buffer,&Value);
  2790.  
  2791.     if(UseRegion && RegionSet)
  2792.         CursorY = Top;
  2793.     else
  2794.         CursorY = 0;
  2795.  
  2796.     CursorX = 0;
  2797.  
  2798.     if(Value != -1)
  2799.     {
  2800.             /* Our raster origin is 0/0 instead of 1/1. */
  2801.  
  2802.         if(Value)
  2803.             Value--;
  2804.  
  2805.         if(UseRegion && RegionSet)
  2806.             CursorY = Top + Value;
  2807.         else
  2808.             CursorY = Value;
  2809.  
  2810.         if(Buffer)
  2811.         {
  2812.             ReadValue(Buffer,&Value);
  2813.  
  2814.             if(Value > 0)
  2815.                 CursorX = Value - 1;
  2816.             else
  2817.                 CursorX = 0;
  2818.         }
  2819.  
  2820.             /* Truncate illegal positions. */
  2821.  
  2822.         if(CursorX > LastColumn)
  2823.             CursorX = LastColumn;
  2824.  
  2825.         if(CursorY > LastLine)
  2826.             CursorY = LastLine;
  2827.     }
  2828.  
  2829.     ConFontScaleUpdate();
  2830.  
  2831.     RepositionCursor();
  2832. }
  2833.  
  2834.     /* SetAttributes(STRPTR Buffer):
  2835.      *
  2836.      *    Set the current display rendering attributes.
  2837.      */
  2838.  
  2839. VOID 
  2840. SetAttributes(STRPTR Buffer)
  2841. {
  2842.     LONG TextFlags = FS_NORMAL;
  2843.     WORD Value;
  2844.  
  2845.     do
  2846.     {
  2847.         Buffer = ReadValue(Buffer,&Value);
  2848.  
  2849.         if(Value == -1)
  2850.             Value = 0;
  2851.  
  2852.         switch(Value)
  2853.         {
  2854.             case 0:
  2855.  
  2856.                 FgPen = GetPenIndex(SafeTextPen);
  2857.                 BgPen = 0;
  2858.  
  2859.                 Attributes = 0;
  2860.  
  2861.                 break;
  2862.  
  2863.             case 1:
  2864.  
  2865.                 Attributes |= ATTR_HIGHLIGHT;
  2866.  
  2867.                 break;
  2868.  
  2869.             case 4:
  2870.  
  2871.                 Attributes |= ATTR_UNDERLINE;
  2872.  
  2873.                 break;
  2874.  
  2875.             case 5:
  2876.  
  2877.                 Attributes |= ATTR_BLINK;
  2878.  
  2879.                 break;
  2880.  
  2881.             case 7:
  2882.  
  2883.                 if(!(Attributes & ATTR_INVERSE))
  2884.                 {
  2885.                     WORD Help;
  2886.  
  2887.                     Help    = FgPen;
  2888.                     FgPen    = BgPen;
  2889.                     BgPen    = Help;
  2890.                 }
  2891.  
  2892.                 Attributes |= ATTR_INVERSE;
  2893.  
  2894.                 break;
  2895.  
  2896.             case 22:
  2897.  
  2898.                 Attributes &= ~ATTR_HIGHLIGHT;
  2899.  
  2900.                 break;
  2901.  
  2902.             case 24:
  2903.  
  2904.                 Attributes &= ~ATTR_UNDERLINE;
  2905.  
  2906.                 break;
  2907.  
  2908.             case 25:
  2909.  
  2910.                 Attributes &= ~ATTR_BLINK;
  2911.  
  2912.                 break;
  2913.  
  2914.             case 27:
  2915.  
  2916.                 if(Attributes & ATTR_INVERSE)
  2917.                 {
  2918.                     WORD Help;
  2919.  
  2920.                     Help    = FgPen;
  2921.                     FgPen    = BgPen;
  2922.                     BgPen    = Help;
  2923.                 }
  2924.  
  2925.                 Attributes &= ~ATTR_INVERSE;
  2926.  
  2927.                 break;
  2928.  
  2929.             default:
  2930.  
  2931.                 if(Value >= 30)
  2932.                 {
  2933.                     if(Value <= 37)
  2934.                     {
  2935.                         if(Attributes & ATTR_INVERSE)
  2936.                             BgPen = Value - 30;
  2937.                         else
  2938.                             FgPen = Value - 30;
  2939.                     }
  2940.                     else
  2941.                     {
  2942.                         if(Value >= 40 && Value <= 47)
  2943.                         {
  2944.                             if(Attributes & ATTR_INVERSE)
  2945.                                 FgPen = Value - 40;
  2946.                             else
  2947.                                 BgPen = Value - 40;
  2948.                         }
  2949.                     }
  2950.                 }
  2951.  
  2952.                 break;
  2953.         }
  2954.     }
  2955.     while(Buffer);
  2956.  
  2957.         /* Make sure that the text rendered will be
  2958.          * visible by wrapping the colour if
  2959.          * necessary.
  2960.          */
  2961.  
  2962.     if(FgPen > DepthMask && !(FgPen & DepthMask))
  2963.         FgPen = GetPenIndex(SafeTextPen);
  2964.  
  2965.     if(BgPen > DepthMask && !(BgPen & DepthMask))
  2966.         BgPen = GetPenIndex(SafeTextPen);
  2967.  
  2968.     if(Attributes & ATTR_UNDERLINE)
  2969.         TextFlags |= FSF_UNDERLINED;
  2970.  
  2971.     if(Attributes & ATTR_HIGHLIGHT)
  2972.     {
  2973.         if(Config -> ScreenConfig -> ColourMode == COLOUR_SIXTEEN)
  2974.         {
  2975.             if(Attributes & ATTR_INVERSE)
  2976.                 BgPen |= 8;
  2977.             else
  2978.                 FgPen |= 8;
  2979.         }
  2980.         else
  2981.             TextFlags |= FSF_BOLD;
  2982.     }
  2983.  
  2984.     if(Attributes & ATTR_BLINK)
  2985.     {
  2986.         if(Config -> TerminalConfig -> EmulationMode == EMULATION_ANSIVT100)
  2987.         {
  2988.             switch(Config -> ScreenConfig -> ColourMode)
  2989.             {
  2990.                 case COLOUR_AMIGA:
  2991.  
  2992.                     if(Attributes & ATTR_INVERSE)
  2993.                         BgPen = 3;
  2994.                     else
  2995.                         FgPen = 3;
  2996.  
  2997.                     break;
  2998.  
  2999.                 case COLOUR_EIGHT:
  3000.  
  3001.                     if(Attributes & ATTR_INVERSE)
  3002.                         BgPen |= 8;
  3003.                     else
  3004.                         FgPen |= 8;
  3005.  
  3006.                     break;
  3007.  
  3008.                 case COLOUR_SIXTEEN:
  3009.  
  3010.                     if(Screen)
  3011.                     {
  3012.                         if(Screen -> RastPort . BitMap -> Depth > 4)
  3013.                         {
  3014.                             if(Attributes & ATTR_INVERSE)
  3015.                                 BgPen |= 16;
  3016.                             else
  3017.                                 FgPen |= 16;
  3018.                         }
  3019.                     }
  3020.  
  3021.                     break;
  3022.  
  3023.                 case COLOUR_MONO:
  3024.  
  3025.                     if(Attributes & ATTR_INVERSE)
  3026.                         BgPen = GetPenIndex(SafeTextPen);
  3027.                     else
  3028.                         FgPen = GetPenIndex(SafeTextPen);
  3029.  
  3030.                     break;
  3031.             }
  3032.         }
  3033.     }
  3034.  
  3035.     if(TextFlags != StyleType)
  3036.     {
  3037.         SetSoftStyle(RPort,TextFlags,0xFF);
  3038.  
  3039.         StyleType = TextFlags;
  3040.     }
  3041.  
  3042.     if(Config -> ScreenConfig -> ColourMode == COLOUR_MONO)
  3043.     {
  3044.         if(ColourValue(MappedPens[0][FgPen]) < ColourValue(MappedPens[0][BgPen]))
  3045.         {
  3046.             if(Attributes & ATTR_INVERSE)
  3047.             {
  3048.                 FgPen = GetPenIndex(SafeTextPen);
  3049.                 BgPen = 0;
  3050.             }
  3051.             else
  3052.             {
  3053.                 FgPen = 0;
  3054.                 BgPen = GetPenIndex(SafeTextPen);
  3055.             }
  3056.         }
  3057.         else
  3058.         {
  3059.             if(Attributes & ATTR_INVERSE)
  3060.             {
  3061.                 FgPen = 0;
  3062.                 BgPen = GetPenIndex(SafeTextPen);
  3063.             }
  3064.             else
  3065.             {
  3066.                 FgPen = GetPenIndex(SafeTextPen);
  3067.                 BgPen = 0;
  3068.             }
  3069.         }
  3070.     }
  3071.  
  3072.     if(MappedPens[0][FgPen] != ReadAPen(RPort))
  3073.         SetAPen(RPort,MappedPens[0][FgPen]);
  3074.  
  3075.     if(MappedPens[0][BgPen] != ReadBPen(RPort))
  3076.         SetBPen(RPort,MappedPens[0][BgPen]);
  3077.  
  3078.     RepositionCursor();
  3079. }
  3080.  
  3081.     /* SetRegion(STRPTR Buffer):
  3082.      *
  3083.      *    Set the current scroll region top and bottom.
  3084.      */
  3085.  
  3086. VOID 
  3087. SetRegion(STRPTR Buffer)
  3088. {
  3089.     WORD NewTop,Value,NewBottom = LastLine;
  3090.  
  3091.     Buffer = ReadValue(Buffer,&Value);
  3092.  
  3093.     if(!Value)
  3094.         Value = 1;
  3095.  
  3096.     if(Value > 0)
  3097.     {
  3098.         if(Buffer)
  3099.         {
  3100.             NewTop = Value - 1;
  3101.  
  3102.             ReadValue(Buffer,&Value);
  3103.  
  3104.             if(Value > 0)
  3105.                 NewBottom = Value - 1;
  3106.  
  3107.             if(NewBottom > LastLine)
  3108.                 NewBottom = LastLine;
  3109.  
  3110.             if(NewTop > LastLine)
  3111.                 NewTop = LastLine;
  3112.         }
  3113.         else
  3114.         {
  3115.             NewTop        = 0;
  3116.             NewBottom    = LastLine;
  3117.         }
  3118.     }
  3119.     else
  3120.     {
  3121.         NewTop        = 0;
  3122.         NewBottom    = LastLine;
  3123.     }
  3124.  
  3125.     if(NewTop < NewBottom)
  3126.     {
  3127.         if(NewTop != 0 || NewBottom != LastLine)
  3128.         {
  3129.             Top    = NewTop;
  3130.             Bottom    = NewBottom;
  3131.  
  3132.             RegionSet = TRUE;
  3133.         }
  3134.         else
  3135.             UseRegion = RegionSet = FALSE;
  3136.  
  3137.         ResetCursor();
  3138.     }
  3139.     else
  3140.         RegionSet = FALSE;
  3141. }
  3142.  
  3143.     /* ResetCursor():
  3144.      *
  3145.      *    Reset cursor to top of screen.
  3146.      */
  3147.  
  3148. VOID
  3149. ResetCursor()
  3150. {
  3151.     CursorX    = 0;
  3152.  
  3153.     if(UseRegion && RegionSet)
  3154.         CursorY = Top;
  3155.     else
  3156.         CursorY    = 0;
  3157.  
  3158.     ConFontScaleUpdate();
  3159.  
  3160.     RepositionCursor();
  3161. }
  3162.