home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / term43-source.lha / Extras / Source / term-Source.lha / termEmulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-16  |  46.3 KB  |  2,945 lines

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