home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term23_2.lha / Source_Code / termSource / termEmulation.c < prev    next >
C/C++ Source or Header  |  1992-08-18  |  42KB  |  2,462 lines

  1. /*
  2. **    $Id: termEmulation.c,v 1.3 92/08/15 20:13:55 olsen Sta Locker: olsen $
  3. **    $Revision: 1.3 $
  4. **    $Date: 92/08/15 20:13:55 $
  5. **
  6. **    Terminal emulation (parsing and processing) routines
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* This structure describes an ANSI control sequence. */
  15.  
  16. struct ControlCode
  17. {
  18.     UBYTE     FirstChar;
  19.     UBYTE    *Match;
  20.     UBYTE     LastChar;
  21.  
  22.     BYTE     ExactSize;
  23.     UBYTE *    (* __regargs Func)(UBYTE *Buffer);
  24. };
  25.  
  26. #define NUM_CODES (sizeof(ANSICode) / sizeof(struct ControlCode))
  27.  
  28.     /* How many characters we will keep in the scan buffer. */
  29.  
  30. #define MAX_SCAN_SIZE    256
  31.  
  32.     /* Flag indicating whether the cursor has already been
  33.      * erased or not.
  34.      */
  35.  
  36. STATIC BYTE CursorEnabled = FALSE;
  37.  
  38.     /* Global string buffer and backup style. */
  39.  
  40. STATIC UBYTE GlobalBuffer[40],StyleType = FS_NORMAL;
  41.  
  42.     /* Cursor backup data. */
  43.  
  44. STATIC struct CursorData CursorBackup;
  45.  
  46.     /* A couple of internally referenced variables. */
  47.  
  48. STATIC BYTE    CharsInBuffer    = 0,
  49.         ScanStep    = 0;
  50. STATIC UBYTE    SaveBuffer[MAX_SCAN_SIZE + 1];
  51.  
  52.     /* Character access tables. */
  53.  
  54. STATIC UBYTE Table0[256] =
  55. {
  56.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  57.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  58.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  59.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  60.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  61.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  62.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  63.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  64.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  65.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  66.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  67.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  68.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  69.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  70.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  71.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  72. };
  73.  
  74. STATIC UBYTE Table1[256] =
  75. {
  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.     1,1,1,1,1,1,1,1,1,1,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.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  91.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  92. };
  93.  
  94. STATIC UBYTE Table2[256] =
  95. {
  96.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  98.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  99.     1,1,1,1,1,1,1,1,1,1,0,1,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.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  111.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  112. };
  113.  
  114. STATIC UBYTE Table3[256] =
  115. {
  116.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  117.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  118.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  119.     1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,
  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.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  131.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  132. };
  133.  
  134. STATIC UBYTE Table4[256] =
  135. {
  136.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  137.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  138.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  139.     1,1,1,1,1,1,1,1,1,1,0,0,0,1,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.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  151.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  152. };
  153.  
  154.     /* This follows the control code information. */
  155.  
  156. struct ControlCode ANSICode[] =
  157. {
  158.     /* Single Character Sequences. */
  159.  
  160.     'D',    Table0,     0 ,    1,    (APTR)CursorScrollDown,
  161.     'M',    Table0,     0 ,    1,    (APTR)CursorScrollUp,
  162.     'E',    Table0,     0 ,    1,    (APTR)NextLine,
  163.     '7',    Table0,     0 ,    1,    (APTR)SaveCursor,
  164.     '8',    Table0,     0 ,    1,    (APTR)LoadCursor,
  165.     '=',    Table0,     0 ,    1,    (APTR)NumericAppMode,
  166.     '>',    Table0,     0 ,    1,    (APTR)NumericAppMode,
  167.     'N',    Table0,     0 ,    1,    (APTR)Ignore,
  168.     'O',    Table0,     0 ,    1,    (APTR)Ignore,
  169.     'H',    Table0,     0 ,    1,    (APTR)SetTab,
  170.     'Z',    Table0,     0 ,    1,    (APTR)RequestTerminal,
  171.     'c',    Table0,     0 ,    1,    (APTR)Reset,
  172.     '<',    Table0,     0 ,    1,    (APTR)Ignore,
  173.     '~',    Table0,     0 ,    1,    (APTR)Ignore,
  174.     'n',    Table0,     0 ,    1,    (APTR)Ignore,
  175.     '}',    Table0,     0 ,    1,    (APTR)Ignore,
  176.     'o',    Table0,     0 ,    1,    (APTR)Ignore,
  177.     '|',    Table0,     0 ,    1,    (APTR)Ignore,
  178.  
  179.     /* Double Character Sequences. */
  180.  
  181.     '[',    Table0,    's',    2,    (APTR)SaveCursor,
  182.     '[',    Table0,    'u',    2,    (APTR)LoadCursor,
  183.     '(',    Table0,    'A',    2,    (APTR)FontStuff,
  184.     '(',    Table0,    'B',    2,    (APTR)FontStuff,
  185.     '(',    Table0,    '0',    2,    (APTR)FontStuff,
  186.     ')',    Table0,    'A',    2,    (APTR)FontStuff,
  187.     ')',    Table0,    'B',    2,    (APTR)FontStuff,
  188.     ')',    Table0,    '0',    2,    (APTR)FontStuff,
  189.     '#',    Table0,    '3',    2,    (APTR)ScaleFont,
  190.     '#',    Table0,    '4',    2,    (APTR)ScaleFont,
  191.     '#',    Table0,    '5',    2,    (APTR)ScaleFont,
  192.     '#',    Table0,    '6',    2,    (APTR)ScaleFont,
  193.     '#',    Table0,    '8',    2,    (APTR)AlignmentTest,
  194.     ' ',    Table0,    'F',    2,    (APTR)Ignore,
  195.     ' ',    Table0,    'G',    2,    (APTR)Ignore,
  196.  
  197.     /* Multiple Character Sequence. */
  198.  
  199.     '[',    Table3,    'i',    0,    (APTR)PrinterController,
  200.  
  201.     '[',    Table3,    'n',    0,    (APTR)RequestInformation,
  202.     '[',    Table3,    'c',    0,    (APTR)RequestTerminal,
  203.     '[',    Table3,    'h',    0,    (APTR)SetSomething,
  204.     '[',    Table3,    'l',    0,    (APTR)SetSomething,
  205.  
  206.     '[',    Table4,    'h',    0,    (APTR)Ignore,
  207.  
  208.     '[',    Table1,    'A',    0,    (APTR)MoveCursor,
  209.     '[',    Table1,    'B',    0,    (APTR)MoveCursor,
  210.     '[',    Table1,    'C',    0,    (APTR)MoveCursor,
  211.     '[',    Table1,    'D',    0,    (APTR)MoveCursor,
  212.     '[',    Table1,    'K',    0,    (APTR)EraseLine,
  213.     '[',    Table1,    'J',    0,    (APTR)EraseScreen,
  214.     '[',    Table1,    'P',    0,    (APTR)EraseCharacters,
  215.     '[',    Table1,    '@',    0,    (APTR)InsertCharacters,
  216.     '[',    Table1,    'L',    0,    (APTR)InsertLine,
  217.     '[',    Table1,    'M',    0,    (APTR)ClearLine,
  218.     '[',    Table1,    'g',    0,    (APTR)SetTabs,
  219.     '[',    Table1,    'q',    0,    (APTR)Ignore,
  220.  
  221.     '[',    Table2,    'H',    0,    (APTR)SetAbsolutePosition,
  222.     '[',    Table2,    'f',    0,    (APTR)SetAbsolutePosition,
  223.     '[',    Table2,    'm',    0,    (APTR)SetAttributes,
  224.     '[',    Table2,    'y',    0,    (APTR)Ignore,
  225.     '[',    Table2,    'r',    0,    (APTR)SetRegion,
  226.  
  227.     '[',    Table1,    'S',    0,    (APTR)ScrollUp,
  228.     '[',    Table1,    'T',    0,    (APTR)ScrollDown
  229. };
  230.  
  231.     /* DoCancel():
  232.      *
  233.      *    Cancel any currently scanned sequence.
  234.      */
  235.  
  236. BYTE
  237. DoCancel()
  238. {
  239.     InSequence    = FALSE;
  240.     CharsInBuffer    = ScanStep = 0;
  241.  
  242.     return(FALSE);
  243. }
  244.  
  245.     /* CSIFake():
  246.      *
  247.      *    This routine was added to support 8-bit control
  248.      *    sequences introduced by a CSI character.
  249.      */
  250.  
  251. VOID
  252. CSIFake()
  253. {
  254.         /* Reset scanner */
  255.  
  256.     DoCancel();
  257.  
  258.         /* Perform as if ESC [ had been transmitted. */
  259.  
  260.     InSequence = ParseCode('[');
  261. }
  262.  
  263.     /* ParseCode(UBYTE c):
  264.      *
  265.      *    Input:    A character to be passed through the ANSI code
  266.      *        parser.
  267.      *
  268.      *    Output:    FALSE if input characters did form a valid ANSI
  269.      *        control sequence or if input characters did not
  270.      *        form an ANSI control sequence at all.
  271.      *
  272.      *        TRUE if input characters did possibly introduce
  273.      *        a valid ANSI control sequence.
  274.      */
  275.  
  276. BYTE __regargs
  277. ParseCode(UBYTE c)
  278. {
  279.     register WORD i;
  280.  
  281.         /* ScanStep = 0:    This is the first character
  282.          *            to introduce a control sequence.
  283.          */
  284.  
  285.     if(!ScanStep)
  286.     {
  287.             /* Scan all available codes and try to find
  288.              * a match.
  289.              */
  290.  
  291.         for(i = 0 ; i < NUM_CODES ; i++)
  292.         {
  293.                 /* This character may introduce a
  294.                  * control sequence.
  295.                  */
  296.  
  297.             if(ANSICode[i] . FirstChar == c)
  298.             {
  299.                     /* If this is a single
  300.                      * character control sequence
  301.                      * call the approriate function
  302.                      * and exit immediately.
  303.                      */
  304.  
  305.                 if(ANSICode[i] . ExactSize == 1)
  306.                 {
  307.                     if(Config . Emulation != EMULATION_ATOMIC)
  308.                     {
  309.                         UBYTE *SomeString;
  310.  
  311.                         SaveBuffer[CharsInBuffer++] = c;
  312.                         SaveBuffer[CharsInBuffer  ] = 0;
  313.  
  314.                         if(SomeString = (*ANSICode[i] . Func)(SaveBuffer))
  315.                             SerWrite(SomeString,strlen(SomeString));
  316.                     }
  317.  
  318.                     CharsInBuffer = ScanStep = 0;
  319.  
  320.                     return(FALSE);
  321.                 }
  322.                 else
  323.                 {
  324.                         /* The length of this control
  325.                          * sequence is greater than
  326.                          * a single character. Save
  327.                          * the input character and
  328.                          * return.
  329.                          */
  330.  
  331.                     ScanStep = i;
  332.  
  333.                     SaveBuffer[CharsInBuffer++] = c;
  334.  
  335.                     return(TRUE);
  336.                 }
  337.             }
  338.         }
  339.     }
  340.     else
  341.     {
  342.         if(CharsInBuffer < MAX_SCAN_SIZE)
  343.         {
  344.                 /* Scan the remaining codes for a match. */
  345.  
  346.             for(i = ScanStep ; i < NUM_CODES ; i++)
  347.             {
  348.                     /* This sequence begins with the
  349.                      * same character the parser was
  350.                      * initialized with, so let's take
  351.                      * a look at it.
  352.                      */
  353.  
  354.                 if(ANSICode[i] . FirstChar == SaveBuffer[0])
  355.                 {
  356.                         /* This character is supposed to
  357.                          * terminate the sequence, so exit.
  358.                          */
  359.  
  360.                     if(ANSICode[i] . LastChar == c)
  361.                     {
  362.                         if(Config . Emulation != EMULATION_ATOMIC)
  363.                         {
  364.                             UBYTE *SomeString;
  365.  
  366.                             SaveBuffer[CharsInBuffer++] = c;
  367.                             SaveBuffer[CharsInBuffer  ] = 0;
  368.  
  369.                             if(SomeString = (*ANSICode[i] . Func)(SaveBuffer))
  370.                                 SerWrite(SomeString,strlen(SomeString));
  371.                         }
  372.  
  373.                         CharsInBuffer = ScanStep = 0;
  374.  
  375.                         return(FALSE);
  376.                     }
  377.                     else
  378.                     {
  379.                             /* If this character is part of
  380.                              * a legal sequence store it
  381.                              * and return.
  382.                              */
  383.  
  384.                         if(ANSICode[i] . Match[c])
  385.                         {
  386.                             ScanStep = i;
  387.  
  388.                             SaveBuffer[CharsInBuffer++] = c;
  389.  
  390.                             return(TRUE);
  391.                         }
  392.                     }
  393.                 }
  394.             }
  395.         }
  396.     }
  397.  
  398.         /* Return failure. */
  399.  
  400.     CharsInBuffer = ScanStep = 0;
  401.  
  402.     return(FALSE);
  403. }
  404.  
  405.     /* GetFontWidth():
  406.      *
  407.      *    Get the font width of the current line.
  408.      */
  409.  
  410. STATIC WORD
  411. GetFontWidth()
  412. {
  413.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  414.     {
  415.         if(Config . FontScale == SCALE_HALF)
  416.             return(TextFontWidth / 2);
  417.         else
  418.             return(TextFontWidth);
  419.     }
  420.     else
  421.     {
  422.         if(Config . FontScale == SCALE_HALF)
  423.             return(TextFontWidth);
  424.         else
  425.             return(TextFontWidth * 2);
  426.     }
  427. }
  428.  
  429.     /* ColourValue(UWORD Colour):
  430.      *
  431.      *    Calculate the value of a given colour (brightness).
  432.      */
  433.  
  434. STATIC WORD __regargs
  435. ColourValue(UWORD Colour)
  436. {
  437.     BYTE    Red,Green,Blue;
  438.     WORD    Sum;
  439.  
  440.     Red    = Colour >> 8;
  441.     Green    = (Colour >> 4) & 0xF;
  442.     Blue    = Colour & 0xF;
  443.  
  444.     Sum = (Red + Green + Blue) / 3;
  445.  
  446.     return(Sum);
  447. }
  448.  
  449.     /* ScrollRegion(WORD Direction):
  450.      *
  451.      *    Scroll the current scroll region up or down.
  452.      */
  453.  
  454. STATIC VOID __regargs
  455. ScrollRegion(WORD Direction)
  456. {
  457.     WORD RegionTop,RegionBottom,RegionLines;
  458.     LONG Dir,MinY,MaxY;
  459.  
  460.     if(Direction < 0)
  461.         Dir = -Direction;
  462.     else
  463.         Dir = Direction;
  464.  
  465.     if(RegionSet)
  466.     {
  467.         MinY         = Top * TextFontHeight;
  468.         MaxY        = (Bottom + 1) * TextFontHeight - 1;
  469.  
  470.         RegionTop    = Top;
  471.         RegionBottom    = Bottom + 1;
  472.         RegionLines    = Bottom - Top + 1;
  473.     }
  474.     else
  475.     {
  476.         MinY        = 0;
  477.         MaxY         = (LastLine + 1) * TextFontHeight - 1;
  478.  
  479.         RegionTop    = 0;
  480.         RegionBottom    = LastLine + 1;
  481.         RegionLines    = LastLine + 1;
  482.     }
  483.  
  484.     BackupRender();
  485.  
  486.     SetBPen(RPort,0);
  487.  
  488.     RasterScrollRegion(Direction,RegionTop,RegionBottom,RegionLines);
  489.  
  490.     if(Dir > RegionLines)
  491.     {
  492.         /* All that is needed is to delete the lines
  493.          * note: not too brilliant for smooth scroll
  494.          */
  495.  
  496.         ScrollLineRectFill(RPort,0,MinY,LastPixel,MaxY);
  497.     }
  498.     else
  499.     {
  500.         if(Config . JumpScroll || (TextFontHeight & 1))
  501.             ScrollLineRaster(RPort,0,Direction * TextFontHeight,0,MinY,LastPixel,MaxY);
  502.         else
  503.         {
  504.             WORD Lines = Dir * (TextFontHeight / 2);
  505.  
  506.             if(Direction < 0)
  507.             {
  508.                 while(Lines--)
  509.                 {
  510.                     WaitTOF();
  511.  
  512.                     ScrollLineRaster(RPort,0,-2,0,MinY,LastPixel,MaxY);
  513.                 }
  514.             }
  515.             else
  516.             {
  517.                 while(Lines--)
  518.                 {
  519.                     WaitTOF();
  520.  
  521.                     ScrollLineRaster(RPort,0,2,0,MinY,LastPixel,MaxY);
  522.                 }
  523.             }
  524.         }
  525.     }
  526.  
  527.     BackupRender();
  528. }
  529.  
  530.     /* LastChar(UBYTE *Buffer):
  531.      *
  532.      *    Return the last character in a string.
  533.      */
  534.  
  535. STATIC UBYTE __regargs
  536. LastChar(UBYTE *Buffer)
  537. {
  538.     WORD Offset = 0;
  539.  
  540.     while(Buffer[Offset])
  541.         Offset++;
  542.  
  543.     return(Buffer[Offset - 1]);
  544. }
  545.  
  546.     /* ReadValue(UBYTE *Buffer,BYTE *Value):
  547.      *
  548.      *    Parse a buffer for numbers and return a pointer
  549.      *    to the next buffer element to contain additional
  550.      *    information.
  551.      */
  552.  
  553. STATIC UBYTE * __regargs
  554. ReadValue(UBYTE *Buffer,WORD *Value)
  555. {
  556.     while((*Buffer < '0' || *Buffer > '9') && (*Buffer != ';') && *Buffer)
  557.         Buffer++;
  558.  
  559.     if(*Buffer)
  560.     {
  561.         *Value = 0;
  562.  
  563.         while(*Buffer >= '0' && *Buffer <= '9')
  564.             *Value = (*Value * 10) + (*Buffer++ - '0');
  565.     }
  566.     else
  567.         *Value = -1;
  568.  
  569.     if(*Buffer == ';' || *Buffer == ' ')
  570.         return(&Buffer[1]);
  571.     else
  572.         return(NULL);
  573. }
  574.  
  575.     /* ClipBlitCursor(UBYTE DoClip,UBYTE DoMove):
  576.      *
  577.      *    Change the appearance of the cursor.
  578.      */
  579.  
  580. VOID __regargs
  581. ClipBlitCursor(UBYTE DoClip,UBYTE DoMove)
  582. {
  583.     if(DoClip || DoMove)
  584.     {
  585.         STATIC WORD LastCursorX = -1,LastCursorY = -1;
  586.         STATIC LONG DestX,DestY,XSize,X,Y,Column;
  587.  
  588.         if(CursorY != LastCursorY || CursorX != LastCursorX)
  589.         {
  590.             if(CursorY != LastCursorY)
  591.             {
  592.                 if(CursorY > LastLine)
  593.                     Y = LastLine;
  594.                 else
  595.                 {
  596.                     if(CursorY < 0)
  597.                         Y = 0;
  598.                     else
  599.                         Y = CursorY;
  600.                 }
  601.  
  602.                 if(RasterAttr[Y] == SCALE_ATTR_NORMAL)
  603.                     Column = LastColumn;
  604.                 else
  605.                     Column = ((LastColumn + 1) / 2) - 1;
  606.  
  607.                 DestY = Y * TextFontHeight;
  608.  
  609.                 LastCursorY = CursorY;
  610.             }
  611.  
  612.             LastCursorX = CursorX;
  613.  
  614.             if(CursorX > Column)
  615.                 X = Column;
  616.             else
  617.             {
  618.                 if(CursorX < 0)
  619.                     X = 0;
  620.                 else
  621.                     X = CursorX;
  622.             }
  623.  
  624.             if(Config . FontScale == SCALE_NORMAL)
  625.             {
  626.                 if(RasterAttr[Y] == SCALE_ATTR_NORMAL)
  627.                 {
  628.                     DestX = X * TextFontWidth;
  629.                     XSize = TextFontWidth;
  630.                 }
  631.                 else
  632.                 {
  633.                     DestX = X * TextFontWidth * 2;
  634.                     XSize = TextFontWidth * 2;
  635.  
  636.                     if(X > ((LastColumn + 1) / 2) - 1)
  637.                         X = ((LastColumn + 1) / 2) - 1;
  638.                 }
  639.             }
  640.             else
  641.             {
  642.                 if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  643.                 {
  644.                     DestX = X * TextFontWidth / 2;
  645.                     XSize = TextFontWidth / 2;
  646.                 }
  647.                 else
  648.                 {
  649.                     DestX = X * TextFontWidth;
  650.                     XSize = TextFontWidth;
  651.  
  652.                     if(X > ((LastColumn + 1) / 2) - 1)
  653.                         X = ((LastColumn + 1) / 2) - 1;
  654.                 }
  655.             }
  656.         }
  657.  
  658.         if(DoMove)
  659.             Move(RPort,DestX,DestY + TextFontBase);
  660.  
  661.         if(DoClip)
  662.         {
  663.             BYTE Depth = RPort -> BitMap -> Depth;
  664.  
  665.             if(Depth > 1 && !(Config . DisableBlinking & TERMINAL_FASTER))
  666.             {
  667.                 STATIC    UBYTE    DepthMasks[5] = { 0,1,3,7,15 };
  668.                     UBYTE    Mask = RPort -> Mask;
  669.  
  670.                 SetWrMsk(RPort,DepthMasks[Depth]);
  671.  
  672.                 ClipBlit(RPort,0,0,RPort,DestX,DestY,XSize,TextFontHeight,0x50);
  673.  
  674.                 SetWrMsk(RPort,Mask);
  675.             }
  676.             else
  677.                 ClipBlit(RPort,0,0,RPort,DestX,DestY,XSize,TextFontHeight,0x50);
  678.         }
  679.     }
  680. }
  681.  
  682.     /* ClearCursor():
  683.      *
  684.      *    Clear the cursor image.
  685.      */
  686.  
  687. VOID
  688. ClearCursor()
  689. {
  690.     if(CursorEnabled)
  691.     {
  692.         ClipBlitCursor(TRUE,FALSE);
  693.  
  694.         CursorEnabled = FALSE;
  695.     }
  696. }
  697.  
  698.     /* DrawCursor():
  699.      *
  700.      *    Explicitely (re-)draw the cursor image.
  701.      */
  702.  
  703. VOID
  704. DrawCursor()
  705. {
  706.     if(!CursorEnabled)
  707.     {
  708.         ClipBlitCursor(TRUE,FALSE);
  709.  
  710.         CursorEnabled = TRUE;
  711.     }
  712. }
  713.  
  714.     /* SetCursor():
  715.      *
  716.      *    Move the cursor to a given location.
  717.      */
  718.  
  719. VOID
  720. SetCursor()
  721. {
  722.     ClipBlitCursor(!CursorEnabled,TRUE);
  723.  
  724.     CursorEnabled = TRUE;
  725. }
  726.  
  727.     /* BackupRender():
  728.      *
  729.      *    Save current draw modes, pen and position or restore
  730.      *    the data.
  731.      */
  732.  
  733. VOID
  734. BackupRender()
  735. {
  736.     STATIC BYTE    Called = FALSE;
  737.     STATIC UBYTE    DrMd,FgPen,BgPen;
  738.     STATIC UWORD    CpX,CpY;
  739.     STATIC UBYTE    Style;
  740.  
  741.     if(!Called)
  742.     {
  743.         DrMd    = RPort -> DrawMode;
  744.         FgPen    = RPort -> FgPen;
  745.         BgPen    = RPort -> BgPen;
  746.  
  747.         CpX    = RPort -> cp_x;
  748.         CpY    = RPort -> cp_y;
  749.  
  750.         Style    = StyleType;
  751.  
  752.         Called    = TRUE;
  753.     }
  754.     else
  755.     {
  756.         if(RPort -> DrawMode != DrMd)
  757.             SetDrMd(RPort,DrMd);
  758.  
  759.         if(RPort -> FgPen != FgPen)
  760.             SetAPen(RPort,FgPen);
  761.  
  762.         if(RPort -> BgPen != BgPen)
  763.             SetBPen(RPort,BgPen);
  764.  
  765.         if(RPort -> cp_x != CpX || RPort -> cp_y != CpY)
  766.             Move(RPort,CpX,CpY);
  767.  
  768.         if(Style != StyleType)
  769.         {
  770.             SetSoftStyle(RPort,Style,0xFF);
  771.  
  772.             StyleType = Style;
  773.         }
  774.  
  775.         Called = FALSE;
  776.     }
  777. }
  778.  
  779.     /* ShiftChar(LONG Size):
  780.      *
  781.      *    Simulate character insertion at the current cursor
  782.      *    position by shifting the whole line Size times eight pixels
  783.      *    to the right.
  784.      */
  785.  
  786. VOID __regargs
  787. ShiftChar(LONG Size)
  788. {
  789.     LONG DeltaX,MinX,MinY;
  790.  
  791.     MinY = CursorY * TextFontHeight;
  792.  
  793.     if(Config . FontScale == SCALE_NORMAL)
  794.     {
  795.         if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  796.         {
  797.             DeltaX    = Size * TextFontWidth;
  798.             MinX    = CursorX * TextFontWidth;
  799.         }
  800.         else
  801.         {
  802.             DeltaX    = Size * TextFontWidth * 2;
  803.             MinX    = CursorX * TextFontWidth * 2;
  804.         }
  805.     }
  806.     else
  807.     {
  808.         if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  809.         {
  810.             DeltaX    = Size * TextFontWidth / 2;
  811.             MinX    = CursorX * TextFontWidth / 2;
  812.         }
  813.         else
  814.         {
  815.             DeltaX    = Size * TextFontWidth;
  816.             MinX    = CursorX * TextFontWidth;
  817.         }
  818.     }
  819.  
  820.     if(MinX < Window -> Width)
  821.     {
  822.         BackupRender();
  823.  
  824.         SetBPen(RPort,0);
  825.  
  826.         ScrollLineRaster(RPort,-DeltaX,0,MinX,MinY,LastPixel,MinY + TextFontHeight - 1);
  827.  
  828.         BackupRender();
  829.     }
  830. }
  831.  
  832.     /* Ignore():
  833.      *
  834.      *    Do nothing, return immediately.
  835.      */
  836.  
  837. UBYTE *
  838. Ignore()
  839. {
  840.     return(NULL);
  841. }
  842.  
  843.     /* ScrollDown(UBYTE *Buffer):
  844.      *
  845.      *    Scroll the current region down.
  846.      */
  847.  
  848. UBYTE * __regargs
  849. ScrollDown(UBYTE *Buffer)
  850. {
  851.     WORD Value;
  852.  
  853.     ReadValue(Buffer,&Value);
  854.  
  855.     if(Value < 1)
  856.         Value = 1;
  857.  
  858.     ClearCursor();
  859.  
  860.     ScrollRegion(-Value);
  861.  
  862.     DrawCursor();
  863.  
  864.     return(NULL);
  865. }
  866.  
  867.     /* ScrollUp(UBYTE *Buffer):
  868.      *
  869.      *    Scroll the current region up.
  870.      */
  871.  
  872. UBYTE * __regargs
  873. ScrollUp(UBYTE *Buffer)
  874. {
  875.     WORD Value;
  876.  
  877.     ReadValue(Buffer,&Value);
  878.  
  879.     if(Value < 1)
  880.         Value = 1;
  881.  
  882.     ClearCursor();
  883.  
  884.     ScrollRegion(Value);
  885.  
  886.     DrawCursor();
  887.  
  888.     return(NULL);
  889. }
  890.  
  891.     /* CursorScrollDown():
  892.      *
  893.      *    Move cursor down and scroll region if necessary.
  894.      */
  895.  
  896. UBYTE *
  897. CursorScrollDown()
  898. {
  899.     ClearCursor();
  900.  
  901.     DownLine();
  902.  
  903.     SetCursor();
  904.  
  905.     return(NULL);
  906. }
  907.  
  908. VOID
  909. DownLine()
  910. {
  911.     UBYTE InRegion = TRUE;
  912.     WORD  Hit      = LastLine;
  913.  
  914.     if(RegionSet)
  915.     {
  916.         if(CursorY <= Bottom)
  917.             Hit = Bottom;
  918.         else
  919.             InRegion = FALSE;
  920.     }
  921.  
  922.     if(CursorY == Hit)
  923.     {
  924.         if(InRegion)
  925.             ScrollRegion(1);
  926.     }
  927.     else
  928.     {
  929.         CursorY++;
  930.  
  931.         if(CursorY > LastLine)
  932.             CursorY = LastLine;
  933.     }
  934. }
  935.  
  936.     /* CursorScrollUp():
  937.      *
  938.      *    Move cursor up and scroll region if necessary.
  939.      */
  940.  
  941. UBYTE *
  942. CursorScrollUp()
  943. {
  944.     BYTE InRegion    = TRUE;
  945.     WORD Hit    = 0;
  946.  
  947.     ClearCursor();
  948.  
  949.     if(RegionSet)
  950.     {
  951.         if(CursorY >= Top)
  952.             Hit = Top;
  953.         else
  954.             InRegion = FALSE;
  955.     }
  956.  
  957.     if(CursorY == Hit)
  958.     {
  959.         if(InRegion)
  960.             ScrollRegion(-1);
  961.     }
  962.     else
  963.     {
  964.         if(--CursorY < 0)
  965.             CursorY = 0;
  966.     }
  967.  
  968.     SetCursor();
  969.  
  970.     return(NULL);
  971. }
  972.  
  973.     /* NextLine():
  974.      *
  975.      *    Do something like CR+LF.
  976.      */
  977.  
  978. UBYTE *
  979. NextLine()
  980. {
  981.     ClearCursor();
  982.  
  983.     CursorX = 0;
  984.  
  985.     DownLine();
  986.  
  987.     SetCursor();
  988.  
  989.     return(NULL);
  990. }
  991.  
  992.     /* SaveCursor():
  993.      *
  994.      *    Save cursor position and rendering attributes.
  995.      */
  996.  
  997. UBYTE *
  998. SaveCursor()
  999. {
  1000.     CursorBackup . Charset        = Charset;
  1001.     CursorBackup . Attributes    = Attributes;
  1002.     CursorBackup . CursorX        = CursorX;
  1003.     CursorBackup . CursorY        = CursorY;
  1004.     CursorBackup . Style        = StyleType;
  1005.     CursorBackup . FgPen        = RPort -> FgPen;
  1006.     CursorBackup . BgPen        = RPort -> BgPen;
  1007.     CursorBackup . CurrentFont    = CurrentFont;
  1008.  
  1009.     return(NULL);
  1010. }
  1011.  
  1012.     /* FontStuff(UBYTE *Buffer):
  1013.      *
  1014.      *    Set the drawing font (standard characters/line).
  1015.      */
  1016.  
  1017. UBYTE * __regargs
  1018. FontStuff(UBYTE *Buffer)
  1019. {
  1020.     BYTE Changed = FALSE;
  1021.  
  1022.     if(Buffer[0] == '(')
  1023.     {
  1024.         switch(LastChar(Buffer))
  1025.         {
  1026.             case 'A':
  1027.             case 'B':    if(CharMode[0] != TABLE_ASCII && !Charset)
  1028.                         Changed = TRUE;
  1029.  
  1030.                     CharMode[0] = TABLE_ASCII;
  1031.  
  1032.                     break;
  1033.  
  1034.             case '0':    if(CharMode[0] != TABLE_GFX && !Charset)
  1035.                         Changed = TRUE;
  1036.  
  1037.                     CharMode[0] = TABLE_GFX;
  1038.  
  1039.                     break;
  1040.         }
  1041.     }
  1042.  
  1043.     if(Buffer[0] == ')')
  1044.     {
  1045.         switch(LastChar(Buffer))
  1046.         {
  1047.             case 'A':
  1048.             case 'B':    if(CharMode[1] != TABLE_ASCII && Charset == 1)
  1049.                         Changed = TRUE;
  1050.  
  1051.                     CharMode[1] = TABLE_ASCII;
  1052.  
  1053.                     break;
  1054.  
  1055.             case '0':    if(CharMode[1] != TABLE_GFX && Charset == 1)
  1056.                         Changed = TRUE;
  1057.  
  1058.                     CharMode[1] = TABLE_GFX;
  1059.  
  1060.                     break;
  1061.         }
  1062.     }
  1063.  
  1064.     if(Changed)
  1065.     {
  1066.         BackupRender();
  1067.  
  1068.         if(Charset)
  1069.             DoShiftIn();
  1070.         else
  1071.             DoShiftOut();
  1072.  
  1073.         BackupRender();
  1074.     }
  1075.  
  1076.     return(NULL);
  1077. }
  1078.  
  1079.     /* LoadCursor():
  1080.      *
  1081.      *    Load cursor position and rendering attributes.
  1082.      */
  1083.  
  1084. UBYTE *
  1085. LoadCursor()
  1086. {
  1087.     ClearCursor();
  1088.  
  1089.     Charset        = CursorBackup . Charset;
  1090.  
  1091.     CharMode[0]    = CursorBackup . CharMode[0];
  1092.     CharMode[1]    = CursorBackup . CharMode[1];
  1093.  
  1094.     if(CurrentFont != CursorBackup . CurrentFont)
  1095.     {
  1096.         CurrentFont = CursorBackup . CurrentFont;
  1097.  
  1098.         SetFont(RPort,CurrentFont);
  1099.     }
  1100.  
  1101.     if(StyleType != CursorBackup . Style)
  1102.     {
  1103.         SetSoftStyle(RPort,CursorBackup . Style,0xFF);
  1104.  
  1105.         StyleType = CursorBackup . Style;
  1106.     }
  1107.  
  1108.     if(RPort -> FgPen != CursorBackup . FgPen)
  1109.         SetAPen(RPort,CursorBackup . FgPen);
  1110.  
  1111.     if(RPort -> BgPen != CursorBackup . BgPen)
  1112.         SetBPen(RPort,CursorBackup . BgPen);
  1113.  
  1114.     Attributes    = CursorBackup . Attributes;
  1115.     CursorX        = CursorBackup . CursorX;
  1116.     CursorY        = CursorBackup . CursorY;
  1117.  
  1118.     SetCursor();
  1119.  
  1120.     return(NULL);
  1121. }
  1122.  
  1123. UBYTE * __regargs
  1124. ScaleFont(UBYTE *Buffer)
  1125. {
  1126.     WORD NewScale,Scale;
  1127.  
  1128.     Scale = RasterAttr[CursorY];
  1129.  
  1130.     ClearCursor();
  1131.  
  1132.     NewScale = Scale;
  1133.  
  1134.     switch(LastChar(Buffer))
  1135.     {
  1136.         case '3':
  1137.  
  1138.             NewScale = SCALE_ATTR_TOP2X;
  1139.  
  1140.             break;
  1141.  
  1142.         case '4':
  1143.  
  1144.             NewScale = SCALE_ATTR_BOT2X;
  1145.  
  1146.             break;
  1147.  
  1148.         case '5':
  1149.  
  1150.             NewScale = SCALE_NORMAL;
  1151.  
  1152.             break;
  1153.  
  1154.         case '6':
  1155.  
  1156.             NewScale = SCALE_ATTR_2X;
  1157.  
  1158.             break;
  1159.     }
  1160.  
  1161.     if(Scale != NewScale)
  1162.     {
  1163.         UBYTE    *RasterPtr    = &Raster[CursorY * RasterWidth];
  1164.         WORD     RightMargin    = LastColumn + 1,
  1165.              CursorXSave    = CursorX;
  1166.  
  1167.         if(NewScale != SCALE_ATTR_NORMAL)
  1168.             RightMargin /= 2;
  1169.  
  1170.         RasterAttr[CursorY] = NewScale;
  1171.  
  1172.         if(((Config . FontScale == SCALE_NORMAL) && (NewScale == SCALE_ATTR_NORMAL)) || ((Config . FontScale == SCALE_HALF) && (NewScale == SCALE_ATTR_2X)))
  1173.         {
  1174.             Move(RPort,0,CursorY * TextFontHeight + TextFontBase);
  1175.             Text(RPort,RasterPtr,RightMargin);
  1176.         }
  1177.         else
  1178.         {
  1179.             CursorX = 0;
  1180.  
  1181.             PrintScaled(RasterPtr,RightMargin,NewScale);
  1182.         }
  1183.  
  1184.         if(CursorXSave >= RightMargin)
  1185.             CursorX = RightMargin - 1;
  1186.         else
  1187.             CursorX = CursorXSave;
  1188.     }
  1189.  
  1190.     SetCursor();
  1191.  
  1192.     return(NULL);
  1193. }
  1194.  
  1195. UBYTE *
  1196. AlignmentTest()
  1197. {
  1198.     STRPTR Buffer;
  1199.  
  1200.     if(Buffer = AllocVec(LastColumn + 1,MEMF_ANY))
  1201.     {
  1202.         WORD i;
  1203.  
  1204.         memset(Buffer,'E',LastColumn + 1);
  1205.  
  1206.         EraseScreen("2");
  1207.  
  1208.         ClearCursor();
  1209.  
  1210.         if(Config . FontScale == SCALE_HALF)
  1211.         {
  1212.             for(i = 0 ; i <= LastLine ; i++)
  1213.             {
  1214.                 CursorX = 0;
  1215.                 CursorY = i;
  1216.  
  1217.                 RasterAttr[i] = SCALE_ATTR_NORMAL;
  1218.  
  1219.                 RasterPutString(Buffer,LastColumn + 1);
  1220.                 ScrollLinePutString(LastColumn + 1);
  1221.  
  1222.                 Move(RPort,0,(i * TextFontHeight) + TextFontBase);
  1223.                 PrintScaled(Buffer,LastColumn + 1,SCALE_ATTR_NORMAL);
  1224.             }
  1225.         }
  1226.         else
  1227.         {
  1228.             for(i = 0 ; i <= LastLine ; i++)
  1229.             {
  1230.                 CursorX = 0;
  1231.                 CursorY = i;
  1232.  
  1233.                 RasterAttr[i] = SCALE_ATTR_NORMAL;
  1234.  
  1235.                 RasterPutString(Buffer,LastColumn + 1);
  1236.                 ScrollLinePutString(LastColumn + 1);
  1237.  
  1238.                 Move(RPort,0,(i * TextFontHeight) + TextFontBase);
  1239.                 Text(RPort,Buffer,LastColumn + 1);
  1240.             }
  1241.         }
  1242.  
  1243.         CursorX = CursorY = 0;
  1244.  
  1245.         SetCursor();
  1246.  
  1247.         FreeVec(Buffer);
  1248.     }
  1249.  
  1250.     return(NULL);
  1251. }
  1252.  
  1253.     /* SetTab():
  1254.      *
  1255.      *    Set a tabulator stop at the current position.
  1256.      */
  1257.  
  1258. UBYTE *
  1259. SetTab()
  1260. {
  1261.     if(CursorX < 1024)
  1262.         TabStops[CursorX] = TRUE;
  1263.  
  1264.     return(NULL);
  1265. }
  1266.  
  1267.     /* RequestTerminal(UBYTE *Buffer):
  1268.      *
  1269.      *    Return the current terminal position.
  1270.      */
  1271.  
  1272. UBYTE * __regargs
  1273. RequestTerminal(UBYTE *Buffer)
  1274. {
  1275.     switch(Buffer[0])
  1276.     {
  1277.                 /* Make ourselves known as a VT200
  1278.                  * terminal.
  1279.                  */
  1280.  
  1281.         case '[':    if(Buffer[1] != '>')
  1282.                     return("\033[?62;1;2;6;7;8;9c");
  1283.                 else
  1284.                     return("\033[>1;10;0c");
  1285.  
  1286.                 /* This is an old status request type,
  1287.                  * we will return the standard `I am a
  1288.                  * VT101' sequence.
  1289.                  */
  1290.  
  1291.         case 'Z':    return("\033[?1;0c");
  1292.  
  1293.         default:    return(NULL);
  1294.     }
  1295. }
  1296.  
  1297.     /* Reset():
  1298.      *
  1299.      *    Reset terminal to initial state.
  1300.      */
  1301.  
  1302. UBYTE *
  1303. Reset()
  1304. {
  1305.     WORD i;
  1306.  
  1307.     ClearCursor();
  1308.  
  1309.     memset(&TabStops[0],FALSE,1024);
  1310.  
  1311.     for(i = 8 ; i < 1024 ; i += 8)
  1312.         TabStops[i] = TRUE;
  1313.  
  1314.     CharMode[0] = TABLE_ASCII;
  1315.     CharMode[1] = TABLE_GFX;
  1316.  
  1317.     Charset = 0;
  1318.  
  1319.     SetAPen(RPort,0);
  1320.  
  1321.     SetWrMsk(RPort,0xFF);
  1322.  
  1323.     RectFill(RPort,0,0,Window -> Width - 1,Window -> Height - 1);
  1324.  
  1325.     ScrollLineEraseScreen(2);
  1326.  
  1327.     RasterEraseScreen(2);
  1328.  
  1329.     switch(Config . ColourMode)
  1330.     {
  1331.         case COLOUR_EIGHT:    FgPen = 7;
  1332.                     break;
  1333.  
  1334.         case COLOUR_SIXTEEN:    FgPen = 15;
  1335.                     break;
  1336.  
  1337.         case COLOUR_AMIGA:
  1338.         default:        FgPen = 1;
  1339.                     break;
  1340.     }
  1341.  
  1342.     BgPen = 0;
  1343.  
  1344.     if(RPort -> FgPen != FgPen)
  1345.         SetAPen(RPort,FgPen);
  1346.  
  1347.     if(RPort -> BgPen != BgPen)
  1348.         SetBPen(RPort,BgPen);
  1349.  
  1350.     if(StyleType != FS_NORMAL)
  1351.     {
  1352.         SetSoftStyle(RPort,FS_NORMAL,0xFF);
  1353.  
  1354.         StyleType = FS_NORMAL;
  1355.     }
  1356.  
  1357.     CurrentFont = TextFont;
  1358.  
  1359.     SetFont(RPort,CurrentFont);
  1360.  
  1361.     if(Config . EightyColumns)
  1362.     {
  1363.         LastColumn    = 79;
  1364.         LastPixel    = 80 * 8 - 1;
  1365.     }
  1366.     else
  1367.     {
  1368.         LastColumn    = Window -> Width / TextFontWidth - 1;
  1369.         LastPixel    = (LastColumn + 1) * TextFontWidth - 1;
  1370.     }
  1371.  
  1372.     UseRegion        = FALSE;
  1373.     RegionSet        = FALSE;
  1374.  
  1375.     Config . AutoWrap    = TRUE;
  1376.     Config . NewLine    = FALSE;
  1377.     Config . InsertChar    = FALSE;
  1378.     Config . CursorApp    = FALSE;
  1379.     Config . NumApp        = FALSE;
  1380.     Config . FontScale    = SCALE_NORMAL;
  1381.     Config . JumpScroll    = TRUE;
  1382.  
  1383.     Attributes    = 0;
  1384.     Top        = 0;
  1385.     Bottom        = LastLine;
  1386.     CursorX        = 0;
  1387.     CursorY        = 0;
  1388.  
  1389.     CursorBackup . Charset        = Charset;
  1390.     CursorBackup . Attributes    = Attributes;
  1391.     CursorBackup . CursorX        = CursorX;
  1392.     CursorBackup . CursorY        = CursorY;
  1393.     CursorBackup . Style        = StyleType;
  1394.     CursorBackup . FgPen        = FgPen;
  1395.     CursorBackup . BgPen        = BgPen;
  1396.     CursorBackup . CurrentFont    = CurrentFont;
  1397.  
  1398.     SetCursor();
  1399.  
  1400.     return(NULL);
  1401. }
  1402.  
  1403.     /* PrinterController(UBYTE *Buffer):
  1404.      *
  1405.      *    Controls various screen dump and capture functions.
  1406.      */
  1407.  
  1408. UBYTE * __regargs
  1409. PrinterController(UBYTE *Buffer)
  1410. {
  1411.     if(Config . PrinterEnabled)
  1412.     {
  1413.         switch(Buffer[1])
  1414.         {
  1415.             case 'i':
  1416.             case '0':    if(RegionSet)
  1417.                         PrintRegion(Top,Bottom + 1);
  1418.                     else
  1419.                         PrintRegion(0,LastLine + 1);
  1420.  
  1421.                     break;
  1422.  
  1423.             case '5':    OpenPrinterCapture(TRUE);
  1424.                     break;
  1425.  
  1426.             case '4':    ClosePrinterCapture(FALSE);
  1427.                     break;
  1428.         }
  1429.     }
  1430.  
  1431.     return(NULL);
  1432. }
  1433.  
  1434.     /* RequestInformation(UBYTE *Buffer):
  1435.      *
  1436.      *    Request miscellaneous information (state & cursor position).
  1437.      */
  1438.  
  1439. UBYTE * __regargs
  1440. RequestInformation(UBYTE *Buffer)
  1441. {
  1442.     WORD Value;
  1443.  
  1444.     ReadValue(Buffer,&Value);
  1445.  
  1446.     switch(Value)
  1447.     {
  1448.                 /* Terminal status report, return code
  1449.                  * for `no malfunction'.
  1450.                  */
  1451.  
  1452.         case 5:        return("\033[0n");
  1453.  
  1454.                 /* The origin is placed at 0/0 and the first
  1455.                  * cursor position is 1/1. We'll have to add
  1456.                  * 1 to our internal positions since our
  1457.                  * universe has been shifted one field to the
  1458.                  * left top corner.
  1459.                  */
  1460.  
  1461.         case 6:        SPrintf(GlobalBuffer,"\033[%ld;%ldR",CursorY + 1,CursorX + 1);
  1462.                 return(GlobalBuffer);
  1463.  
  1464.                 /* A VT200 command: request printer status.
  1465.                  * We will return `the printer is ready'.
  1466.                  */
  1467.  
  1468.         case 15:    if(Config . PrinterEnabled)
  1469.                     return("\033[?10n");
  1470.                 else
  1471.                     return("\033[?11n");
  1472.  
  1473.                 /* VT200 command: request user defined
  1474.                  * key status. We will return `user
  1475.                  * defined keys are locked'.
  1476.                  */
  1477.  
  1478.         case 25:    return("\033[?21n");
  1479.  
  1480.                 /* Another VT200 command: request
  1481.                  * keyboard language. We will return
  1482.                  * `keyboard language unknown' - does
  1483.                  * anybody know when locale.library will
  1484.                  * be released?
  1485.                  */
  1486.  
  1487.         case 26:    return("\033[?27;0n");
  1488.  
  1489.         default:    return(NULL);
  1490.     }
  1491. }
  1492.  
  1493.     /* SetSomething(UBYTE *Buffer):
  1494.      *
  1495.      *    Set a terminal option.
  1496.      */
  1497.  
  1498. UBYTE * __regargs
  1499. SetSomething(UBYTE *Buffer)
  1500. {
  1501.     switch(Buffer[1])
  1502.     {
  1503.         case '?':
  1504.  
  1505.             switch(Buffer[2])
  1506.             {
  1507.                     /* Set cursor keys applications mode. */
  1508.  
  1509.                 case '1':    if(Buffer[3] == 'h')
  1510.                             Config . CursorApp = TRUE;
  1511.                         else
  1512.                             Config . CursorApp = FALSE;
  1513.  
  1514.                         return(NULL);
  1515.  
  1516.                     /* Set line length (132 or 80). */
  1517.  
  1518.                 case '3':    ClearCursor();
  1519.  
  1520.                         if(Buffer[3] == 'h')
  1521.                         {
  1522.                             if(Config . FontScale != SCALE_HALF)
  1523.                             {
  1524.                                 Config . FontScale = SCALE_HALF;
  1525.  
  1526.                                 if(Config . EightyColumns)
  1527.                                 {
  1528.                                     LastColumn    = 131;
  1529.                                     LastPixel    = 80 * 8 - 1;
  1530.                                 }
  1531.                                 else
  1532.                                 {
  1533.                                     LastColumn    = Window -> Width / (TextFontWidth / 2) - 1;
  1534.                                     LastPixel    = (LastColumn + 1) * (TextFontWidth / 2) - 1;
  1535.                                 }
  1536.                             }
  1537.                         }
  1538.                         else
  1539.                         {
  1540.                             if(Config . FontScale != SCALE_NORMAL)
  1541.                             {
  1542.                                 Config . FontScale = SCALE_NORMAL;
  1543.  
  1544.                                 if(Config . EightyColumns)
  1545.                                 {
  1546.                                     LastColumn    = 79;
  1547.                                     LastPixel    = 80 * 8 - 1;
  1548.                                 }
  1549.                                 else
  1550.                                 {
  1551.                                     LastColumn    = Window -> Width / TextFontWidth - 1;
  1552.                                     LastPixel    = (LastColumn + 1) * TextFontWidth - 1;
  1553.                                 }
  1554.                             }
  1555.                         }
  1556.  
  1557.                         CursorX = CursorY = 0;
  1558.  
  1559.                         SetCursor();
  1560.  
  1561.                         EraseScreen("2");
  1562.  
  1563.                         return(NULL);
  1564.  
  1565.                     /* Set scroll mode (jump or smooth). */
  1566.  
  1567.                 case '4':    if(Buffer[3] == 'h')
  1568.                             Config . JumpScroll = FALSE;
  1569.                         else
  1570.                             Config . JumpScroll = TRUE;
  1571.  
  1572.                         break;
  1573.  
  1574.                     /* Turn region on or off. */
  1575.  
  1576.                 case '6':    if(Buffer[3] == 'h')
  1577.                             UseRegion = TRUE;
  1578.                         else
  1579.                             UseRegion = FALSE;
  1580.  
  1581.                         ResetCursor();
  1582.  
  1583.                         return(NULL);
  1584.  
  1585.                     /* Turn character wrapping on or off. */
  1586.  
  1587.                 case '7':    if(Buffer[3] == 'h')
  1588.                             Config . AutoWrap = TRUE;
  1589.                         else
  1590.                             Config . AutoWrap = FALSE;
  1591.  
  1592.                         return(NULL);
  1593.  
  1594.                     /* Set interlaced mode. */
  1595.  
  1596.                 case '9':    if(Buffer[3] == 'h')
  1597.                         {
  1598.                             if(!(Config . DisplayMode & LACE))
  1599.                             {
  1600.                                 CopyMem(&Config,&PrivateConfig,sizeof(struct Configuration));
  1601.  
  1602.                                 Config . DisplayMode |= LACE;
  1603.  
  1604.                                 ResetDisplay = TRUE;
  1605.                             }
  1606.                         }
  1607.                         else
  1608.                         {
  1609.                             if(Config . DisplayMode & LACE)
  1610.                             {
  1611.                                 CopyMem(&Config,&PrivateConfig,sizeof(struct Configuration));
  1612.  
  1613.                                 Config . DisplayMode &= ~LACE;
  1614.  
  1615.                                 ResetDisplay = TRUE;
  1616.                             }
  1617.                         }
  1618.  
  1619.                         return(NULL);
  1620.  
  1621.                 default:    return(NULL);
  1622.             }
  1623.  
  1624.             break;
  1625.  
  1626.         case '2':
  1627.  
  1628.                 /* Set newline mode. */
  1629.  
  1630.             if(Buffer[2] == '0')
  1631.             {
  1632.                 if(Buffer[3] == 'h')
  1633.                     Config . NewLine = TRUE;
  1634.                 else
  1635.                     Config . NewLine = FALSE;
  1636.             }
  1637.  
  1638.             break;
  1639.  
  1640.         case '4':
  1641.  
  1642.                 /* Set insert mode. */
  1643.  
  1644.             if(Buffer[2] == 'h')
  1645.                 Config . InsertChar = TRUE;
  1646.             else
  1647.                 Config . InsertChar = FALSE;
  1648.  
  1649.             break;
  1650.  
  1651.         case '1':
  1652.  
  1653.                 /* Print region or screen. */
  1654.  
  1655.             if(Buffer[2] == '9')
  1656.             {
  1657.                 if(Buffer[3] == 'l')
  1658.                 {
  1659.                     if(RegionSet)
  1660.                         PrintRegion(Top,Bottom + 1);
  1661.                     else
  1662.                         PrintRegion(0,LastLine + 1);
  1663.                 }
  1664.  
  1665.                 if(Buffer[3] == 'h')
  1666.                     PrintRegion(0,LastLine + 1);
  1667.             }
  1668.  
  1669.             break;
  1670.     }
  1671.  
  1672.     return(NULL);
  1673. }
  1674.  
  1675.     /* NumericAppMode(UBYTE *Buffer):
  1676.      *
  1677.      *    Set the numeric pad applications mode.
  1678.      */
  1679.  
  1680. UBYTE * __regargs
  1681. NumericAppMode(UBYTE *Buffer)
  1682. {
  1683.     if(*Buffer == '=')
  1684.         Config . NumApp = TRUE;
  1685.     else
  1686.     {
  1687.         if(*Buffer == '>')
  1688.             Config . NumApp = FALSE;
  1689.     }
  1690.  
  1691.     return(NULL);
  1692. }
  1693.  
  1694.     /* MoveCursor(UBYTE *Buffer):
  1695.      *
  1696.      *    Move the cursor in some direction and stop at
  1697.      *    top/bottom/margin if necessary.
  1698.      */
  1699.  
  1700. UBYTE * __regargs
  1701. MoveCursor(UBYTE *Buffer)
  1702. {
  1703.     WORD Value,Hit,LastCharPosition;
  1704.     BYTE InRegion = TRUE;
  1705.  
  1706.     ReadValue(Buffer,&Value);
  1707.  
  1708.     if(Value < 1)
  1709.         Value = 1;
  1710.  
  1711.     ClearCursor();
  1712.  
  1713.     switch(LastChar(Buffer))
  1714.     {
  1715.             /* Move cursor Up value lines */
  1716.  
  1717.         case 'A':
  1718.  
  1719. ScrollUp:            Hit = 0;
  1720.  
  1721.                 if(RegionSet)
  1722.                 {
  1723.                     if(CursorY >= Top)
  1724.                         Hit = Top;
  1725.                     else
  1726.                         InRegion = FALSE;
  1727.                 }
  1728.  
  1729.                 CursorY -= Value;
  1730.  
  1731.                 if(CursorY < Hit)
  1732.                 {
  1733.                     Value = CursorY - Hit;
  1734.  
  1735.                     CursorY = Hit;
  1736.  
  1737.                     if(Config . CursorWrap && InRegion)
  1738.                         ScrollRegion(Value);
  1739.                 }
  1740.  
  1741.                 break;
  1742.  
  1743.             /* Move cursor Down value lines */
  1744.  
  1745.         case 'B':
  1746.  
  1747. ScrollDown:            Hit = LastLine;
  1748.  
  1749.                 if(RegionSet)
  1750.                 {
  1751.                     if(CursorY <= Bottom)
  1752.                         Hit = Bottom;
  1753.                     else
  1754.                         InRegion = FALSE;
  1755.                 }
  1756.  
  1757.                 CursorY += Value;
  1758.  
  1759.                 if(CursorY > Hit)
  1760.                 {
  1761.                     Value = CursorY - Hit;
  1762.  
  1763.                     CursorY = Hit;
  1764.  
  1765.                     if(Config . CursorWrap && InRegion)
  1766.                         ScrollRegion(Value);
  1767.                 }
  1768.  
  1769.                 break;
  1770.  
  1771.             /* Move cursor Right value columns */
  1772.  
  1773.         case 'C':    CursorX += Value;
  1774.  
  1775.                 if(CursorX > LastColumn)
  1776.                 {
  1777.                     if(Config . CursorWrap)
  1778.                     {
  1779.                         Value     = CursorX / (LastColumn + 1);
  1780.  
  1781.                         CursorX    -= Value * (LastColumn + 1);
  1782.  
  1783.                         goto ScrollDown;
  1784.                     }
  1785.                     else
  1786.                         CursorX = LastColumn;
  1787.                 }
  1788.  
  1789.                 break;
  1790.  
  1791.             /* Move cursor Left value columns */
  1792.  
  1793.         case 'D':    CursorX -= Value;
  1794.  
  1795.                 if(CursorX < 0)
  1796.                 {
  1797.                     if(Config . CursorWrap)
  1798.                     {
  1799.                         Value     = CursorX / (LastColumn + 1);
  1800.                         CursorX    -= Value * (LastColumn + 1);
  1801.                         Value     = -Value;
  1802.  
  1803.                         goto ScrollDown;
  1804.                     }
  1805.                     else
  1806.                         CursorX = 0;
  1807.                 }
  1808.  
  1809.                 break;
  1810.  
  1811.         default:    break;
  1812.     }
  1813.  
  1814.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  1815.         LastCharPosition = LastColumn;
  1816.     else
  1817.         LastCharPosition = ((LastColumn + 1) / 2) - 1;
  1818.  
  1819.     if(CursorX > LastCharPosition)
  1820.         CursorX = LastCharPosition;
  1821.  
  1822.     SetCursor();
  1823.  
  1824.     return(NULL);
  1825. }
  1826.  
  1827.     /* EraseLine(UBYTE *Buffer):
  1828.      *
  1829.      *    Erase a line on the display.
  1830.      */
  1831.  
  1832. UBYTE * __regargs
  1833. EraseLine(UBYTE *Buffer)
  1834. {
  1835.     WORD Value,Width = GetFontWidth();
  1836.  
  1837.     ReadValue(Buffer,&Value);
  1838.  
  1839.     BackupRender();
  1840.  
  1841.     SetAPen(RPort,0);
  1842.  
  1843.     ClearCursor();
  1844.  
  1845.     switch(Value)
  1846.     {
  1847.         case 1:    ScrollLineRectFill(RPort,0,CursorY * TextFontHeight,((CursorX + 1) * Width) - 1,(CursorY + 1) * TextFontHeight - 1);
  1848.             break;
  1849.  
  1850.         case 2:    ScrollLineRectFill(RPort,0,CursorY * TextFontHeight,LastPixel,(CursorY + 1) * TextFontHeight - 1);
  1851.             break;
  1852.  
  1853.         default:ScrollLineRectFill(RPort,CursorX * Width,CursorY * TextFontHeight,LastPixel,(CursorY + 1) * TextFontHeight - 1);
  1854.             break;
  1855.     }
  1856.  
  1857.     ScrollLineEraseLine(Value);
  1858.  
  1859.     DrawCursor();
  1860.  
  1861.     RasterEraseLine(Value);
  1862.  
  1863.     BackupRender();
  1864.  
  1865.     return(NULL);
  1866. }
  1867.  
  1868.     /* EraseScreen(UBYTE *Buffer):
  1869.      *
  1870.      *    Erase parts of the screen.
  1871.      */
  1872.  
  1873. UBYTE * __regargs
  1874. EraseScreen(UBYTE *Buffer)
  1875. {
  1876.     WORD Value,Width = GetFontWidth();
  1877.  
  1878.     ClearCursor();
  1879.  
  1880.     ReadValue(Buffer,&Value);
  1881.  
  1882.     BackupRender();
  1883.  
  1884.     SetAPen(RPort,0);
  1885.  
  1886.     switch(Value)
  1887.     {
  1888.         case 1:    if(CursorY)
  1889.                 ScrollLineRectFill(RPort,0,0,LastPixel,(CursorY * TextFontHeight) - 1);
  1890.  
  1891.             ScrollLineRectFill(RPort,0,CursorY * TextFontHeight,((CursorX + 1) * Width) - 1,(CursorY + 1) * TextFontHeight - 1);
  1892.  
  1893.             break;
  1894.  
  1895.         case 2:    ScrollLineRectFill(RPort,0,0,LastPixel,(LastLine + 1) * TextFontHeight - 1);
  1896.             break;
  1897.  
  1898.         default:ScrollLineRectFill(RPort,CursorX * Width,CursorY * TextFontHeight,LastPixel,(CursorY + 1) * TextFontHeight - 1);
  1899.  
  1900.             if(CursorY != LastLine)
  1901.                 ScrollLineRectFill(RPort,0,(CursorY + 1) * TextFontHeight,LastPixel,(LastLine + 1) * TextFontHeight - 1);
  1902.  
  1903.             break;
  1904.     }
  1905.  
  1906.     ScrollLineEraseScreen(Value);
  1907.  
  1908.     RasterEraseScreen(Value);
  1909.  
  1910.     DrawCursor();
  1911.  
  1912.     BackupRender();
  1913.  
  1914.     return(NULL);
  1915. }
  1916.  
  1917.     /* EraseCharacters(UBYTE *Buffer):
  1918.      *
  1919.      *    Erase a number of characters.
  1920.      */
  1921.  
  1922. UBYTE * __regargs
  1923. EraseCharacters(UBYTE *Buffer)
  1924. {
  1925.     WORD Value;
  1926.  
  1927.     ReadValue(Buffer,&Value);
  1928.  
  1929.     BackupRender();
  1930.  
  1931.     SetBPen(RPort,0);
  1932.  
  1933.     if(Value == -1)
  1934.         Value = 1;
  1935.  
  1936.     if(Value > 0)
  1937.     {
  1938.         WORD Width = GetFontWidth();
  1939.  
  1940.         RasterEraseCharacters(Value);
  1941.  
  1942.         ScrollLineEraseCharacters(Value);
  1943.  
  1944.         ClearCursor();
  1945.  
  1946.         ScrollLineRaster(RPort,Value * Width,0,CursorX * Width,CursorY * TextFontHeight,LastPixel,(CursorY + 1) * TextFontHeight - 1);
  1947.  
  1948.         DrawCursor();
  1949.     }
  1950.  
  1951.     BackupRender();
  1952.  
  1953.     return(NULL);
  1954. }
  1955.  
  1956.     /* InsertCharacters(UBYTE *Buffer):
  1957.      *
  1958.      *    Insert a number of characters.
  1959.      */
  1960.  
  1961. UBYTE * __regargs
  1962. InsertCharacters(UBYTE *Buffer)
  1963. {
  1964.     WORD Value;
  1965.  
  1966.     ReadValue(Buffer,&Value);
  1967.  
  1968.     BackupRender();
  1969.  
  1970.     SetBPen(RPort,0);
  1971.  
  1972.     if(Value == -1)
  1973.         Value = 1;
  1974.  
  1975.     if(Value > 0)
  1976.     {
  1977.         WORD Width = GetFontWidth();
  1978.  
  1979.         RasterShiftChar(Value);
  1980.  
  1981.         ScrollLineShiftChar(Value);
  1982.  
  1983.         ClearCursor();
  1984.  
  1985.         ScrollLineRaster(RPort,-Value * Width,0,CursorX * Width,CursorY * TextFontHeight,LastPixel,(CursorY + 1) * TextFontHeight - 1);
  1986.  
  1987.         DrawCursor();
  1988.     }
  1989.  
  1990.     BackupRender();
  1991.  
  1992.     return(NULL);
  1993. }
  1994.  
  1995.     /* InsertLine(UBYTE *Buffer):
  1996.      *
  1997.      *    Insert a number of lines and scroll the rest of the
  1998.      *    display down.
  1999.      */
  2000.  
  2001. UBYTE * __regargs
  2002. InsertLine(UBYTE *Buffer)
  2003. {
  2004.     WORD Value;
  2005.  
  2006.     ReadValue(Buffer,&Value);
  2007.  
  2008.     BackupRender();
  2009.  
  2010.     SetAPen(RPort,0);
  2011.  
  2012.     if(Value == -1)
  2013.         Value = 1;
  2014.  
  2015.     if(Value > 0)
  2016.     {
  2017.         WORD RegionBottom,RegionTop,TheTop = CursorY;
  2018.  
  2019.         if(RegionSet)
  2020.         {
  2021.             RegionTop    = Top;
  2022.             RegionBottom    = Bottom + 1;
  2023.         }
  2024.         else
  2025.         {
  2026.             RegionTop    = 0;
  2027.             RegionBottom    = LastLine + 1;
  2028.         }
  2029.  
  2030.         if(TheTop < RegionTop)
  2031.             TheTop = RegionTop;
  2032.  
  2033.         RasterInsertLine(Value,TheTop);
  2034.  
  2035.         ClearCursor();
  2036.  
  2037.         ScrollLineRaster(RPort,0,-(Value * TextFontHeight),0,TheTop * TextFontHeight,LastPixel,RegionBottom * TextFontHeight - 1);
  2038.  
  2039.         DrawCursor();
  2040.     }
  2041.  
  2042.     BackupRender();
  2043.  
  2044.     return(NULL);
  2045. }
  2046.  
  2047.     /* ClearLine(UBYTE *Buffer):
  2048.      *
  2049.      *    Clear a number of lines and scroll up the ones below it.
  2050.      */
  2051.  
  2052. UBYTE * __regargs
  2053. ClearLine(UBYTE *Buffer)
  2054. {
  2055.     WORD Value;
  2056.  
  2057.     ReadValue(Buffer,&Value);
  2058.  
  2059.     BackupRender();
  2060.  
  2061.     SetAPen(RPort,0);
  2062.  
  2063.     if(Value == -1)
  2064.         Value = 1;
  2065.  
  2066.     if(Value > 0)
  2067.     {
  2068.         WORD RegionBottom,RegionTop,TheTop = CursorY;
  2069.  
  2070.         if(RegionSet)
  2071.         {
  2072.             RegionTop    = Top;
  2073.             RegionBottom    = Bottom + 1;
  2074.         }
  2075.         else
  2076.         {
  2077.             RegionTop    = 0;
  2078.             RegionBottom    = LastLine + 1;
  2079.         }
  2080.  
  2081.         if(TheTop < RegionTop)
  2082.             TheTop = RegionTop;
  2083.  
  2084.         RasterClearLine(Value,TheTop);
  2085.  
  2086.         ClearCursor();
  2087.  
  2088.         ScrollLineRaster(RPort,0,Value * TextFontHeight,0,TheTop * TextFontHeight,LastPixel,RegionBottom * TextFontHeight - 1);
  2089.  
  2090.         DrawCursor();
  2091.     }
  2092.  
  2093.     BackupRender();
  2094.  
  2095.     return(NULL);
  2096. }
  2097.  
  2098.     /* SetTabs(UBYTE *Buffer):
  2099.      *
  2100.      *    Set the current tab stops.
  2101.      */
  2102.  
  2103. UBYTE * __regargs
  2104. SetTabs(UBYTE *Buffer)
  2105. {
  2106.     WORD Value;
  2107.  
  2108.     ReadValue(Buffer,&Value);
  2109.  
  2110.     if(Value == -1)
  2111.         Value = 0;
  2112.  
  2113.     switch(Value)
  2114.     {
  2115.         case 0:    if(CursorX < 1024)
  2116.                 TabStops[CursorX] = FALSE;
  2117.  
  2118.             break;
  2119.  
  2120.         case 3:    memset(&TabStops[0],FALSE,1024);
  2121.  
  2122.             break;
  2123.  
  2124.         default:break;
  2125.     }
  2126.  
  2127.     return(NULL);
  2128. }
  2129.  
  2130.     /* SetAbsolutePosition(UBYTE *Buffer):
  2131.      *
  2132.      *    Move the cursor to a given location on the display,
  2133.      *    this routine ignores the current scroll region
  2134.      *    settings.
  2135.      */
  2136.  
  2137. UBYTE * __regargs
  2138. SetAbsolutePosition(UBYTE *Buffer)
  2139. {
  2140.     WORD Value;
  2141.  
  2142.     Buffer = ReadValue(Buffer,&Value);
  2143.  
  2144.     ClearCursor();
  2145.  
  2146.     if(UseRegion && RegionSet)
  2147.         CursorY = Top;
  2148.     else
  2149.         CursorY = 0;
  2150.  
  2151.     CursorX = 0;
  2152.  
  2153.     if(Value != -1)
  2154.     {
  2155.             /* Our raster origin is 0/0 instead of 1/1. */
  2156.  
  2157.         if(Value)
  2158.             Value--;
  2159.  
  2160.         if(UseRegion && RegionSet)
  2161.             CursorY = Top + Value;
  2162.         else
  2163.             CursorY = Value;
  2164.  
  2165.         if(Buffer)
  2166.         {
  2167.             ReadValue(Buffer,&Value);
  2168.  
  2169.             if(Value > 0)
  2170.                 CursorX = Value - 1;
  2171.             else
  2172.                 CursorX = 0;
  2173.         }
  2174.  
  2175.             /* Truncate illegal positions. */
  2176.  
  2177.         if(CursorX > LastColumn)
  2178.             CursorX = LastColumn;
  2179.  
  2180.         if(CursorY > LastLine)
  2181.             CursorY = LastLine;
  2182.     }
  2183.  
  2184.     SetCursor();
  2185.  
  2186.     return(NULL);
  2187. }
  2188.  
  2189.     /* SetAttributes(UBYTE *Buffer):
  2190.      *
  2191.      *    Set the current display rendering attributes.
  2192.      */
  2193.  
  2194. UBYTE * __regargs
  2195. SetAttributes(UBYTE *Buffer)
  2196. {
  2197.     LONG TextFlags = FS_NORMAL;
  2198.     WORD Value;
  2199.  
  2200.     ClearCursor();
  2201.  
  2202.     do
  2203.     {
  2204.         Buffer = ReadValue(Buffer,&Value);
  2205.  
  2206.         if(Value == -1)
  2207.             Value = 0;
  2208.  
  2209.         switch(Value)
  2210.         {
  2211.             case 0:    switch(Config . ColourMode)
  2212.                 {
  2213.                     case COLOUR_AMIGA:
  2214.                     case COLOUR_MONO:    FgPen = 1;
  2215.                                 break;
  2216.  
  2217.                     case COLOUR_EIGHT:    FgPen = 7;
  2218.                                 break;
  2219.  
  2220.                     case COLOUR_SIXTEEN:    FgPen = 15;
  2221.                                 break;
  2222.                 }
  2223.  
  2224.                 BgPen = 0;
  2225.  
  2226.                 if(RPort -> FgPen != FgPen)
  2227.                     SetAPen(RPort,FgPen);
  2228.  
  2229.                 if(RPort -> BgPen != BgPen)
  2230.                     SetBPen(RPort,BgPen);
  2231.  
  2232.                 Attributes = 0;
  2233.  
  2234.                 break;
  2235.  
  2236.             case 1:    Attributes |= ATTR_HIGHLIGHT;
  2237.  
  2238.                 break;
  2239.  
  2240.             case 4:    Attributes |= ATTR_UNDERLINE;
  2241.  
  2242.                 break;
  2243.  
  2244.             case 5:    Attributes |= ATTR_BLINK;
  2245.  
  2246.                 break;
  2247.  
  2248.             case 7:    if(!(Attributes & ATTR_INVERSE))
  2249.                 {
  2250.                     BYTE Help;
  2251.  
  2252.                     Help    = FgPen;
  2253.                     FgPen    = BgPen;
  2254.                     BgPen    = Help;
  2255.                 }
  2256.  
  2257.                 Attributes |= ATTR_INVERSE;
  2258.  
  2259.                 break;
  2260.  
  2261.             default:if(Value >= 30)
  2262.                 {
  2263.                     if(Value <= 37)
  2264.                     {
  2265.                         if(Attributes & ATTR_INVERSE)
  2266.                             BgPen = Value - 30;
  2267.                         else
  2268.                             FgPen = Value - 30;
  2269.                     }
  2270.                     else
  2271.                     {
  2272.                         if(Value >= 40 && Value <= 47)
  2273.                         {
  2274.                             if(Attributes & ATTR_INVERSE)
  2275.                                 FgPen = Value - 40;
  2276.                             else
  2277.                                 BgPen = Value - 40;
  2278.                         }
  2279.                     }
  2280.                 }
  2281.  
  2282.                 break;
  2283.         }
  2284.     }
  2285.     while(Buffer);
  2286.  
  2287.     if(Attributes & ATTR_UNDERLINE)
  2288.         TextFlags |= FSF_UNDERLINED;
  2289.  
  2290.     if(Attributes & ATTR_HIGHLIGHT)
  2291.     {
  2292.         if(Config . ColourMode == COLOUR_SIXTEEN)
  2293.         {
  2294.             if(Attributes & ATTR_INVERSE)
  2295.                 BgPen |= 8;
  2296.             else
  2297.                 FgPen |= 8;
  2298.         }
  2299.         else
  2300.             TextFlags |= FSF_BOLD;
  2301.     }
  2302.  
  2303.     if(Attributes & ATTR_BLINK)
  2304.     {
  2305.         if(Config . Emulation == EMULATION_ANSIVT100)
  2306.         {
  2307.             switch(Config . ColourMode)
  2308.             {
  2309.                 case COLOUR_AMIGA:    if(Attributes & ATTR_INVERSE)
  2310.                                 BgPen = 3;
  2311.                             else
  2312.                                 FgPen = 3;
  2313.                             break;
  2314.  
  2315.                 case COLOUR_EIGHT:    if(Attributes & ATTR_INVERSE)
  2316.                                 BgPen |= 8;
  2317.                             else
  2318.                                 FgPen |= 8;
  2319.                             break;
  2320.  
  2321.                 case COLOUR_SIXTEEN:    break;
  2322.  
  2323.                 case COLOUR_MONO:    if(Attributes & ATTR_INVERSE)
  2324.                                 BgPen = 1;
  2325.                             else
  2326.                                 FgPen = 1;
  2327.  
  2328.                             break;
  2329.             }
  2330.         }
  2331.     }
  2332.  
  2333.     if(TextFlags != StyleType)
  2334.     {
  2335.         SetSoftStyle(RPort,TextFlags,0xFF);
  2336.  
  2337.         StyleType = TextFlags;
  2338.     }
  2339.  
  2340.     if(Config . ColourMode == COLOUR_MONO)
  2341.     {
  2342.         if((FgPen & 1) == (BgPen & 1))
  2343.         {
  2344.             if(ColourValue(FgPen) < ColourValue(BgPen))
  2345.             {
  2346.                 if(Attributes & ATTR_INVERSE)
  2347.                 {
  2348.                     FgPen = 1;
  2349.                     BgPen = 0;
  2350.                 }
  2351.                 else
  2352.                 {
  2353.                     FgPen = 0;
  2354.                     BgPen = 1;
  2355.                 }
  2356.             }
  2357.             else
  2358.             {
  2359.                 if(Attributes & ATTR_INVERSE)
  2360.                 {
  2361.                     FgPen = 0;
  2362.                     BgPen = 1;
  2363.                 }
  2364.                 else
  2365.                 {
  2366.                     FgPen = 1;
  2367.                     BgPen = 0;
  2368.                 }
  2369.             }
  2370.         }
  2371.     }
  2372.  
  2373.     if(FgPen != RPort -> FgPen)
  2374.         SetAPen(RPort,FgPen);
  2375.  
  2376.     if(BgPen != RPort -> BgPen)
  2377.         SetBPen(RPort,BgPen);
  2378.  
  2379.     SetCursor();
  2380.  
  2381.     return(NULL);
  2382. }
  2383.  
  2384.     /* SetRegion(UBYTE *Buffer):
  2385.      *
  2386.      *    Set the current scroll region top and bottom.
  2387.      */
  2388.  
  2389. UBYTE * __regargs
  2390. SetRegion(UBYTE *Buffer)
  2391. {
  2392.     WORD NewTop,Value,NewBottom = LastLine;
  2393.  
  2394.     Buffer = ReadValue(Buffer,&Value);
  2395.  
  2396.     if(Value > 0)
  2397.     {
  2398.         NewTop = Value;
  2399.  
  2400.         if(Value > 0)
  2401.             NewTop = Value - 1;
  2402.  
  2403.         if(Buffer)
  2404.         {
  2405.             ReadValue(Buffer,&Value);
  2406.  
  2407.             if(Value > 0)
  2408.                 NewBottom = Value - 1;
  2409.         }
  2410.  
  2411.         if(NewBottom > LastLine)
  2412.             NewBottom = LastLine;
  2413.  
  2414.         if(NewTop > LastLine)
  2415.             NewTop = LastLine;
  2416.     }
  2417.     else
  2418.     {
  2419.         NewTop        = 0;
  2420.         NewBottom    = LastLine;
  2421.     }
  2422.  
  2423.     if(NewTop < NewBottom)
  2424.     {
  2425.         if(NewTop != 0 || NewBottom != LastLine)
  2426.         {
  2427.             Top    = NewTop;
  2428.             Bottom    = NewBottom;
  2429.  
  2430.             RegionSet = TRUE;
  2431.         }
  2432.         else
  2433.             UseRegion = RegionSet = FALSE;
  2434.  
  2435.         ResetCursor();
  2436.     }
  2437.     else
  2438.         RegionSet = FALSE;
  2439.  
  2440.     return(NULL);
  2441. }
  2442.  
  2443.     /* ResetCursor():
  2444.      *
  2445.      *    Reset cursor to top of screen.
  2446.      */
  2447.  
  2448. VOID
  2449. ResetCursor()
  2450. {
  2451.     ClearCursor();
  2452.  
  2453.     CursorX    = 0;
  2454.  
  2455.     if(UseRegion && RegionSet)
  2456.         CursorY = Top;
  2457.     else
  2458.         CursorY    = 0;
  2459.  
  2460.     SetCursor();
  2461. }
  2462.