home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term33so.lha / termConsole.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  46KB  |  2,652 lines

  1. /*
  2. **    termConsole.c
  3. **
  4. **    High-level terminal console routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Character set modes. */
  13.  
  14. enum    {    MODE_STANDARD,MODE_GFX };
  15.  
  16.     /* Hints for the data flow scanner. */
  17.  
  18. STATIC WORD    ScanStart,
  19.         ScanEnd;
  20.  
  21. STATIC WORD    AttentionCount[SCAN_COUNT],
  22.         AttentionLength[SCAN_COUNT],
  23.         FlowCount;
  24.  
  25.     /* Temporary console working buffer. */
  26.  
  27. STATIC UBYTE    ConTempBuffer[512];
  28.  
  29.     /* Text output data. */
  30.  
  31. STATIC UBYTE    CurrentFontScale,FontScalingRequired;
  32. STATIC WORD    LastPrintableColumn;
  33.  
  34.     /* ConTranslateSetup():
  35.      *
  36.      *    Set up for buffer translation.
  37.      */
  38.  
  39. STATIC VOID __inline
  40. ConTranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  41. {
  42.     Handle -> LocalBuffer        = NULL;
  43.     Handle -> LocalLen        = 0;
  44.  
  45.     Handle -> SourceBuffer        = SourceBuffer;
  46.     Handle -> SourceLen        = SourceLen;
  47.  
  48.     Handle -> DestinationBuffer    = DestinationBuffer;
  49.     Handle -> DestinationLen    = DestinationLen;
  50.  
  51.     Handle -> Table            = Table;
  52. }
  53.  
  54.     /* ConTranslateBuffer(struct TranslationHandle *Handle):
  55.      *
  56.      *    Translate buffer contents according to
  57.      *    translation table contents.
  58.      */
  59.  
  60. STATIC LONG __inline
  61. ConTranslateBuffer(struct TranslationHandle *Handle)
  62. {
  63.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  64.     register LONG                 BytesWritten    = 0;
  65.     register struct TranslationEntry    *Entry;
  66.  
  67.         /* Are we to return any translated data? */
  68.  
  69.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  70.     {
  71.             /* Decrement number of bytes in buffer. */
  72.  
  73.         Handle -> LocalLen--;
  74.  
  75.             /* Return next character. */
  76.  
  77.         *Data++ = *Handle -> LocalBuffer++;
  78.  
  79.             /* Add another byte. */
  80.  
  81.         BytesWritten++;
  82.     }
  83.  
  84.         /* Loop until done. */
  85.  
  86.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  87.     {
  88.             /* Another byte eaten. */
  89.  
  90.         Handle -> SourceLen--;
  91.  
  92.             /* Get table entry. */
  93.  
  94.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  95.         {
  96.                 /* Copy to local data area. */
  97.  
  98.             Handle -> LocalBuffer    = Entry -> String;
  99.             Handle -> LocalLen    = Entry -> Len;
  100.  
  101.                 /* Translate the data. */
  102.  
  103.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  104.             {
  105.                     /* Decrement number of bytes in buffer. */
  106.  
  107.                 Handle -> LocalLen--;
  108.  
  109.                     /* Return next character. */
  110.  
  111.                 *Data++ = *Handle -> LocalBuffer++;
  112.  
  113.                     /* Add another byte. */
  114.  
  115.                 BytesWritten++;
  116.             }
  117.         }
  118.     }
  119.  
  120.     return(BytesWritten);
  121. }
  122.  
  123.     /* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
  124.      *
  125.      *    Data flow filter.
  126.      */
  127.  
  128. STATIC VOID __regargs
  129. FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
  130. {
  131.     register UBYTE c;
  132.  
  133.         /* Run until done. */
  134.  
  135.     do
  136.     {
  137.         if(c = (*Data++ & Mask))
  138.         {
  139.  
  140.                 /* We already got a `CONNECT',
  141.                  * Continue scanning the serial output
  142.                  * data for the actual baud rate.
  143.                  */
  144.  
  145.             if(BaudPending)
  146.             {
  147.                 if(c < ' ')
  148.                 {
  149.                     while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  150.                         BaudCount--;
  151.  
  152.                     BaudBuffer[BaudCount] = 0;
  153.  
  154.                     FlowInfo . Connect = TRUE;
  155.                     FlowInfo . Changed = TRUE;
  156.  
  157.                     BaudPending = FALSE;
  158.  
  159.                     DTERate = GetBaudRate(BaudBuffer);
  160.                 }
  161.                 else
  162.                 {
  163.                     if(BaudCount || c != ' ')
  164.                     {
  165.                         BaudBuffer[BaudCount++] = c;
  166.  
  167.                         if(BaudCount == 79)
  168.                         {
  169.                             while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  170.                                 BaudCount--;
  171.  
  172.                             BaudBuffer[BaudCount] = 0;
  173.  
  174.                             FlowInfo . Connect = TRUE;
  175.                             FlowInfo . Changed = TRUE;
  176.  
  177.                             BaudPending = FALSE;
  178.  
  179.                             DTERate = GetBaudRate(BaudBuffer);
  180.                         }
  181.                     }
  182.                 }
  183.             }
  184.             else
  185.             {
  186.                 register BYTE MatchMade;
  187.                 register WORD i;
  188.  
  189.                 do
  190.                 {
  191.                     MatchMade = FALSE;
  192.  
  193.                         /* Scan all ID strings for matches. */
  194.  
  195.                     for(i = ScanStart ; i <= ScanEnd ; i++)
  196.                     {
  197.                             /* This sequence is a likely
  198.                              * match.
  199.                              */
  200.  
  201.                         if(AttentionCount[i] == FlowCount)
  202.                         {
  203.                                 /* Does the character
  204.                                  * fit into the sequence?
  205.                                  */
  206.  
  207.                             if(c == AttentionBuffers[i][FlowCount] & Mask)
  208.                             {
  209.                                 MatchMade = TRUE;
  210.  
  211.                                     /* Did we hit the
  212.                                      * last character
  213.                                      * in the sequence?
  214.                                      */
  215.  
  216.                                 if(++AttentionCount[i] == AttentionLength[i])
  217.                                 {
  218.                                         /* We've got a valid
  219.                                          * sequence, now look
  220.                                          * which flags to change.
  221.                                          */
  222.  
  223.                                     switch(i)
  224.                                     {
  225.                                             /* We got a `no carrier' message. */
  226.  
  227.                                         case SCAN_NOCARRIER:
  228.  
  229.                                             if(Config -> SerialConfig -> CheckCarrier)
  230.                                             {
  231.                                                 WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  232.  
  233.                                                 DoIO(WriteRequest);
  234.  
  235.                                                     /* Is the carrier still present? */
  236.  
  237.                                                 if(!(WriteRequest -> io_Status & CIAF_COMCD))
  238.                                                     break;
  239.                                             }
  240.  
  241.                                             if(!FlowInfo . NoCarrier)
  242.                                             {
  243.                                                 FlowInfo . NoCarrier    = TRUE;
  244.                                                 FlowInfo . Changed    = TRUE;
  245.                                             }
  246.  
  247.                                             WasOnline = Online;
  248.  
  249.                                             Online = FALSE;
  250.  
  251.                                                 /* Clear the password. */
  252.  
  253.                                             Password[0] = 0;
  254.                                             UserName[0] = 0;
  255.  
  256.                                             CurrentBBSName[0]    = 0;
  257.                                             CurrentBBSComment[0]    = 0;
  258.                                             CurrentBBSNumber[0]    = 0;
  259.  
  260.                                             if(WasOnline)
  261.                                             {
  262.                                                 StopCall(FALSE);
  263.  
  264.                                                 if(CurrentPay && ChosenEntry)
  265.                                                     LogAction(LocaleString(MSG_TERMAUX_CARRIER_LOST_COST_TXT),CreateSum(CurrentPay,TRUE));
  266.                                                 else
  267.                                                     LogAction(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT));
  268.  
  269.                                                 Say(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT));
  270.  
  271.                                                 SetDialMenu(TRUE);
  272.                                             }
  273.  
  274.                                             break;
  275.  
  276.                                             /* Got another call. */
  277.  
  278.                                         case SCAN_RING:
  279.  
  280.                                             if(!FlowInfo . Ring)
  281.                                             {
  282.                                                 FlowInfo . Ring        = TRUE;
  283.                                                 FlowInfo . Changed    = TRUE;
  284.                                             }
  285.  
  286.                                             break;
  287.  
  288.                                             /* Got a voice call. */
  289.  
  290.                                         case SCAN_VOICE:
  291.  
  292.                                             if(!FlowInfo . Voice)
  293.                                             {
  294.                                                 FlowInfo . Voice    = TRUE;
  295.                                                 FlowInfo . Changed    = TRUE;
  296.                                             }
  297.  
  298.                                             break;
  299.  
  300.                                             /* Got a connect message. */
  301.  
  302.                                         case SCAN_CONNECT:
  303.  
  304.                                                 /* Are we to check the carrier signal? */
  305.  
  306.                                             if(Config -> SerialConfig -> CheckCarrier)
  307.                                             {
  308.                                                 WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  309.  
  310.                                                 DoIO(WriteRequest);
  311.  
  312.                                                     /* Is the carrier signal present, i.e.
  313.                                                      * was the `CONNECT' message valid?
  314.                                                      */
  315.  
  316.                                                 if(WriteRequest -> io_Status & CIAF_COMCD)
  317.                                                     break;
  318.                                             }
  319.  
  320.                                             WasOnline = Online;
  321.  
  322.                                             if(!Online)
  323.                                             {
  324.                                                 BaudBuffer[0]    = 0;
  325.  
  326.                                                 BaudPending    = TRUE;
  327.                                                 BaudCount    = 0;
  328.                                             }
  329.  
  330.                                             break;
  331.  
  332.                                             /* Got the ZModem inquiry sequence. */
  333.  
  334.                                         case SCAN_ZMODEM:
  335.  
  336.                                             if(!FlowInfo . ZModemUpload)
  337.                                             {
  338.                                                 FlowInfo . ZModemUpload    = TRUE;
  339.                                                 FlowInfo . Changed    = TRUE;
  340.                                             }
  341.  
  342.                                             break;
  343.  
  344.                                             /* Line is busy. */
  345.  
  346.                                         case SCAN_BUSY:
  347.  
  348.                                             if(!FlowInfo . Busy)
  349.                                             {
  350.                                                 FlowInfo . Busy        = TRUE;
  351.                                                 FlowInfo . Changed    = TRUE;
  352.                                             }
  353.  
  354.                                             break;
  355.  
  356.                                         case SCAN_NODIALTONE:
  357.  
  358.                                             if(!FlowInfo . NoDialTone)
  359.                                             {
  360.                                                 FlowInfo . NoDialTone    = TRUE;
  361.                                                 FlowInfo . Changed    = TRUE;
  362.                                             }
  363.  
  364.                                             break;
  365.                                     }
  366.                                 }
  367.                             }
  368.                         }
  369.                     }
  370.  
  371.                     if(MatchMade)
  372.                         FlowCount++;
  373.                     else
  374.                     {
  375.                         if(FlowCount)
  376.                         {
  377.                             FlowCount = 0;
  378.  
  379.                             memset(AttentionCount,0,sizeof(AttentionCount));
  380.                         }
  381.                         else
  382.                             break;
  383.                     }
  384.                 }
  385.                 while(!FlowCount);
  386.             }
  387.         }
  388.     }
  389.     while(--Size);
  390. }
  391.  
  392.     /* StripSequence():
  393.      *
  394.      *    Strips a string from ESC and CSI introduced control
  395.      *    sequences.
  396.      */
  397.  
  398. STATIC LONG __regargs
  399. StripSequence(STRPTR Src,STRPTR Dst,LONG Length)
  400. {
  401.     STATIC BYTE    HasESC    = FALSE,
  402.             HasCSI    = FALSE;
  403.     LONG        Size    = 0;
  404.  
  405.     while(Length--)
  406.     {
  407.         if(HasESC)
  408.         {
  409.             if(*Src == '[')
  410.             {
  411.                 HasESC = FALSE;
  412.                 HasCSI = TRUE;
  413.             }
  414.             else
  415.             {
  416.                 if(*Src >= '0')
  417.                     HasESC = FALSE;
  418.             }
  419.  
  420.             Src++;
  421.  
  422.             continue;
  423.         }
  424.  
  425.         if(HasCSI)
  426.         {
  427.             if(*Src >= '@')
  428.                 HasCSI = FALSE;
  429.  
  430.             Src++;
  431.  
  432.             continue;
  433.         }
  434.  
  435.         switch(*Src)
  436.         {
  437.             case CAN:
  438.             case SUB:
  439.  
  440.                 HasESC = HasCSI = FALSE;
  441.                 break;
  442.  
  443.             case '\r':
  444.  
  445.                 break;
  446.  
  447.             case ESC:
  448.  
  449.                 HasESC = TRUE;
  450.                 break;
  451.  
  452.             case CSI:
  453.  
  454.                 HasCSI = TRUE;
  455.                 break;
  456.  
  457.             default:
  458.  
  459.                 if(IsPrintable[*Src])
  460.                 {
  461.                     *Dst++ = *Src;
  462.  
  463.                     Size++;
  464.                 }
  465.  
  466.                 break;
  467.         }
  468.  
  469.         Src++;
  470.     }
  471.  
  472.     return(Size);
  473. }
  474.  
  475.     /* ConOutputPrinter(STRPTR Buffer,LONG Size):
  476.      *
  477.      *    Raw text output routine, printer capture flavour.
  478.      */
  479.  
  480. STATIC VOID __regargs
  481. ConOutputPrinter(STRPTR Buffer,LONG Size)
  482. {
  483.     if(FWrite(PrinterCapture,Buffer,Size,1) != 1)
  484.     {
  485.         BlockWindows();
  486.  
  487.         if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  488.             ClosePrinterCapture(TRUE);
  489.  
  490.         ReleaseWindows();
  491.     }
  492. }
  493.  
  494.     /* ConOutputCaptureGFX(STRPTR Buffer,LONG Size):
  495.      *
  496.      *    Raw text output routine, GFX text & capture flavour.
  497.      */
  498.  
  499. STATIC VOID __regargs
  500. ConOutputCaptureGFX(STRPTR Buffer,LONG Size)
  501. {
  502.     register WORD Offset;
  503.  
  504.         /* Do we still have a character in the
  505.          * magnificient buffer?
  506.          */
  507.  
  508.     while(Size)
  509.     {
  510.             /* Cursor is positioned at
  511.              * the right hand side of the
  512.              * display. If auto-wrap is
  513.              * enabled, perform some
  514.              * kind of CR/LF, else leave
  515.              * the cursor where it is and
  516.              * quit the show.
  517.              */
  518.  
  519.         if(CursorX > LastPrintableColumn)
  520.         {
  521.                 /* Wrap cursor. */
  522.  
  523.             if(Config -> EmulationConfig -> LineWrap)
  524.             {
  525.                     /* Move to beginning of next line. */
  526.  
  527.                 CursorX = 0;
  528.  
  529.                 DownLine();
  530.  
  531.                 Capture("\n",1);
  532.  
  533.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  534.  
  535.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  536.  
  537.                 LastPrintableColumn = LastColumn;
  538.  
  539.                     /* Reposition cursor, don't redraw it. */
  540.  
  541.                 ClipBlitCursor(FALSE,TRUE);
  542.             }
  543.             else
  544.             {
  545.                     /* Stop the cursor. */
  546.  
  547.                 CursorX = LastPrintableColumn;
  548.  
  549.                 Capture(Buffer,Size);
  550.  
  551.                     /* Make it reappear. */
  552.  
  553.                 ClipBlitCursor(FALSE,TRUE);
  554.  
  555.                 return;
  556.             }
  557.         }
  558.  
  559.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  560.             Offset = Size;
  561.  
  562.         if(Config -> EmulationConfig -> InsertMode)
  563.         {
  564.             RasterShiftChar(Offset);
  565.  
  566.             ScrollLineShiftChar(Offset);
  567.  
  568.             ShiftChar(Offset);
  569.         }
  570.  
  571.         RasterPutString(Buffer,Offset);
  572.  
  573.         ScrollLinePutString(Offset);
  574.  
  575.         if(FontScalingRequired)
  576.             PrintScaled(Buffer,Offset,CurrentFontScale);
  577.         else
  578.             GfxText(RPort,Buffer,Offset);
  579.  
  580.         Capture(Buffer,Offset);
  581.  
  582.         Buffer    += Offset;
  583.  
  584.         Size    -= Offset;
  585.  
  586.         CursorX    += Offset;
  587.     }
  588.  
  589.     ClipBlitCursor(FALSE,TRUE);
  590. }
  591.  
  592.     /* ConOutputCaptureNormal(STRPTR Buffer,LONG Size):
  593.      *
  594.      *    Raw text output routine, normal text & capture flavour.
  595.      */
  596.  
  597. STATIC VOID __regargs
  598. ConOutputCaptureNormal(STRPTR Buffer,LONG Size)
  599. {
  600.     register WORD Offset;
  601.  
  602.     while(Size)
  603.     {
  604.         if(CursorX > LastPrintableColumn)
  605.         {
  606.             if(Config -> EmulationConfig -> LineWrap)
  607.             {
  608.                 CursorX = 0;
  609.  
  610.                 DownLine();
  611.  
  612.                 Capture("\n",1);
  613.  
  614.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  615.  
  616.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  617.  
  618.                 LastPrintableColumn = LastColumn;
  619.  
  620.                 ClipBlitCursor(FALSE,TRUE);
  621.             }
  622.             else
  623.             {
  624.                 CursorX = LastPrintableColumn;
  625.  
  626.                 Capture(Buffer,Size);
  627.  
  628.                 ClipBlitCursor(FALSE,TRUE);
  629.  
  630.                 return;
  631.             }
  632.         }
  633.  
  634.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  635.             Offset = Size;
  636.  
  637.         if(Config -> EmulationConfig -> InsertMode)
  638.         {
  639.             RasterShiftChar(Offset);
  640.  
  641.             ScrollLineShiftChar(Offset);
  642.  
  643.             ShiftChar(Offset);
  644.         }
  645.  
  646.         RasterPutString(Buffer,Offset);
  647.  
  648.         ScrollLinePutString(Offset);
  649.  
  650.         if(FontScalingRequired)
  651.             PrintScaled(Buffer,Offset,CurrentFontScale);
  652.         else
  653.             Text(RPort,Buffer,Offset);
  654.  
  655.         Capture(Buffer,Offset);
  656.  
  657.         Buffer    += Offset;
  658.  
  659.         Size    -= Offset;
  660.  
  661.         CursorX    += Offset;
  662.     }
  663.  
  664.     ClipBlitCursor(FALSE,TRUE);
  665. }
  666.  
  667.     /* ConOutputGFX(STRPTR Buffer,LONG Size):
  668.      *
  669.      *    Raw text output routine, GFX text flavour.
  670.      */
  671.  
  672. STATIC VOID __regargs
  673. ConOutputGFX(STRPTR Buffer,LONG Size)
  674. {
  675.     register WORD Offset;
  676.  
  677.         /* Do we still have a character in the
  678.          * magnificient buffer?
  679.          */
  680.  
  681.     while(Size)
  682.     {
  683.             /* Cursor is positioned at
  684.              * the right hand side of the
  685.              * display. If auto-wrap is
  686.              * enabled, perform some
  687.              * kind of CR/LF, else leave
  688.              * the cursor where it is and
  689.              * quit the show.
  690.              */
  691.  
  692.         if(CursorX > LastPrintableColumn)
  693.         {
  694.                 /* Wrap cursor. */
  695.  
  696.             if(Config -> EmulationConfig -> LineWrap)
  697.             {
  698.                     /* Move to beginning of next line. */
  699.  
  700.                 CursorX = 0;
  701.  
  702.                 DownLine();
  703.  
  704.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  705.  
  706.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  707.  
  708.                 LastPrintableColumn = LastColumn;
  709.  
  710.                     /* Reposition cursor, don't redraw it. */
  711.  
  712.                 ClipBlitCursor(FALSE,TRUE);
  713.             }
  714.             else
  715.             {
  716.                     /* Stop the cursor. */
  717.  
  718.                 CursorX = LastPrintableColumn;
  719.  
  720.                     /* Make it reappear. */
  721.  
  722.                 ClipBlitCursor(FALSE,TRUE);
  723.  
  724.                 return;
  725.             }
  726.         }
  727.  
  728.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  729.             Offset = Size;
  730.  
  731.         if(Config -> EmulationConfig -> InsertMode)
  732.         {
  733.             RasterShiftChar(Offset);
  734.  
  735.             ScrollLineShiftChar(Offset);
  736.  
  737.             ShiftChar(Offset);
  738.         }
  739.  
  740.         RasterPutString(Buffer,Offset);
  741.  
  742.         ScrollLinePutString(Offset);
  743.  
  744.         if(FontScalingRequired)
  745.             PrintScaled(Buffer,Offset,CurrentFontScale);
  746.         else
  747.             GfxText(RPort,Buffer,Offset);
  748.  
  749.         Buffer    += Offset;
  750.  
  751.         Size    -= Offset;
  752.  
  753.         CursorX    += Offset;
  754.     }
  755.  
  756.     ClipBlitCursor(FALSE,TRUE);
  757. }
  758.  
  759.     /* ConOutputNormal(STRPTR Buffer,LONG Size):
  760.      *
  761.      *    Raw text output routine, normal text flavour.
  762.      */
  763.  
  764. STATIC VOID __regargs
  765. ConOutputNormal(STRPTR Buffer,LONG Size)
  766. {
  767.     register WORD Offset;
  768.  
  769.     while(Size)
  770.     {
  771.         if(CursorX > LastPrintableColumn)
  772.         {
  773.             if(Config -> EmulationConfig -> LineWrap)
  774.             {
  775.                 CursorX = 0;
  776.  
  777.                 DownLine();
  778.  
  779.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  780.  
  781.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  782.  
  783.                 LastPrintableColumn = LastColumn;
  784.  
  785.                 ClipBlitCursor(FALSE,TRUE);
  786.             }
  787.             else
  788.             {
  789.                 CursorX = LastPrintableColumn;
  790.  
  791.                 ClipBlitCursor(FALSE,TRUE);
  792.  
  793.                 return;
  794.             }
  795.         }
  796.  
  797.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  798.             Offset = Size;
  799.  
  800.         if(Config -> EmulationConfig -> InsertMode)
  801.         {
  802.             RasterShiftChar(Offset);
  803.  
  804.             ScrollLineShiftChar(Offset);
  805.  
  806.             ShiftChar(Offset);
  807.         }
  808.  
  809.         RasterPutString(Buffer,Offset);
  810.  
  811.         ScrollLinePutString(Offset);
  812.  
  813.         if(FontScalingRequired)
  814.             PrintScaled(Buffer,Offset,CurrentFontScale);
  815.         else
  816.             Text(RPort,Buffer,Offset);
  817.  
  818.         Buffer    += Offset;
  819.  
  820.         Size    -= Offset;
  821.  
  822.         CursorX    += Offset;
  823.     }
  824.  
  825.     ClipBlitCursor(FALSE,TRUE);
  826. }
  827.  
  828.     /* ConOutputUpdate():
  829.      *
  830.      *    Choose the right raw text output routine for the job.
  831.      */
  832.  
  833. VOID
  834. ConOutputUpdate()
  835. {
  836.     if(ControllerActive)
  837.         ConOutput = ConOutputPrinter;
  838.     else
  839.     {
  840.         if((Config -> CaptureConfig -> CaptureFilterMode && FileCapture) || PrinterCapture)
  841.         {
  842.             if(CurrentFont == GFX)
  843.                 ConOutput = ConOutputCaptureGFX;
  844.             else
  845.                 ConOutput = ConOutputCaptureNormal;
  846.         }
  847.         else
  848.         {
  849.             if(BufferFrozen)
  850.             {
  851.                 if(CurrentFont == GFX)
  852.                     ConOutput = ConOutputGFX;
  853.                 else
  854.                     ConOutput = ConOutputNormal;
  855.             }
  856.             else
  857.             {
  858.                 if(CurrentFont == GFX)
  859.                     ConOutput = ConOutputCaptureGFX;
  860.                 else
  861.                     ConOutput = ConOutputCaptureNormal;
  862.             }
  863.         }
  864.     }
  865.  
  866.     if(ReceiveTable)
  867.         ConDump = ConTransWrite;
  868.     else
  869.         ConDump = ConOutput;
  870. }
  871.  
  872.     /* ConFontScaleUpdate():
  873.      *
  874.      *    Choose the right font scale for the job.
  875.      */
  876.  
  877. VOID
  878. ConFontScaleUpdate()
  879. {
  880.     CurrentFontScale = RasterAttr[CursorY];
  881.  
  882.     if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
  883.     {
  884.         FontScalingRequired    = (CurrentFontScale != SCALE_ATTR_2X);
  885.         LastPrintableColumn    = LastColumn;
  886.     }
  887.     else
  888.     {
  889.         if(FontScalingRequired = (CurrentFontScale != SCALE_ATTR_NORMAL))
  890.             LastPrintableColumn = ((LastColumn + 1) / 2) - 1;
  891.         else
  892.             LastPrintableColumn = LastColumn;
  893.     }
  894. }
  895.  
  896.     /* ConTransWrite(STRPTR Buffer,LONG Size):
  897.      *
  898.      *    Frontend for ConWrite(), including character translation.
  899.      */
  900.  
  901. VOID __regargs
  902. ConTransWrite(STRPTR Buffer,LONG Size)
  903. {
  904.     struct TranslationHandle    Handle;
  905.     UBYTE                LocalBuffer[256];
  906.  
  907.         /* Set up for translation. */
  908.  
  909.     ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
  910.  
  911.         /* Process and output the data. */
  912.  
  913.     while(Size = ConTranslateBuffer(&Handle))
  914.         (* ConOutput)(LocalBuffer,Size);
  915. }
  916.  
  917.     /* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
  918.      *
  919.      *    Process data, external emulation including translation flavour.
  920.      */
  921.  
  922. VOID __regargs
  923. ConProcessDataTransExternal(register STRPTR String,register LONG Size)
  924. {
  925.     struct TranslationHandle Handle;
  926.  
  927.         /* Set up for translation. */
  928.  
  929.     ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
  930.  
  931.     if(StripBuffer)
  932.     {
  933.         register LONG Len;
  934.  
  935.             /* Process and output the data. */
  936.  
  937.         while(Size = ConTranslateBuffer(&Handle))
  938.         {
  939.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  940.  
  941.             XEM_HostData . Source        = ConTempBuffer;
  942.             XEM_HostData . Destination    = StripBuffer;
  943.  
  944.             if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  945.                 Capture(StripBuffer,Len);
  946.         }
  947.     }
  948.     else
  949.     {
  950.             /* Process and output the data. */
  951.  
  952.         while(Size = ConTranslateBuffer(&Handle))
  953.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  954.     }
  955. }
  956.  
  957.     /* ConProcessDataExternal(register STRPTR String,register LONG Size):
  958.      *
  959.      *    Process data, external emulation flavour.
  960.      */
  961.  
  962. VOID __regargs
  963. ConProcessDataExternal(register STRPTR String,register LONG Size)
  964. {
  965.     XEmulatorWrite(XEM_IO,String,Size);
  966.  
  967.         /* Build another string to contain
  968.          * the pure ASCII contents, i.e.
  969.          * not including any ESC control
  970.          * sequences.
  971.          */
  972.  
  973.     if(StripBuffer)
  974.     {
  975.         register LONG Len;
  976.  
  977.         XEM_HostData . Source        = String;
  978.         XEM_HostData . Destination    = StripBuffer;
  979.  
  980.         if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  981.             Capture(StripBuffer,Len);
  982.     }
  983. }
  984.  
  985.     /* ConProcessData7(register STRPTR String,register LONG Size):
  986.      *
  987.      *    Process data, 7 bit flavour.
  988.      */
  989.  
  990. VOID __regargs
  991. ConProcessData7(register STRPTR String,register LONG Size)
  992. {
  993.     register LONG    Len = 0;
  994.     register UBYTE    c;
  995.  
  996.         /* If still parsing a sequence,
  997.          * continue with it.
  998.          */
  999.  
  1000.     if(InSequence)
  1001.     {
  1002.         while(Size--)
  1003.         {
  1004.             c = *String++ & 0x7F;
  1005.  
  1006.             if(!(*AbortTable[c])(c))
  1007.             {
  1008.                 InSequence = FALSE;
  1009.  
  1010.                 break;
  1011.             }
  1012.         }
  1013.     }
  1014.  
  1015.         /* Check which font we are in, if other than Topaz
  1016.          * the only invalid char is a Null (0) which will
  1017.          * display as a space if let to continue.
  1018.          */
  1019.  
  1020.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1021.     {
  1022.         while(Size-- > 0)
  1023.         {
  1024.             if(IsPrintable[c = *String++ & 0x7F])
  1025.             {
  1026.                     /* This character is associated with a
  1027.                      * special function (bell, xon, xoff, etc.).
  1028.                      */
  1029.  
  1030.                 if(SpecialTable[c])
  1031.                 {
  1032.                     if(Len)
  1033.                     {
  1034.                         (*ConDump)(ConTempBuffer,Len);
  1035.  
  1036.                         Len = 0;
  1037.                     }
  1038.  
  1039.                         /* Does this character start
  1040.                          * a control sequence?
  1041.                          */
  1042.  
  1043.                     if(InSequence = (*SpecialTable[c])(c))
  1044.                     {
  1045.                         while(Size-- > 0)
  1046.                         {
  1047.                             c = *String++ & 0x7F;
  1048.  
  1049.                             if(!(*AbortTable[c])(c))
  1050.                             {
  1051.                                 InSequence = FALSE;
  1052.  
  1053.                                 break;
  1054.                             }
  1055.                         }
  1056.                     }
  1057.                 }
  1058.                 else
  1059.                 {
  1060.                         /* Put the character into the buffer
  1061.                          * and flush it if necessary.
  1062.                          */
  1063.  
  1064.                     ConTempBuffer[Len] = c;
  1065.  
  1066.                     if(Len++ == 512)
  1067.                     {
  1068.                         (*ConDump)(ConTempBuffer,Len);
  1069.  
  1070.                         Len = 0;
  1071.                     }
  1072.                 }
  1073.             }
  1074.         }
  1075.     }
  1076.     else
  1077.     {
  1078.         while(Size-- > 0)
  1079.         {
  1080.             if(c = (*String++ & 0x7F))
  1081.             {
  1082.                     /* This character is associated with a
  1083.                      * special function (bell, xon, xoff, etc.).
  1084.                      */
  1085.  
  1086.                 if(SpecialTable[c])
  1087.                 {
  1088.                     if(Len)
  1089.                     {
  1090.                         (*ConDump)(ConTempBuffer,Len);
  1091.  
  1092.                         Len = 0;
  1093.                     }
  1094.  
  1095.                     if(InSequence = (*SpecialTable[c])(c))
  1096.                     {
  1097.                         while(Size-- > 0)
  1098.                         {
  1099.                             c = *String++ & 0x7F;
  1100.  
  1101.                             if(!(*AbortTable[c])(c))
  1102.                             {
  1103.                                 InSequence = FALSE;
  1104.  
  1105.                                 break;
  1106.                             }
  1107.                         }
  1108.                     }
  1109.                 }
  1110.                 else
  1111.                 {
  1112.                         /* Put the character into the buffer
  1113.                          * and flush it if necessary.
  1114.                          */
  1115.  
  1116.                     ConTempBuffer[Len] = c;
  1117.  
  1118.                     if(Len++ == 512)
  1119.                     {
  1120.                         (*ConDump)(ConTempBuffer,Len);
  1121.  
  1122.                         Len = 0;
  1123.                     }
  1124.                 }
  1125.             }
  1126.         }
  1127.     }
  1128.  
  1129.     if(Len)
  1130.         (*ConDump)(ConTempBuffer,Len);
  1131. }
  1132.  
  1133.     /* ConProcessData8(register STRPTR String,register LONG Size):
  1134.      *
  1135.      *    Process data, 8 bit flavour.
  1136.      */
  1137.  
  1138. VOID __regargs
  1139. ConProcessData8(register STRPTR String,register LONG Size)
  1140. {
  1141.     register LONG    Len = 0;
  1142.     register UBYTE    c;
  1143.  
  1144.     if(InSequence)
  1145.     {
  1146.         while(Size--)
  1147.         {
  1148.             c = *String++;
  1149.  
  1150.             if(!(*AbortTable[c])(c))
  1151.             {
  1152.                 InSequence = FALSE;
  1153.  
  1154.                 break;
  1155.             }
  1156.         }
  1157.     }
  1158.  
  1159.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1160.     {
  1161.         while(Size-- > 0)
  1162.         {
  1163.             if(IsPrintable[c = *String++])
  1164.             {
  1165.                 if(SpecialTable[c])
  1166.                 {
  1167.                     if(Len)
  1168.                     {
  1169.                         (*ConDump)(ConTempBuffer,Len);
  1170.  
  1171.                         Len = 0;
  1172.                     }
  1173.  
  1174.                     if(InSequence = (*SpecialTable[c])(c))
  1175.                     {
  1176.                         while(Size-- > 0)
  1177.                         {
  1178.                             c = *String++;
  1179.  
  1180.                             if(!(*AbortTable[c])(c))
  1181.                             {
  1182.                                 InSequence = FALSE;
  1183.  
  1184.                                 break;
  1185.                             }
  1186.                         }
  1187.                     }
  1188.                 }
  1189.                 else
  1190.                 {
  1191.                     ConTempBuffer[Len] = c;
  1192.  
  1193.                     if(Len++ == 512)
  1194.                     {
  1195.                         (*ConDump)(ConTempBuffer,Len);
  1196.  
  1197.                         Len = 0;
  1198.                     }
  1199.                 }
  1200.             }
  1201.         }
  1202.     }
  1203.     else
  1204.     {
  1205.         while(Size-- > 0)
  1206.         {
  1207.             if(c = *String++)
  1208.             {
  1209.                 if(SpecialTable[c])
  1210.                 {
  1211.                     if(Len)
  1212.                     {
  1213.                         (*ConDump)(ConTempBuffer,Len);
  1214.  
  1215.                         Len = 0;
  1216.                     }
  1217.  
  1218.                     if(InSequence = (*SpecialTable[c])(c))
  1219.                     {
  1220.                         while(Size-- > 0)
  1221.                         {
  1222.                             c = *String++;
  1223.  
  1224.                             if(!(*AbortTable[c])(c))
  1225.                             {
  1226.                                 InSequence = FALSE;
  1227.  
  1228.                                 break;
  1229.                             }
  1230.                         }
  1231.                     }
  1232.                 }
  1233.                 else
  1234.                 {
  1235.                     ConTempBuffer[Len] = c;
  1236.  
  1237.                     if(Len++ == 512)
  1238.                     {
  1239.                         (*ConDump)(ConTempBuffer,Len);
  1240.  
  1241.                         Len = 0;
  1242.                     }
  1243.                 }
  1244.             }
  1245.         }
  1246.     }
  1247.  
  1248.     if(Len)
  1249.         (*ConDump)(ConTempBuffer,Len);
  1250. }
  1251.  
  1252.     /* ConProcessDataHex7(register STRPTR String,register LONG Size):
  1253.      *
  1254.      *    Process data, hex mode flavour, seven bits.
  1255.      */
  1256.  
  1257. VOID __regargs
  1258. ConProcessDataHex7(register STRPTR String,register LONG Size)
  1259. {
  1260.     UBYTE    DummyBuffer[40],c;
  1261.     LONG    Fit,Spaces,Current;
  1262.  
  1263.         /* How many characters will fit into the line? */
  1264.  
  1265.     Fit    = (LastColumn + 1) / 4;
  1266.  
  1267.         /* Which position are we currently in? */
  1268.  
  1269.     Current    = CursorX / 3;
  1270.  
  1271.         /* Weird cursor position? */
  1272.  
  1273.     if(Current >= Fit || (CursorX % 3))
  1274.     {
  1275.         ConProcessData7("\r\n",2);
  1276.  
  1277.         Current = 0;
  1278.     }
  1279.  
  1280.         /* Check the font type. */
  1281.  
  1282.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1283.     {
  1284.         while(Size-- > 0)
  1285.         {
  1286.             c = (*String++) & 0x7F;
  1287.  
  1288.             Spaces = (Fit - Current) * 3 + Current - 3;
  1289.  
  1290.             if(c > ' ' && c < 127)
  1291.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1292.             else
  1293.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1294.  
  1295.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1296.  
  1297.             if(Current++ == Fit)
  1298.             {
  1299.                 Current = 0;
  1300.  
  1301.                 ConProcessData7("\r\n",2);
  1302.             }
  1303.         }
  1304.     }
  1305.     else
  1306.     {
  1307.         while(Size-- > 0)
  1308.         {
  1309.             c = (*String++) & 0x7F;
  1310.  
  1311.             Spaces = (Fit - Current) * 3 + Current - 3;
  1312.  
  1313.             if(c && c != ' ')
  1314.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1315.             else
  1316.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1317.  
  1318.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1319.  
  1320.             if(Current++ == Fit)
  1321.             {
  1322.                 Current = 0;
  1323.  
  1324.                 ConProcessData7("\r\n",2);
  1325.             }
  1326.         }
  1327.     }
  1328. }
  1329.  
  1330.     /* ConProcessDataHex8(register STRPTR String,register LONG Size):
  1331.      *
  1332.      *    Process data, hex mode flavour, eight bits.
  1333.      */
  1334.  
  1335. VOID __regargs
  1336. ConProcessDataHex8(register STRPTR String,register LONG Size)
  1337. {
  1338.     UBYTE    DummyBuffer[40],c;
  1339.     LONG    Fit,Spaces,Current;
  1340.  
  1341.         /* How many characters will fit into the line? */
  1342.  
  1343.     Fit    = (LastColumn + 1) / 4;
  1344.  
  1345.         /* Which position are we currently in? */
  1346.  
  1347.     Current    = CursorX / 3;
  1348.  
  1349.         /* Weird cursor position? */
  1350.  
  1351.     if(Current >= Fit || (CursorX % 3))
  1352.     {
  1353.         ConProcessData8("\r\n",2);
  1354.  
  1355.         Current = 0;
  1356.     }
  1357.  
  1358.         /* Check the font type. */
  1359.  
  1360.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1361.     {
  1362.         while(Size-- > 0)
  1363.         {
  1364.             c = *String++;
  1365.  
  1366.             Spaces = (Fit - Current) * 3 + Current - 3;
  1367.  
  1368.             if((c > ' ' && c < 127) || c > 160)
  1369.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1370.             else
  1371.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1372.  
  1373.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1374.  
  1375.             if(Current++ == Fit)
  1376.             {
  1377.                 Current = 0;
  1378.  
  1379.                 ConProcessData8("\r\n",2);
  1380.             }
  1381.         }
  1382.     }
  1383.     else
  1384.     {
  1385.         while(Size-- > 0)
  1386.         {
  1387.             c = *String++;
  1388.  
  1389.             Spaces = (Fit - Current) * 3 + Current - 3;
  1390.  
  1391.             if(c && c != ' ')
  1392.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1393.             else
  1394.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1395.  
  1396.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1397.  
  1398.             if(Current++ == Fit)
  1399.             {
  1400.                 Current = 0;
  1401.  
  1402.                 ConProcessData8("\r\n",2);
  1403.             }
  1404.         }
  1405.     }
  1406. }
  1407.  
  1408.     /* ConTransferHost(STRPTR Buffer,LONG Len):
  1409.      *
  1410.      *    Process data read from the serial line,
  1411.      *    special XPR flavour.
  1412.      */
  1413.  
  1414. VOID __regargs
  1415. ConTransferHost(STRPTR Buffer,LONG Len)
  1416. {
  1417.     Len = XProtocolHostMon(XprIO,Buffer,Len,Config -> SerialConfig -> SerialBufferSize);
  1418.  
  1419.     if(TransferWindow)
  1420.         TransferCleanup();
  1421.  
  1422.     if(Len)
  1423.         ConProcess(Buffer,Len);
  1424. }
  1425.  
  1426.     /* ConsoleCommand(STRPTR String):
  1427.      *
  1428.      *    Just like SerialCommand(), but addresses the local
  1429.      *    terminal side.
  1430.      */
  1431.  
  1432. VOID __regargs
  1433. ConsoleCommand(STRPTR String)
  1434. {
  1435.     STATIC UBYTE LocalBuffer[256];
  1436.  
  1437.     LONG    Count = 0,i,Len = strlen(String);
  1438.  
  1439.     BYTE    GotControl    = FALSE,
  1440.         GotEscape    = FALSE;
  1441.  
  1442.         /* Scan the string. */
  1443.  
  1444.     for(i = 0 ; i < Len ; i++)
  1445.     {
  1446.             /* We are looking for plain characters
  1447.              * and the control ('\') and escape
  1448.              * ('^') characters.
  1449.              */
  1450.  
  1451.         if(!GotControl && !GotEscape)
  1452.         {
  1453.                 /* Got a control character,
  1454.                  * the next byte will probably be
  1455.                  * a command sequence.
  1456.                  */
  1457.  
  1458.             if(String[i] == '\\')
  1459.             {
  1460.                 GotControl = TRUE;
  1461.  
  1462.                 continue;
  1463.             }
  1464.  
  1465.                 /* Got an escape character,
  1466.                  * the next byte will be some
  1467.                  * kind of control character
  1468.                  * (such as XON, XOF, bell, etc.).
  1469.                  */
  1470.  
  1471.             if(String[i] == '^')
  1472.             {
  1473.                 GotEscape = TRUE;
  1474.  
  1475.                 continue;
  1476.             }
  1477.  
  1478.                 /* This tells us to wait another
  1479.                  * second before continuing with
  1480.                  * the scanning.
  1481.                  */
  1482.  
  1483.             if(String[i] == '~')
  1484.                 continue;
  1485.  
  1486.                 /* Stuff the character into the
  1487.                  * buffer.
  1488.                  */
  1489.  
  1490.             LocalBuffer[Count++] = String[i];
  1491.         }
  1492.         else
  1493.         {
  1494.                 /* Convert the character to a control
  1495.                  * style character (^C, etc.).
  1496.                  */
  1497.  
  1498.             if(GotEscape)
  1499.             {
  1500.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
  1501.                     LocalBuffer[Count++] = ToUpper(String[i]) - '@';
  1502.                 else
  1503.                     LocalBuffer[Count++] = String[i];
  1504.  
  1505.                 GotEscape = FALSE;
  1506.             }
  1507.  
  1508.                 /* The next character represents a command. */
  1509.  
  1510.             if(GotControl)
  1511.             {
  1512.                 switch(ToUpper(String[i]))
  1513.                 {
  1514.                         /* Translate code. */
  1515.  
  1516.                     case '*':
  1517.  
  1518.                         i++;
  1519.  
  1520.                         while(i < Len && String[i] == ' ')
  1521.                             i++;
  1522.  
  1523.                         if(i < Len)
  1524.                         {
  1525.                             UBYTE DummyBuffer[5],j = 0,Char;
  1526.  
  1527.                             if(String[i] >= '0' && String[i] <= '9')
  1528.                             {
  1529.                                 while(j < 3 && i < Len)
  1530.                                 {
  1531.                                     Char = String[i++];
  1532.  
  1533.                                     if(Char >= '0' && Char <= '9')
  1534.                                         DummyBuffer[j++] = Char;
  1535.                                     else
  1536.                                     {
  1537.                                         i--;
  1538.  
  1539.                                         break;
  1540.                                     }
  1541.                                 }
  1542.                             }
  1543.                             else
  1544.                             {
  1545.                                 while(j < 4 && i < Len)
  1546.                                 {
  1547.                                     Char = ToLower(String[i++]);
  1548.  
  1549.                                     if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  1550.                                         DummyBuffer[j++] = Char;
  1551.                                     else
  1552.                                     {
  1553.                                         i--;
  1554.  
  1555.                                         break;
  1556.                                     }
  1557.                                 }
  1558.                             }
  1559.  
  1560.                             DummyBuffer[j] = 0;
  1561.  
  1562.                             LocalBuffer[Count++] = NameToCode(DummyBuffer);
  1563.                         }
  1564.  
  1565.                         i--;
  1566.  
  1567.                         break;
  1568.  
  1569.                         /* Execute an AmigaDOS command. */
  1570.  
  1571.                     case 'D':
  1572.  
  1573.                         return;
  1574.  
  1575.                         /* Execute an ARexx command. */
  1576.  
  1577.                     case 'A':
  1578.  
  1579.                         return;
  1580.  
  1581.                         /* Add the control character ('\'). */
  1582.  
  1583.                     case '\\':
  1584.  
  1585.                         LocalBuffer[Count++] = '\\';
  1586.                         break;
  1587.  
  1588.                         /* This is a backspace. */
  1589.  
  1590.                     case 'B':
  1591.  
  1592.                         LocalBuffer[Count++] = '\b';
  1593.                         break;
  1594.  
  1595.                         /* This is a form feed. */
  1596.  
  1597.                     case 'F':
  1598.  
  1599.                         LocalBuffer[Count++] = '\f';
  1600.                         break;
  1601.  
  1602.                         /* This is a line feed. */
  1603.  
  1604.                     case 'N':
  1605.  
  1606.                         LocalBuffer[Count++] = '\n';
  1607.                         break;
  1608.  
  1609.                         /* Send the current password. */
  1610.  
  1611.                     case 'P':
  1612.  
  1613.                         break;
  1614.  
  1615.                         /* This is a carriage return. */
  1616.  
  1617.                     case 'R':
  1618.  
  1619.                         LocalBuffer[Count++] = '\r';
  1620.                         break;
  1621.  
  1622.                         /* This is a tab. */
  1623.  
  1624.                     case 'T':
  1625.  
  1626.                         LocalBuffer[Count++] = '\t';
  1627.                         break;
  1628.  
  1629.                         /* Send the current user name. */
  1630.  
  1631.                     case 'U':
  1632.  
  1633.                         break;
  1634.  
  1635.                         /* Send a break across the serial line. */
  1636.  
  1637.                     case 'X':
  1638.  
  1639.                         break;
  1640.  
  1641.                         /* Feed the contents of the
  1642.                          * clipboard into the input
  1643.                          * stream.
  1644.                          */
  1645.  
  1646.                     case 'I':
  1647.  
  1648.                         if(Count)
  1649.                             ConProcess(LocalBuffer,Count);
  1650.  
  1651.                         Count = LoadClip(LocalBuffer,256);
  1652.  
  1653.                         break;
  1654.  
  1655.                         /* Send a string to the clipboard. */
  1656.  
  1657.                     case 'G':
  1658.  
  1659.                         if(String[i + 1])
  1660.                             SaveClip(&String[i + 1],strlen(&String[i + 1]));
  1661.  
  1662.                         return;
  1663.  
  1664.                         /* Produce the escape character. */
  1665.  
  1666.                     case 'E':
  1667.  
  1668.                         LocalBuffer[Count++] = ESC;
  1669.                         break;
  1670.  
  1671.                         /* Call a menu item. */
  1672.  
  1673.                     case 'C':
  1674.  
  1675.                         break;
  1676.  
  1677.                         /* Stuff the character into the buffer. */
  1678.  
  1679.                     default:
  1680.  
  1681.                         LocalBuffer[Count++] = String[i];
  1682.                         break;
  1683.                 }
  1684.  
  1685.                 GotControl = FALSE;
  1686.             }
  1687.         }
  1688.  
  1689.             /* If the buffer is full, release it. */
  1690.  
  1691.         if(Count == 256)
  1692.         {
  1693.             ConProcess(LocalBuffer,Count);
  1694.  
  1695.             Count = 0;
  1696.         }
  1697.     }
  1698.  
  1699.     if(Count)
  1700.         ConProcess(LocalBuffer,Count);
  1701. }
  1702.  
  1703.     /* ConProcess(STRPTR String,LONG Size):
  1704.      *
  1705.      *    Process the contents of a string to be sent to the
  1706.      *    console window.
  1707.      */
  1708.  
  1709. VOID __regargs
  1710. ConProcess(register STRPTR String,register LONG Size)
  1711. {
  1712.         /* If the capture filter happens to be disabled, write the
  1713.          * raw data.
  1714.          */
  1715.  
  1716.     if(!Config -> CaptureConfig -> CaptureFilterMode)
  1717.         CaptureToFile(String,Size);
  1718.  
  1719.         /* Feed the flow filter. */
  1720.  
  1721.     if(UseFlow)
  1722.     {
  1723.         if(Config -> SerialConfig -> StripBit8)
  1724.             FlowFilter(String,Size,0x7F);
  1725.         else
  1726.             FlowFilter(String,Size,0xFF);
  1727.     }
  1728.  
  1729.         /* In quiet mode no characters are echoed to the
  1730.          * console window, they are just passed through
  1731.          * the data flow filter. Usually, this mode is
  1732.          * enabled by the dial panel.
  1733.          */
  1734.  
  1735.     if(!Quiet)
  1736.         (*ConProcessData)(String,Size);
  1737. }
  1738.  
  1739.     /* ConWrites(STRPTR String,...):
  1740.      *
  1741.      *    Output a string to the console.
  1742.      */
  1743.  
  1744. VOID __stdargs
  1745. ConWrites(STRPTR String,...)
  1746. {
  1747.     va_list    VarArgs;
  1748.  
  1749.     if(Marking)
  1750.         DropMarker();
  1751.  
  1752.     ClearCursor();
  1753.  
  1754.     va_start(VarArgs,String);
  1755.     VSPrintf(SharedBuffer,String,VarArgs);
  1756.     va_end(VarArgs);
  1757.  
  1758.     ConProcess(SharedBuffer,strlen(SharedBuffer));
  1759.  
  1760.     DrawCursor();
  1761. }
  1762.  
  1763.     /* FlowInit():
  1764.      *
  1765.      *    Set up the data flow parser. The parser scans the serial
  1766.      *    output data for more or less interesting modem output
  1767.      *    (carrier lost, connect, etc.).
  1768.      */
  1769.  
  1770. VOID
  1771. FlowInit(BYTE FullReset)
  1772. {
  1773.     WORD i;
  1774.  
  1775.         /* Set up `NO CARRIER' message. */
  1776.  
  1777.     if(Config -> ModemConfig -> NoCarrier[0])
  1778.         SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
  1779.     else
  1780.         AttentionBuffers[SCAN_NOCARRIER][0] = 0;
  1781.  
  1782.         /* Set up ZRQINIT message. */
  1783.  
  1784.     strcpy(AttentionBuffers[SCAN_ZMODEM],"*\030B01");
  1785.  
  1786.         /* Set up `CONNECT' message. */
  1787.  
  1788.     strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
  1789.  
  1790.         /* Set up `VOICE' message. */
  1791.  
  1792.     if(Config -> ModemConfig -> Voice[0])
  1793.         SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
  1794.     else
  1795.         AttentionBuffers[SCAN_VOICE][0] = 0;
  1796.  
  1797.         /* Set up `RING' message. */
  1798.  
  1799.     if(Config -> ModemConfig -> Ring[0])
  1800.         SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
  1801.     else
  1802.         AttentionBuffers[SCAN_RING][0] = 0;
  1803.  
  1804.         /* Set up `BUSY' message. */
  1805.  
  1806.     if(Config -> ModemConfig -> Busy[0])
  1807.         SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
  1808.     else
  1809.         AttentionBuffers[SCAN_BUSY][0] = 0;
  1810.  
  1811.         /* Set up `NO DIALTONE' message. */
  1812.  
  1813.     if(Config -> ModemConfig -> NoDialTone[0])
  1814.         SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
  1815.     else
  1816.         AttentionBuffers[SCAN_NODIALTONE][0] = 0;
  1817.  
  1818.         /* Set up `OK' message. */
  1819.  
  1820.     if(Config -> ModemConfig -> Ok[0])
  1821.         SPrintf(AttentionBuffers[SCAN_OK],"%s\r",Config -> ModemConfig -> Ok);
  1822.     else
  1823.         AttentionBuffers[SCAN_OK][0] = 0;
  1824.  
  1825.         /* Set up `ERROR' message. */
  1826.  
  1827.     if(Config -> ModemConfig -> Error[0])
  1828.         SPrintf(AttentionBuffers[SCAN_ERROR],"%s\r",Config -> ModemConfig -> Error);
  1829.     else
  1830.         AttentionBuffers[SCAN_ERROR][0] = 0;
  1831.  
  1832.         /* Reset match counter. */
  1833.  
  1834.     FlowCount = 0;
  1835.  
  1836.         /* Reset indices. */
  1837.  
  1838.     memset(AttentionCount,0,sizeof(AttentionCount));
  1839.  
  1840.         /* Determine lengths. */
  1841.  
  1842.     for(i = 0 ; i < SCAN_COUNT ; i++)
  1843.         AttentionLength[i] = strlen(AttentionBuffers[i]);
  1844.  
  1845.     if(FullReset)
  1846.     {
  1847.             /* No, we are not yet looking for a baud rate. */
  1848.  
  1849.         BaudPending = FALSE;
  1850.  
  1851.             /* Reset the flags. */
  1852.  
  1853.         memset(&FlowInfo,FALSE,sizeof(struct FlowInfo));
  1854.     }
  1855.  
  1856.         /* Is it safe to disable the flow filter? */
  1857.  
  1858.     if(!FullCheck && Online && Config -> SerialConfig -> CheckCarrier && !Config -> MiscConfig -> AutoUpload)
  1859.         UseFlow = FALSE;
  1860.     else
  1861.         UseFlow = TRUE;
  1862.  
  1863.         /* Full data check is a lot slower than looking for
  1864.          * just a single sequence (such as the `CONNECT'
  1865.          * below). This mode is reserved for the dial panel.
  1866.          */
  1867.  
  1868.     if(FullCheck)
  1869.     {
  1870.         ScanStart    = 0;
  1871.         ScanEnd        = SCAN_COUNT - 1;
  1872.     }
  1873.     else
  1874.     {
  1875.         if(Online)
  1876.         {
  1877.             ScanStart = SCAN_NOCARRIER;
  1878.  
  1879.             if(UsesZModem)
  1880.                 ScanEnd = SCAN_ZMODEM;
  1881.             else
  1882.                 ScanEnd = SCAN_NOCARRIER;
  1883.         }
  1884.         else
  1885.         {
  1886.             if(UsesZModem)
  1887.                 ScanStart = SCAN_ZMODEM;
  1888.             else
  1889.                 ScanStart = SCAN_CONNECT;
  1890.  
  1891.             ScanEnd = SCAN_RING;
  1892.         }
  1893.     }
  1894. }
  1895.  
  1896.     /* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
  1897.      *
  1898.      *    Text output, if necessary switching from gfx font
  1899.      *    to current default font.
  1900.      */
  1901.  
  1902. VOID __regargs
  1903. GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
  1904. {
  1905.     BYTE TextMode;
  1906.     LONG SameMode;
  1907.  
  1908.         /* Determine current text rendering mode. */
  1909.  
  1910.     if(GfxTable[Buffer[0]] == MODE_GFX)
  1911.         TextMode = MODE_GFX;
  1912.     else
  1913.     {
  1914.         TextMode = MODE_STANDARD;
  1915.  
  1916.         SetFont(RPort,TextFont);
  1917.     }
  1918.  
  1919.         /* Reset number of characters in common mode. */
  1920.  
  1921.     SameMode = 0;
  1922.  
  1923.         /* Scan until all input is processed. */
  1924.  
  1925.     FOREVER
  1926.     {
  1927.             /* Scan for characters in the current mode. */
  1928.  
  1929.         while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
  1930.             SameMode++;
  1931.  
  1932.             /* Output the text found. */
  1933.  
  1934.         Text(RPort,Buffer,SameMode);
  1935.  
  1936.             /* Decrement number of remaining bytes. */
  1937.  
  1938.         Length -= SameMode;
  1939.  
  1940.             /* Anything left? */
  1941.  
  1942.         if(Length)
  1943.         {
  1944.                 /* Skip to next character. */
  1945.  
  1946.             Buffer        += SameMode;
  1947.             SameMode     = 0;
  1948.  
  1949.                 /* Change text output mode. */
  1950.  
  1951.             if(TextMode == MODE_GFX)
  1952.             {
  1953.                 SetFont(RPort,TextFont);
  1954.  
  1955.                 TextMode = MODE_STANDARD;
  1956.             }
  1957.             else
  1958.             {
  1959.                 SetFont(RPort,GFX);
  1960.  
  1961.                 TextMode = MODE_GFX;
  1962.             }
  1963.         }
  1964.         else
  1965.             break;
  1966.     }
  1967.  
  1968.         /* Reset font type. */
  1969.  
  1970.     if(TextMode == MODE_STANDARD)
  1971.         SetFont(RPort,GFX);
  1972. }
  1973.  
  1974.     /* ConvertKey():
  1975.      *
  1976.      *    The actual key conversion routine.
  1977.      */
  1978.  
  1979. STATIC LONG __inline
  1980. ConvertKey(ULONG Qualifier,UWORD Code,APTR IAddress,STRPTR Buffer,LONG Len)
  1981. {
  1982.     LONG Actual;
  1983.  
  1984.         /* Fill in the defaults. */
  1985.  
  1986.     FakeInputEvent -> ie_Code        = Code;
  1987.     FakeInputEvent -> ie_Qualifier        = Qualifier;
  1988.     FakeInputEvent -> ie_position . ie_addr    = *((APTR *)IAddress);
  1989.  
  1990.         /* Clear the buffer (sortof). */
  1991.  
  1992.     Buffer[0] = 0;
  1993.  
  1994.         /* Convert the codes. */
  1995.  
  1996.     if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
  1997.         return(Actual);
  1998.     else
  1999.         return(0);
  2000. }
  2001.  
  2002.     /* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
  2003.      *
  2004.      *    Convert a raw key information according to the
  2005.      *    current keymap settings.
  2006.      */
  2007.  
  2008. UBYTE __regargs
  2009. KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
  2010. {
  2011.     if(Buffer)
  2012.         Buffer[0] = 0;
  2013.  
  2014.     if(Len)
  2015.         *Len = 0;
  2016.  
  2017.         /* Key was pressed, not released. */
  2018.  
  2019.     if(Massage -> Class == IDCMP_RAWKEY && !(Massage -> Code & IECODE_UP_PREFIX))
  2020.     {
  2021.             /* These are the sequences mapped to special
  2022.              * control keys (cursor keys, function keys,
  2023.              * the help key).
  2024.              */
  2025.  
  2026.         STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
  2027.         {
  2028.             (STRPTR)"A",    CUP,
  2029.             (STRPTR)"B",    CDN,
  2030.             (STRPTR)"C",    CFW,
  2031.             (STRPTR)"D",    CBK,
  2032.  
  2033.             (STRPTR)"?~",    HLP,
  2034.  
  2035.             (STRPTR)"0~",    FN1,
  2036.             (STRPTR)"1~",    FN2,
  2037.             (STRPTR)"2~",    FN3,
  2038.             (STRPTR)"3~",    FN4,
  2039.             (STRPTR)"4~",    FN5,
  2040.             (STRPTR)"5~",    FN6,
  2041.             (STRPTR)"6~",    FN7,
  2042.             (STRPTR)"7~",    FN8,
  2043.             (STRPTR)"8~",    FN9,
  2044.             (STRPTR)"9~",    F10
  2045.         };
  2046.  
  2047.         STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
  2048.  
  2049.         UBYTE    ConvertBuffer[257];
  2050.         ULONG    Qualifier;
  2051.         LONG    Actual;
  2052.  
  2053.             /* If it's a function or cursor key, clear the qualifier. */
  2054.  
  2055.         if(Massage -> Code >= CURSOR_UP_CODE && Massage -> Code <= F10_CODE)
  2056.             Qualifier = NULL;
  2057.         else
  2058.         {
  2059.             Qualifier = Massage -> Qualifier;
  2060.  
  2061.                 /* Does it have a numeric keypad qualifier set? */
  2062.  
  2063.             if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
  2064.             {
  2065.                     /* Look at the vanilla result. */
  2066.  
  2067.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Massage -> Code,Massage -> IAddress,ConvertBuffer,1))
  2068.                 {
  2069.                     STRPTR String;
  2070.  
  2071.                         /* Take a look at the results. */
  2072.  
  2073.                     switch(ConvertBuffer[0])
  2074.                     {
  2075.                         case '[':
  2076.  
  2077.                             String = "\033OP";
  2078.                             break;
  2079.  
  2080.                         case ']':
  2081.  
  2082.                             String = "\033OQ";
  2083.                             break;
  2084.  
  2085.                         case '/':
  2086.  
  2087.                             String = "\033OR";
  2088.                             break;
  2089.  
  2090.                         case '*':
  2091.  
  2092.                             String = "\033OS";
  2093.                             break;
  2094.  
  2095.                         default:
  2096.  
  2097.                             String = NULL;
  2098.                             break;
  2099.                     }
  2100.  
  2101.                         /* Return the PFx key code. */
  2102.  
  2103.                     if(String)
  2104.                     {
  2105.                         if(Buffer)
  2106.                             memcpy(Buffer,String,3);
  2107.  
  2108.                         if(Len)
  2109.                             *Len = 3;
  2110.  
  2111.                         return('\033');
  2112.                     }
  2113.                 }
  2114.             }
  2115.  
  2116.                 /* Does it have a shift qualifier set? */
  2117.  
  2118.             if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  2119.             {
  2120.                     /* Do the conversion... */
  2121.  
  2122.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Massage -> Code,Massage -> IAddress,ConvertBuffer,1))
  2123.                 {
  2124.                         /* Did it produce a tab key? If so, transfer
  2125.                          * Esc tab instead.
  2126.                          */
  2127.  
  2128.                     if(ConvertBuffer[0] == '\t')
  2129.                     {
  2130.                         if(Len)
  2131.                             *Len = 2;
  2132.  
  2133.                         if(Buffer)
  2134.                             memcpy(Buffer,"\033\t",2);
  2135.  
  2136.                         return('\033');
  2137.                     }
  2138.                 }
  2139.             }
  2140.  
  2141.                 /* Does it have the control qualifier set? */
  2142.  
  2143.             if(Qualifier & IEQUALIFIER_CONTROL)
  2144.             {
  2145.                     /* Do the conversion... */
  2146.  
  2147.                 if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Massage -> Code,Massage -> IAddress,ConvertBuffer,1))
  2148.                 {
  2149.                         /* Did it produce a space or an `at' sign? */
  2150.  
  2151.                     if(ConvertBuffer[0] == ' ' || ConvertBuffer[0] == '@')
  2152.                     {
  2153.                             /* If so, produce a nul instead. */
  2154.  
  2155.                         if(Len)
  2156.                             *Len = 1;
  2157.  
  2158.                         if(Buffer)
  2159.                             Buffer[0] = 0;
  2160.  
  2161.                         return(0);
  2162.                     }
  2163.                 }
  2164.             }
  2165.         }
  2166.  
  2167.             /* Do the final conversion... */
  2168.  
  2169.         if(Actual = ConvertKey(Qualifier,Massage -> Code,Massage -> IAddress,ConvertBuffer,256))
  2170.         {
  2171.                 /* Did we get anything in return? */
  2172.  
  2173.             if(ConvertBuffer[0])
  2174.             {
  2175.                     /* Are we to swap the backspace and
  2176.                      * delete keys?
  2177.                      */
  2178.  
  2179.                 if(Config -> EmulationConfig -> SwapBSDelete)
  2180.                 {
  2181.                     register WORD i;
  2182.  
  2183.                     for(i = 0 ; i < Actual ; i++)
  2184.                     {
  2185.                         if(ConvertBuffer[i] == BKS)
  2186.                             ConvertBuffer[i] = DEL;
  2187.                         else
  2188.                         {
  2189.                             if(ConvertBuffer[i] == DEL)
  2190.                                 ConvertBuffer[i] = BKS;
  2191.                         }
  2192.                     }
  2193.                 }
  2194.  
  2195.                     /* Translated sequence starts
  2196.                      * with a CSI, let's have a look
  2197.                      * at the associated control
  2198.                      * key.
  2199.                      */
  2200.  
  2201.                 if(ConvertBuffer[0] == CSI)
  2202.                 {
  2203.                     register WORD i;
  2204.  
  2205.                     for(i = 0 ; i < sizeof(SeqLens) ; i++)
  2206.                     {
  2207.                             /* Does it match? */
  2208.  
  2209.                         if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
  2210.                         {
  2211.                                 /* Store the length. */
  2212.  
  2213.                             if(Len)
  2214.                                 *Len = 1;
  2215.  
  2216.                                 /* Store the result. */
  2217.  
  2218.                             if(Buffer)
  2219.                             {
  2220.                                 Buffer[0] = ConversionTable[i] . Result;
  2221.                                 Buffer[1] = 0;
  2222.                             }
  2223.  
  2224.                             return(ConversionTable[i] . Result);
  2225.                         }
  2226.                     }
  2227.                 }
  2228.  
  2229.                     /* Store the number of characters converted. */
  2230.  
  2231.                 if(Len)
  2232.                     *Len = Actual;
  2233.  
  2234.                     /* Store the converted characters. */
  2235.  
  2236.                 if(Buffer)
  2237.                     memcpy(Buffer,ConvertBuffer,Actual);
  2238.  
  2239.                 return(ConvertBuffer[0]);
  2240.             }
  2241.         }
  2242.     }
  2243.  
  2244.     return(0);
  2245. }
  2246.  
  2247.     /* DoBackspace():
  2248.      *
  2249.      *    Special function: perform backspace.
  2250.      */
  2251.  
  2252. BYTE __regargs
  2253. DoBackspace()
  2254. {
  2255.     Capture("\b",1);
  2256.  
  2257.     if(CursorX)
  2258.     {
  2259.         CursorX--;
  2260.  
  2261.             /* If destructive, shift the remaining line
  2262.              * one character to the right.
  2263.              */
  2264.  
  2265.         if(Config -> EmulationConfig -> DestructiveBackspace)
  2266.         {
  2267.             WORD DeltaX,MinX;
  2268.  
  2269.             BackupRender();
  2270.  
  2271.             RasterEraseCharacters(1);
  2272.  
  2273.             if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
  2274.             {
  2275.                 if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2276.                 {
  2277.                     DeltaX    = TextFontWidth;
  2278.                     MinX    = MUL_X(CursorX);
  2279.                 }
  2280.                 else
  2281.                 {
  2282.                     DeltaX    = TextFontWidth / 2;
  2283.                     MinX    = MUL_X(CursorX) / 2;
  2284.                 }
  2285.             }
  2286.             else
  2287.             {
  2288.                 if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2289.                 {
  2290.                     DeltaX    = TextFontWidth / 2;
  2291.                     MinX    = MUL_X(CursorX) / 2;
  2292.                 }
  2293.                 else
  2294.                 {
  2295.                     DeltaX    = TextFontWidth;
  2296.                     MinX    = MUL_X(CursorX);
  2297.                 }
  2298.             }
  2299.  
  2300.             ScrollLineEraseCharacters(1);
  2301.  
  2302.             ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2303.  
  2304.             BackupRender();
  2305.         }
  2306.  
  2307.         ClipBlitCursor(FALSE,TRUE);
  2308.     }
  2309.  
  2310.     return(FALSE);
  2311. }
  2312.  
  2313.     /* DoBeep():
  2314.      *
  2315.      *    The real interface to the beep routine.
  2316.      */
  2317.  
  2318. BYTE __regargs
  2319. DoBeep()
  2320. {
  2321.         /* Handle the visual part. */
  2322.  
  2323.     if(Config -> TerminalConfig -> BellMode != BELL_AUDIBLE)
  2324.     {
  2325.         if(StatusProcess)
  2326.             Signal(StatusProcess,SIG_BELL);
  2327.     }
  2328.  
  2329.         /* Let it beep. */
  2330.  
  2331.     if(Config -> TerminalConfig -> BellMode == BELL_AUDIBLE || Config -> TerminalConfig -> BellMode == BELL_BOTH)
  2332.         SoundPlay(SOUND_BELL);
  2333.  
  2334.         /* Capture the bell. */
  2335.  
  2336.     if(Config -> CaptureConfig -> CaptureFilterMode == FILTER_NONE)
  2337.         Capture("\a",1);
  2338.  
  2339.     return(FALSE);
  2340. }
  2341.  
  2342.     /* DoxON():
  2343.      *
  2344.      *    Perform XON (stop data flow).
  2345.      */
  2346.  
  2347. BYTE __regargs
  2348. DoxON()
  2349. {
  2350.     if(Config -> SerialConfig -> xONxOFF)
  2351.         Status = STATUS_HOLDING;
  2352.  
  2353.     return(FALSE);
  2354. }
  2355.  
  2356.     /* DoLF():
  2357.      *
  2358.      *    Special function: perform line feed.
  2359.      */
  2360.  
  2361. BYTE __regargs
  2362. DoLF()
  2363. {
  2364.     if(Config -> TerminalConfig -> ReceiveLF == LF_ASLFCR)
  2365.     {
  2366.         CursorX = 0;
  2367.  
  2368.         DownLine();
  2369.  
  2370.         ClipBlitCursor(FALSE,TRUE);
  2371.  
  2372.         Capture("\n",1);
  2373.     }
  2374.     else
  2375.     {
  2376.         if(Config -> TerminalConfig -> ReceiveLF == LF_ASLF)
  2377.         {
  2378.             DownLine();
  2379.  
  2380.             ClipBlitCursor(FALSE,TRUE);
  2381.         }
  2382.     }
  2383.  
  2384.     return(FALSE);
  2385. }
  2386.  
  2387.     /* DoShiftIn():
  2388.      *
  2389.      *    Special function: Shift into graphics mode
  2390.      */
  2391.  
  2392. BYTE __regargs
  2393. DoShiftIn()
  2394. {
  2395.     if(CharMode[1] == TABLE_GFX && GFX)
  2396.         CurrentFont = GFX;
  2397.  
  2398.     if(CharMode[1] == TABLE_ASCII)
  2399.         CurrentFont = TextFont;
  2400.  
  2401.     SetFont(RPort,CurrentFont);
  2402.  
  2403.     ConOutputUpdate();
  2404.  
  2405.     Charset = 1;
  2406.  
  2407.     return(FALSE);
  2408. }
  2409.  
  2410.     /* DoShiftOut():
  2411.      *
  2412.      *    Special function: Shift out of graphics mode
  2413.      */
  2414.  
  2415. BYTE __regargs
  2416. DoShiftOut()
  2417. {
  2418.     if(CharMode[0] == TABLE_GFX && GFX)
  2419.         CurrentFont = GFX;
  2420.  
  2421.     if(CharMode[0] == TABLE_ASCII)
  2422.         CurrentFont = TextFont;
  2423.  
  2424.     SetFont(RPort,CurrentFont);
  2425.  
  2426.     ConOutputUpdate();
  2427.  
  2428.     Charset = 0;
  2429.  
  2430.     return(FALSE);
  2431. }
  2432.  
  2433.     /* DoCR_LF():
  2434.      *
  2435.      *    Special function: perform carriage return and line feed.
  2436.      */
  2437.  
  2438. BYTE __regargs
  2439. DoCR_LF()
  2440. {
  2441.     CursorX = 0;
  2442.  
  2443.     DownLine();
  2444.  
  2445.     ClipBlitCursor(FALSE,TRUE);
  2446.  
  2447.     Capture("\n",1);
  2448.  
  2449.     return(FALSE);
  2450. }
  2451.  
  2452.     /* DoFF():
  2453.      *
  2454.      *    Special function: perform form feed.
  2455.      */
  2456.  
  2457. BYTE __regargs
  2458. DoFF()
  2459. {
  2460.     if(Config -> EmulationConfig -> NewLineMode)
  2461.     {
  2462.         CursorX = 0;
  2463.  
  2464.         DoCR_LF();
  2465.     }
  2466.     else
  2467.     {
  2468.         EraseScreen("2");
  2469.  
  2470.         CursorX = CursorY = 0;
  2471.  
  2472.         ClipBlitCursor(FALSE,TRUE);
  2473.  
  2474.         ConFontScaleUpdate();
  2475.  
  2476.         Capture("\n",1);
  2477.     }
  2478.  
  2479.     return(FALSE);
  2480. }
  2481.  
  2482.     /* DoLF_FF_VT():
  2483.      *
  2484.      *    Special function: handle line feed, form feed and vertical
  2485.      *    tab.
  2486.      */
  2487.  
  2488. BYTE __regargs
  2489. DoLF_FF_VT()
  2490. {
  2491.     if(Config -> EmulationConfig -> NewLineMode)
  2492.         DoCR_LF();
  2493.     else
  2494.         DoLF();
  2495.  
  2496.     return(FALSE);
  2497. }
  2498.  
  2499.     /* DoCR():
  2500.      *
  2501.      *    Special function: handle carriage return.
  2502.      */
  2503.  
  2504. BYTE __regargs
  2505. DoCR()
  2506. {
  2507.     if(Config -> EmulationConfig -> NewLineMode || Config -> TerminalConfig -> ReceiveCR == CR_ASCRLF)
  2508.         DoCR_LF();
  2509.     else
  2510.     {
  2511.         if(Config -> TerminalConfig -> ReceiveCR == CR_ASCR)
  2512.         {
  2513.             CursorX = 0;
  2514.  
  2515.             ClipBlitCursor(FALSE,TRUE);
  2516.  
  2517.             Capture("\n",1);
  2518.         }
  2519.     }
  2520.  
  2521.     return(FALSE);
  2522. }
  2523.  
  2524.     /* DoTab():
  2525.      *
  2526.      *    Special function: handle tab, move cursor to next
  2527.      *    tab stop.
  2528.      */
  2529.  
  2530. BYTE __regargs
  2531. DoTab()
  2532. {
  2533.     WORD Column;
  2534.  
  2535.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2536.         Column = LastColumn;
  2537.     else
  2538.         Column = ((LastColumn + 1) / 2) - 1;
  2539.  
  2540.     if(Config -> EmulationConfig -> LineWrap)
  2541.     {
  2542.         if(CursorX >= LastColumn)
  2543.         {
  2544.             CursorX = 0;
  2545.  
  2546.             DownLine();
  2547.         }
  2548.         else
  2549.         {
  2550.             while(CursorX < Column)
  2551.             {
  2552.                 CursorX++;
  2553.  
  2554.                 if(TabStops[CursorX])
  2555.                     break;
  2556.             }
  2557.         }
  2558.     }
  2559.     else
  2560.     {
  2561.         while(CursorX < Column)
  2562.         {
  2563.             CursorX++;
  2564.  
  2565.             if(TabStops[CursorX])
  2566.                 break;
  2567.         }
  2568.     }
  2569.  
  2570.     ClipBlitCursor(FALSE,TRUE);
  2571.  
  2572.     Capture("\t",1);
  2573.  
  2574.     return(FALSE);
  2575. }
  2576.  
  2577.     /* DoEnq():
  2578.      *
  2579.      *    Special function: send answerback message.
  2580.      */
  2581.  
  2582. BYTE __regargs
  2583. DoEnq()
  2584. {
  2585.     if(Config -> EmulationConfig -> AnswerBack[0])
  2586.         SerialCommand(Config -> EmulationConfig -> AnswerBack);
  2587.  
  2588.     return(FALSE);
  2589. }
  2590.  
  2591.     /* DoEsc():
  2592.      *
  2593.      *    Start new control sequence.
  2594.      */
  2595.  
  2596. BYTE __regargs
  2597. DoEsc()
  2598. {
  2599.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2600.         (* ConDump)("^",1);
  2601.  
  2602.     return(TRUE);
  2603. }
  2604.  
  2605.     /* DoCsi():
  2606.      *
  2607.      *    Start new control sequence.
  2608.      */
  2609.  
  2610. BYTE __regargs
  2611. DoCsi()
  2612. {
  2613.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2614.         (* ConDump)("^[",2);
  2615.  
  2616.     ParseCode('[');
  2617.  
  2618.     return(TRUE);
  2619. }
  2620.  
  2621.     /* DoNewEsc(UBYTE Char):
  2622.      *
  2623.      *    Start new control sequence.
  2624.      */
  2625.  
  2626. BYTE __regargs
  2627. DoNewEsc(UBYTE Char)
  2628. {
  2629.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2630.         (* ConDump)("^",1);
  2631.  
  2632.     DoCancel();
  2633.  
  2634.     return(TRUE);
  2635. }
  2636.  
  2637.     /* DoNewCsi(UBYTE Char):
  2638.      *
  2639.      *    Start new control sequence.
  2640.      */
  2641.  
  2642. BYTE __regargs
  2643. DoNewCsi(UBYTE Char)
  2644. {
  2645.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2646.         (* ConDump)("^[",2);
  2647.  
  2648.     DoCancel();
  2649.  
  2650.     return(ParseCode('['));
  2651. }
  2652.