home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / Emulation.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  50.0 KB  |  3,250 lines

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