home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / comm / term / term41source.lha / Extras / Source / term-Source.lha / termConsole.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-17  |  53.4 KB  |  3,353 lines

  1. /*
  2. **    termConsole.c
  3. **
  4. **    High-level terminal console routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  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 __far    AttentionCount[SCAN_COUNT],
  22.             AttentionLength[SCAN_COUNT],
  23.             FlowCount;
  24.  
  25.     /* Temporary console working buffer. */
  26.  
  27. STATIC UBYTE __far    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.     /* TrapFilter(register STRPTR Data,register LONG Size):
  124.      *
  125.      *    Handle the trap list, similar to FlowFilter().
  126.      */
  127.  
  128. STATIC VOID __regargs
  129. TrapFilter(register STRPTR Data,register LONG Size)
  130. {
  131.     STATIC LONG WaitCount = 0;
  132.  
  133.     struct List    *List = (struct List *)&GenericListTable[GLIST_TRAP] -> ListHeader;
  134.     struct TrapNode    *Node;
  135.  
  136.     register UBYTE c,Mask;
  137.  
  138.     ObtainSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  139.  
  140.     if(Config -> SerialConfig -> StripBit8)
  141.         Mask = 0x7F;
  142.     else
  143.         Mask = 0xFF;
  144.  
  145.     do
  146.     {
  147.         register BOOLEAN MatchMade;
  148.  
  149.         c = (*Data++) & Mask;
  150.  
  151.         do
  152.         {
  153.             MatchMade = FALSE;
  154.  
  155.             for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  156.             {
  157.                 if(Node -> Count == WaitCount)
  158.                 {
  159.                     if(c == (Node -> Sequence[WaitCount] & Mask))
  160.                     {
  161.                         MatchMade = TRUE;
  162.  
  163.                         if(++Node -> Count == Node -> SequenceLen)
  164.                         {
  165.                             struct DataMsg *Msg;
  166.  
  167.                             Node -> Count = 0;
  168.  
  169.                             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + strlen(Node -> Command) + 1))
  170.                             {
  171.                                 Msg -> Type = DATAMSGTYPE_SERIALCOMMAND;
  172.                                 Msg -> Data = (STRPTR)(Msg + 1);
  173.  
  174.                                 strcpy(Msg -> Data,Node -> Command);
  175.  
  176.                                 PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  177.                             }
  178.                         }
  179.                     }
  180.                 }
  181.             }
  182.  
  183.             if(MatchMade)
  184.                 WaitCount++;
  185.             else
  186.             {
  187.                 if(WaitCount)
  188.                 {
  189.                     WaitCount = 0;
  190.  
  191.                     for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  192.                         Node -> Count = 0;
  193.                 }
  194.                 else
  195.                     break;
  196.             }
  197.         }
  198.         while(!WaitCount);
  199.     }
  200.     while(--Size);
  201.  
  202.     ReleaseSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  203. }
  204.  
  205.     /* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
  206.      *
  207.      *    Data flow filter.
  208.      */
  209.  
  210. STATIC VOID __regargs
  211. FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
  212. {
  213.     register UBYTE c;
  214.  
  215.         /* Run until done. */
  216.  
  217.     do
  218.     {
  219.         if(c = (*Data++ & Mask))
  220.         {
  221.  
  222.                 /* We already got a `CONNECT',
  223.                  * Continue scanning the serial output
  224.                  * data for the actual baud rate.
  225.                  */
  226.  
  227.             if(BaudPending)
  228.             {
  229.                 if(c < ' ')
  230.                 {
  231.                     while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  232.                         BaudCount--;
  233.  
  234.                     BaudBuffer[BaudCount] = 0;
  235.  
  236.                     FlowInfo . Connect = TRUE;
  237.                     FlowInfo . Changed = TRUE;
  238.  
  239.                     BaudPending = FALSE;
  240.  
  241.                     DTERate = GetBaudRate(BaudBuffer);
  242.  
  243.                     if(Quiet && Size > 1)
  244.                     {
  245.                         DataHold = Data;
  246.                         DataSize = Size - 1;
  247.                     }
  248.                 }
  249.                 else
  250.                 {
  251.                     if(BaudCount || c != ' ')
  252.                     {
  253.                         BaudBuffer[BaudCount++] = c;
  254.  
  255.                         if(BaudCount == 79)
  256.                         {
  257.                             while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  258.                                 BaudCount--;
  259.  
  260.                             BaudBuffer[BaudCount] = 0;
  261.  
  262.                             FlowInfo . Connect = TRUE;
  263.                             FlowInfo . Changed = TRUE;
  264.  
  265.                             BaudPending = FALSE;
  266.  
  267.                             DTERate = GetBaudRate(BaudBuffer);
  268.  
  269.                             if(Quiet && Size > 1)
  270.                             {
  271.                                 DataHold = Data;
  272.                                 DataSize = Size - 1;
  273.                             }
  274.                         }
  275.                     }
  276.                 }
  277.             }
  278.             else
  279.             {
  280.                 register BYTE MatchMade;
  281.                 register WORD i;
  282.  
  283.                 do
  284.                 {
  285.                     MatchMade = FALSE;
  286.  
  287.                         /* Scan all ID strings for matches. */
  288.  
  289.                     for(i = ScanStart ; i <= ScanEnd ; i++)
  290.                     {
  291.                             /* This sequence is a likely
  292.                              * match.
  293.                              */
  294.  
  295.                         if(AttentionCount[i] == FlowCount)
  296.                         {
  297.                                 /* Does the character
  298.                                  * fit into the sequence?
  299.                                  */
  300.  
  301.                             if(c == AttentionBuffers[i][FlowCount] & Mask)
  302.                             {
  303.                                 MatchMade = TRUE;
  304.  
  305.                                     /* Did we hit the
  306.                                      * last character
  307.                                      * in the sequence?
  308.                                      */
  309.  
  310.                                 if(++AttentionCount[i] == AttentionLength[i])
  311.                                 {
  312.                                         /* We've got a valid
  313.                                          * sequence, now look
  314.                                          * which flags to change.
  315.                                          */
  316.  
  317.                                     switch(i)
  318.                                     {
  319.                                             /* We got a `no carrier' message. */
  320.  
  321.                                         case SCAN_NOCARRIER:
  322.  
  323.                                             if(!FlowInfo . NoCarrier)
  324.                                             {
  325.                                                 FlowInfo . NoCarrier    = TRUE;
  326.                                                 FlowInfo . Changed    = TRUE;
  327.                                             }
  328.  
  329.                                             break;
  330.  
  331.                                             /* Got another call. */
  332.  
  333.                                         case SCAN_RING:
  334.  
  335.                                             if(!FlowInfo . Ring)
  336.                                             {
  337.                                                 FlowInfo . Ring        = TRUE;
  338.                                                 FlowInfo . Changed    = TRUE;
  339.                                             }
  340.  
  341.                                             break;
  342.  
  343.                                             /* Got a voice call. */
  344.  
  345.                                         case SCAN_VOICE:
  346.  
  347.                                             if(!FlowInfo . Voice)
  348.                                             {
  349.                                                 FlowInfo . Voice    = TRUE;
  350.                                                 FlowInfo . Changed    = TRUE;
  351.                                             }
  352.  
  353.                                             break;
  354.  
  355.                                             /* Got a connect message. */
  356.  
  357.                                         case SCAN_CONNECT:
  358.  
  359.                                             ObtainSemaphore(&OnlineSemaphore);
  360.  
  361.                                             if(!Online)
  362.                                             {
  363.                                                 BaudBuffer[0]    = 0;
  364.  
  365.                                                 BaudPending    = TRUE;
  366.                                                 BaudCount    = 0;
  367.                                             }
  368.  
  369.                                             ReleaseSemaphore(&OnlineSemaphore);
  370.  
  371.                                             break;
  372.  
  373.                                             /* Got the ZModem inquiry sequence. */
  374.  
  375.                                         case SCAN_ZMODEM:
  376.  
  377.                                             if(!FlowInfo . ZModemUpload)
  378.                                             {
  379.                                                 FlowInfo . ZModemUpload    = TRUE;
  380.                                                 FlowInfo . Changed    = TRUE;
  381.                                             }
  382.  
  383.                                             break;
  384.  
  385.                                             /* Line is busy. */
  386.  
  387.                                         case SCAN_BUSY:
  388.  
  389.                                             if(!FlowInfo . Busy)
  390.                                             {
  391.                                                 FlowInfo . Busy        = TRUE;
  392.                                                 FlowInfo . Changed    = TRUE;
  393.                                             }
  394.  
  395.                                             break;
  396.  
  397.                                         case SCAN_NODIALTONE:
  398.  
  399.                                             if(!FlowInfo . NoDialTone)
  400.                                             {
  401.                                                 FlowInfo . NoDialTone    = TRUE;
  402.                                                 FlowInfo . Changed    = TRUE;
  403.                                             }
  404.  
  405.                                             break;
  406.                                     }
  407.                                 }
  408.                             }
  409.                         }
  410.                     }
  411.  
  412.                     if(MatchMade)
  413.                         FlowCount++;
  414.                     else
  415.                     {
  416.                         if(FlowCount)
  417.                         {
  418.                             FlowCount = 0;
  419.  
  420.                             memset(AttentionCount,0,sizeof(AttentionCount));
  421.                         }
  422.                         else
  423.                             break;
  424.                     }
  425.                 }
  426.                 while(!FlowCount);
  427.             }
  428.         }
  429.     }
  430.     while(--Size);
  431. }
  432.  
  433.     /* StripSequence():
  434.      *
  435.      *    Strips a string from ESC and CSI introduced control
  436.      *    sequences.
  437.      */
  438.  
  439. STATIC LONG __regargs
  440. StripSequence(STRPTR Src,STRPTR Dst,LONG Length)
  441. {
  442.     STATIC BYTE    HasESC    = FALSE,
  443.             HasCSI    = FALSE;
  444.     LONG        Size    = 0;
  445.  
  446.     while(Length--)
  447.     {
  448.         if(HasESC)
  449.         {
  450.             if(*Src == '[')
  451.             {
  452.                 HasESC = FALSE;
  453.                 HasCSI = TRUE;
  454.             }
  455.             else
  456.             {
  457.                 if(*Src >= '0')
  458.                     HasESC = FALSE;
  459.             }
  460.  
  461.             Src++;
  462.  
  463.             continue;
  464.         }
  465.  
  466.         if(HasCSI)
  467.         {
  468.             if(*Src >= '@')
  469.                 HasCSI = FALSE;
  470.  
  471.             Src++;
  472.  
  473.             continue;
  474.         }
  475.  
  476.         switch(*Src)
  477.         {
  478.             case CAN:
  479.             case SUB:
  480.  
  481.                 HasESC = HasCSI = FALSE;
  482.                 break;
  483.  
  484.             case '\r':
  485.  
  486.                 break;
  487.  
  488.             case ESC:
  489.  
  490.                 HasESC = TRUE;
  491.                 break;
  492.  
  493.             case CSI:
  494.  
  495.                 HasCSI = TRUE;
  496.                 break;
  497.  
  498.             default:
  499.  
  500.                 if(IsPrintable[*Src])
  501.                 {
  502.                     *Dst++ = *Src;
  503.  
  504.                     Size++;
  505.                 }
  506.  
  507.                 break;
  508.         }
  509.  
  510.         Src++;
  511.     }
  512.  
  513.     return(Size);
  514. }
  515.  
  516.     /* ConOutputPrinter(STRPTR Buffer,LONG Size):
  517.      *
  518.      *    Raw text output routine, printer capture flavour.
  519.      */
  520.  
  521. STATIC VOID
  522. ConOutputPrinter(STRPTR Buffer,LONG Size)
  523. {
  524.     if(FWrite(PrinterCapture,Buffer,Size,1) != 1)
  525.     {
  526.         BlockWindows();
  527.  
  528.         if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  529.             ClosePrinterCapture(TRUE);
  530.  
  531.         ReleaseWindows();
  532.     }
  533. }
  534.  
  535.     /* ConOutputGFX(STRPTR Buffer,LONG Size):
  536.      *
  537.      *    Raw text output routine, GFX text flavour.
  538.      */
  539.  
  540. STATIC VOID 
  541. ConOutputGFX(STRPTR Buffer,LONG Size)
  542. {
  543.     register WORD Offset;
  544.  
  545.         /* Do we still have a character in the
  546.          * magnificient buffer?
  547.          */
  548.  
  549.     while(Size)
  550.     {
  551.             /* Cursor is positioned at
  552.              * the right hand side of the
  553.              * display. If auto-wrap is
  554.              * enabled, perform some
  555.              * kind of CR/LF, else leave
  556.              * the cursor where it is and
  557.              * quit the show.
  558.              */
  559.  
  560.         if(CursorX > LastPrintableColumn)
  561.         {
  562.                 /* Wrap cursor. */
  563.  
  564.             if(Config -> EmulationConfig -> LineWrap)
  565.             {
  566.                     /* Move to beginning of next line. */
  567.  
  568.                 CursorX = 0;
  569.  
  570.                 DownLine();
  571.  
  572.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  573.  
  574.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  575.  
  576.                 LastPrintableColumn = LastColumn;
  577.  
  578.                     /* Reposition cursor, don't redraw it. */
  579.  
  580.                 RepositionCursor();
  581.             }
  582.             else
  583.             {
  584.                     /* Stop the cursor. */
  585.  
  586.                 CursorX = LastPrintableColumn;
  587.  
  588.                     /* Make it reappear. */
  589.  
  590.                 RepositionCursor();
  591.  
  592.                 return;
  593.             }
  594.         }
  595.  
  596.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  597.             Offset = Size;
  598.  
  599.         if(Config -> EmulationConfig -> InsertMode)
  600.         {
  601.             RasterShiftChar(Offset);
  602.  
  603.             ScrollLineShiftChar(Offset);
  604.  
  605.             ShiftChar(Offset);
  606.         }
  607.  
  608.         RasterPutString(Buffer,Offset);
  609.  
  610.         ScrollLinePutString(Offset);
  611.  
  612.         if(FontScalingRequired)
  613.             PrintScaled(Buffer,Offset,CurrentFontScale);
  614.         else
  615.             GfxText(RPort,Buffer,Offset);
  616.  
  617.         Buffer    += Offset;
  618.  
  619.         Size    -= Offset;
  620.  
  621.         CursorX    += Offset;
  622.     }
  623.  
  624.     RepositionCursor();
  625. }
  626.  
  627.     /* ConOutputNormal(STRPTR Buffer,LONG Size):
  628.      *
  629.      *    Raw text output routine, normal text flavour.
  630.      */
  631.  
  632. STATIC VOID 
  633. ConOutputNormal(STRPTR Buffer,LONG Size)
  634. {
  635.     register WORD Offset;
  636.  
  637.     while(Size)
  638.     {
  639.         if(CursorX > LastPrintableColumn)
  640.         {
  641.             if(Config -> EmulationConfig -> LineWrap)
  642.             {
  643.                 CursorX = 0;
  644.  
  645.                 DownLine();
  646.  
  647.                 CurrentFontScale = SCALE_ATTR_NORMAL;
  648.  
  649.                 FontScalingRequired = (Config -> EmulationConfig -> FontScale != SCALE_NORMAL);
  650.  
  651.                 LastPrintableColumn = LastColumn;
  652.  
  653.                 RepositionCursor();
  654.             }
  655.             else
  656.             {
  657.                 CursorX = LastPrintableColumn;
  658.  
  659.                 RepositionCursor();
  660.  
  661.                 return;
  662.             }
  663.         }
  664.  
  665.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  666.             Offset = Size;
  667.  
  668.         if(Config -> EmulationConfig -> InsertMode)
  669.         {
  670.             RasterShiftChar(Offset);
  671.  
  672.             ScrollLineShiftChar(Offset);
  673.  
  674.             ShiftChar(Offset);
  675.         }
  676.  
  677.         RasterPutString(Buffer,Offset);
  678.  
  679.         ScrollLinePutString(Offset);
  680.  
  681.         if(FontScalingRequired)
  682.             PrintScaled(Buffer,Offset,CurrentFontScale);
  683.         else
  684.             Text(RPort,Buffer,Offset);
  685.  
  686.         Buffer    += Offset;
  687.  
  688.         Size    -= Offset;
  689.  
  690.         CursorX    += Offset;
  691.     }
  692.  
  693.     RepositionCursor();
  694. }
  695.  
  696.     /* ConProcessUpdate():
  697.      *
  698.      *    Choose the right console data processing routine.
  699.      */
  700.  
  701. VOID
  702. ConProcessUpdate(VOID)
  703. {
  704.     Forbid();
  705.  
  706.     if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  707.     {
  708.         if(ReceiveTable)
  709.             ConProcessData = ConProcessDataTransExternal;
  710.         else
  711.             ConProcessData = ConProcessDataExternal;
  712.     }
  713.     else
  714.     {
  715.         if(Config -> SerialConfig -> StripBit8)
  716.         {
  717.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  718.                 ConProcessData = ConProcessDataHex7;
  719.             else
  720.                 ConProcessData = ConProcessData7;
  721.         }
  722.         else
  723.         {
  724.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  725.                 ConProcessData = ConProcessDataHex8;
  726.             else
  727.                 ConProcessData = ConProcessData8;
  728.         }
  729.     }
  730.  
  731.     Permit();
  732. }
  733.  
  734.     /* ConOutputUpdate():
  735.      *
  736.      *    Choose the right raw text output routine for the job.
  737.      */
  738.  
  739. VOID
  740. ConOutputUpdate()
  741. {
  742.     Forbid();
  743.  
  744.     if(BufferFrozen)
  745.     {
  746.         if(FileCapture)
  747.         {
  748.             if(PrinterCapture)
  749.             {
  750.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  751.                     CaptureData = CaptureFilteredTo_File_Printer;
  752.                 else
  753.                     CaptureData = CaptureRawTo_File_Printer;
  754.             }
  755.             else
  756.             {
  757.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  758.                     CaptureData = CaptureFilteredTo_File;
  759.                 else
  760.                     CaptureData = CaptureRawTo_File;
  761.             }
  762.         }
  763.         else
  764.         {
  765.             if(PrinterCapture)
  766.             {
  767.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  768.                     CaptureData = CaptureFilteredTo_Printer;
  769.                 else
  770.                     CaptureData = CaptureRawTo_Printer;
  771.             }
  772.             else
  773.                 CaptureData = NULL;
  774.         }
  775.     }
  776.     else
  777.     {
  778.         if(FileCapture)
  779.         {
  780.             if(PrinterCapture)
  781.             {
  782.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  783.                     CaptureData = CaptureFilteredTo_Buffer_File_Printer;
  784.                 else
  785.                     CaptureData = CaptureRawTo_Buffer_File_Printer;
  786.             }
  787.             else
  788.             {
  789.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  790.                     CaptureData = CaptureFilteredTo_Buffer_File;
  791.                 else
  792.                     CaptureData = CaptureRawTo_Buffer_File;
  793.             }
  794.         }
  795.         else
  796.         {
  797.             if(PrinterCapture)
  798.             {
  799.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  800.                     CaptureData = CaptureFilteredTo_Buffer_Printer;
  801.                 else
  802.                     CaptureData = CaptureRawTo_Buffer_Printer;
  803.             }
  804.             else
  805.             {
  806.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  807.                     CaptureData = CaptureFilteredTo_Buffer;
  808.                 else
  809.                     CaptureData = CaptureRawTo_Buffer;
  810.             }
  811.         }
  812.     }
  813.  
  814.     if(ControllerActive)
  815.         ConOutput = ConOutputPrinter;
  816.     else
  817.     {
  818.         if(CurrentFont == GFX)
  819.             ConOutput = ConOutputGFX;
  820.         else
  821.             ConOutput = ConOutputNormal;
  822.     }
  823.  
  824.     if(ReceiveTable)
  825.         ConDump = ConTransWrite;
  826.     else
  827.         ConDump = ConOutput;
  828.  
  829.     Permit();
  830. }
  831.  
  832.     /* ConFontScaleUpdate():
  833.      *
  834.      *    Choose the right font scale for the job.
  835.      */
  836.  
  837. VOID
  838. ConFontScaleUpdate()
  839. {
  840.     CurrentFontScale = RasterAttr[CursorY];
  841.  
  842.     if(Config -> EmulationConfig -> FontScale == SCALE_HALF)
  843.     {
  844.         FontScalingRequired    = (CurrentFontScale != SCALE_ATTR_2X);
  845.         LastPrintableColumn    = LastColumn;
  846.     }
  847.     else
  848.     {
  849.         if(FontScalingRequired = (CurrentFontScale != SCALE_ATTR_NORMAL))
  850.             LastPrintableColumn = ((LastColumn + 1) / 2) - 1;
  851.         else
  852.             LastPrintableColumn = LastColumn;
  853.     }
  854. }
  855.  
  856.     /* ConTransWrite(STRPTR Buffer,LONG Size):
  857.      *
  858.      *    Frontend for ConWrite(), including character translation.
  859.      */
  860.  
  861. VOID
  862. ConTransWrite(STRPTR Buffer,LONG Size)
  863. {
  864.     struct TranslationHandle    Handle;
  865.     UBYTE                LocalBuffer[256];
  866.  
  867.         /* Set up for translation. */
  868.  
  869.     ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
  870.  
  871.         /* Process and output the data. */
  872.  
  873.     while(Size = ConTranslateBuffer(&Handle))
  874.         (* ConOutput)(LocalBuffer,Size);
  875. }
  876.  
  877.     /* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
  878.      *
  879.      *    Process data, external emulation including translation flavour.
  880.      */
  881.  
  882. VOID
  883. ConProcessDataTransExternal(register STRPTR String,register LONG Size)
  884. {
  885.     struct TranslationHandle Handle;
  886.  
  887.         /* Set up for translation. */
  888.  
  889.     ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
  890.  
  891.     if(StripBuffer)
  892.     {
  893.         register LONG Len;
  894.  
  895.             /* Process and output the data. */
  896.  
  897.         while(Size = ConTranslateBuffer(&Handle))
  898.         {
  899.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  900.  
  901.             XEM_HostData . Source        = ConTempBuffer;
  902.             XEM_HostData . Destination    = StripBuffer;
  903.  
  904.             if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  905.             {
  906.                 if(CaptureData)
  907.                     (*CaptureData)(StripBuffer,Len);
  908.             }
  909.         }
  910.     }
  911.     else
  912.     {
  913.             /* Process and output the data. */
  914.  
  915.         while(Size = ConTranslateBuffer(&Handle))
  916.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  917.     }
  918. }
  919.  
  920.     /* ConProcessDataExternal(register STRPTR String,register LONG Size):
  921.      *
  922.      *    Process data, external emulation flavour.
  923.      */
  924.  
  925. VOID 
  926. ConProcessDataExternal(register STRPTR String,register LONG Size)
  927. {
  928.     XEmulatorWrite(XEM_IO,String,Size);
  929.  
  930.         /* Build another string to contain
  931.          * the pure ASCII contents, i.e.
  932.          * not including any ESC control
  933.          * sequences.
  934.          */
  935.  
  936.     if(StripBuffer)
  937.     {
  938.         register LONG Len;
  939.  
  940.         XEM_HostData . Source        = String;
  941.         XEM_HostData . Destination    = StripBuffer;
  942.  
  943.         if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  944.         {
  945.             if(CaptureData)
  946.                 (*CaptureData)(StripBuffer,Len);
  947.         }
  948.     }
  949. }
  950.  
  951.     /* ConProcessData7(register STRPTR String,register LONG Size):
  952.      *
  953.      *    Process data, 7 bit flavour.
  954.      */
  955.  
  956. VOID 
  957. ConProcessData7(register STRPTR String,register LONG Size)
  958. {
  959.     register LONG    Len = 0;
  960.     register UBYTE    c;
  961.  
  962.         // Check for prescroll/jump scroll
  963.  
  964.     if(CursorY == Bottom && Bottom > 0)
  965.     {
  966.             // The maximum number of line feeds we need to look for
  967.  
  968.         register WORD Max = MAX(Config -> EmulationConfig -> MaxJump,Config -> EmulationConfig -> MaxScroll);
  969.  
  970.             // Any prescroll/jump scroll action wanted?
  971.  
  972.         if(Max)
  973.         {
  974.             register WORD     Count    = Size,
  975.                      Lines    = 0;
  976.             register UBYTE    *Buffer    = String;
  977.  
  978.                 // Count the number of line feeds
  979.  
  980.             while(Count--)
  981.             {
  982.                 if((*Buffer++ & 0x7F) == '\n')
  983.                 {
  984.                     if(++Lines == Max)
  985.                         break;
  986.                 }
  987.             }
  988.  
  989.                 // Ok, so we have found something
  990.  
  991.             if(Lines)
  992.             {
  993.                 register WORD Scroll,TotalLines;
  994.  
  995.                     // Scroll by default?
  996.  
  997.                 if(Scroll = Config -> EmulationConfig -> MaxJump)
  998.                 {
  999.                         // If there is more, use it
  1000.  
  1001.                     if(Lines > Scroll)
  1002.                         Scroll = Lines;
  1003.                 }
  1004.                 else
  1005.                     Scroll = Lines;
  1006.  
  1007.                     // How tall is the current scroll region?
  1008.  
  1009.                 TotalLines = Bottom - Top + 1;
  1010.  
  1011.                     // Don't scroll more than the entire screenful
  1012.  
  1013.                 if(Scroll > TotalLines)
  1014.                     Scroll = TotalLines;
  1015.  
  1016.                     // Is it worth scrolling?
  1017.  
  1018.                 if(Scroll > 1)
  1019.                 {
  1020.                         // Scroll the region...
  1021.  
  1022.                     ScrollRegion(Scroll);
  1023.  
  1024.                         // Reposition the cursor
  1025.  
  1026.                     if(CursorY > Scroll)
  1027.                         CursorY -= Scroll;
  1028.                     else
  1029.                         CursorY = 0;
  1030.  
  1031.                     RepositionCursor();
  1032.                 }
  1033.             }
  1034.         }
  1035.     }
  1036.  
  1037.         /* If still parsing a sequence,
  1038.          * continue with it.
  1039.          */
  1040.  
  1041.     if(InSequence)
  1042.     {
  1043.         while(Size--)
  1044.         {
  1045.             c = *String++ & 0x7F;
  1046.  
  1047.             if(!(*AbortTable[c])(c))
  1048.             {
  1049.                 InSequence = FALSE;
  1050.  
  1051.                 break;
  1052.             }
  1053.         }
  1054.     }
  1055.  
  1056.         /* Check which font we are in, if other than Topaz
  1057.          * the only invalid char is a Null (0) which will
  1058.          * display as a space if let to continue.
  1059.          */
  1060.  
  1061.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1062.     {
  1063.         while(Size-- > 0)
  1064.         {
  1065.             if(IsPrintable[c = *String++ & 0x7F])
  1066.             {
  1067.                     /* This character is associated with a
  1068.                      * special function (bell, xon, xoff, etc.).
  1069.                      */
  1070.  
  1071.                 if(SpecialTable[c])
  1072.                 {
  1073.                     if(Len)
  1074.                     {
  1075.                         (*ConDump)(ConTempBuffer,Len);
  1076.  
  1077.                         Len = 0;
  1078.                     }
  1079.  
  1080.                         /* Does this character start
  1081.                          * a control sequence?
  1082.                          */
  1083.  
  1084.                     if(InSequence = (*SpecialTable[c])(c))
  1085.                     {
  1086.                         while(Size-- > 0)
  1087.                         {
  1088.                             c = *String++ & 0x7F;
  1089.  
  1090.                             if(!(*AbortTable[c])(c))
  1091.                             {
  1092.                                 InSequence = FALSE;
  1093.  
  1094.                                 break;
  1095.                             }
  1096.                         }
  1097.                     }
  1098.                 }
  1099.                 else
  1100.                 {
  1101.                         /* Put the character into the buffer
  1102.                          * and flush it if necessary.
  1103.                          */
  1104.  
  1105.                     ConTempBuffer[Len] = c;
  1106.  
  1107.                     if(Len++ == 512)
  1108.                     {
  1109.                         (*ConDump)(ConTempBuffer,Len);
  1110.  
  1111.                         Len = 0;
  1112.                     }
  1113.                 }
  1114.             }
  1115.         }
  1116.     }
  1117.     else
  1118.     {
  1119.         while(Size-- > 0)
  1120.         {
  1121.             if(c = (*String++ & 0x7F))
  1122.             {
  1123.                     /* This character is associated with a
  1124.                      * special function (bell, xon, xoff, etc.).
  1125.                      */
  1126.  
  1127.                 if(SpecialTable[c])
  1128.                 {
  1129.                     if(Len)
  1130.                     {
  1131.                         (*ConDump)(ConTempBuffer,Len);
  1132.  
  1133.                         Len = 0;
  1134.                     }
  1135.  
  1136.                     if(InSequence = (*SpecialTable[c])(c))
  1137.                     {
  1138.                         while(Size-- > 0)
  1139.                         {
  1140.                             c = *String++ & 0x7F;
  1141.  
  1142.                             if(!(*AbortTable[c])(c))
  1143.                             {
  1144.                                 InSequence = FALSE;
  1145.  
  1146.                                 break;
  1147.                             }
  1148.                         }
  1149.                     }
  1150.                 }
  1151.                 else
  1152.                 {
  1153.                         /* Put the character into the buffer
  1154.                          * and flush it if necessary.
  1155.                          */
  1156.  
  1157.                     ConTempBuffer[Len] = c;
  1158.  
  1159.                     if(Len++ == 512)
  1160.                     {
  1161.                         (*ConDump)(ConTempBuffer,Len);
  1162.  
  1163.                         Len = 0;
  1164.                     }
  1165.                 }
  1166.             }
  1167.         }
  1168.     }
  1169.  
  1170.     if(Len)
  1171.         (*ConDump)(ConTempBuffer,Len);
  1172. }
  1173.  
  1174.     /* ConProcessData8(register STRPTR String,register LONG Size):
  1175.      *
  1176.      *    Process data, 8 bit flavour.
  1177.      */
  1178.  
  1179. VOID 
  1180. ConProcessData8(register STRPTR String,register LONG Size)
  1181. {
  1182.     register LONG    Len = 0;
  1183.     register UBYTE    c;
  1184.  
  1185.         // Check for prescroll/jump scroll
  1186.  
  1187.     if(CursorY == Bottom && Bottom > 0)
  1188.     {
  1189.             // The maximum number of line feeds we need to look for
  1190.  
  1191.         register WORD Max = MAX(Config -> EmulationConfig -> MaxJump,Config -> EmulationConfig -> MaxScroll);
  1192.  
  1193.             // Any prescroll/jump scroll action wanted?
  1194.  
  1195.         if(Max)
  1196.         {
  1197.             register WORD     Count    = Size,
  1198.                      Lines    = 0;
  1199.             register UBYTE    *Buffer    = String;
  1200.  
  1201.                 // Count the number of line feeds
  1202.  
  1203.             while(Count--)
  1204.             {
  1205.                 if(*Buffer++ == '\n')
  1206.                 {
  1207.                     if(++Lines == Max)
  1208.                         break;
  1209.                 }
  1210.             }
  1211.  
  1212.                 // Ok, so we have found something
  1213.  
  1214.             if(Lines)
  1215.             {
  1216.                 register WORD Scroll,TotalLines;
  1217.  
  1218.                     // Scroll by default?
  1219.  
  1220.                 if(Scroll = Config -> EmulationConfig -> MaxJump)
  1221.                 {
  1222.                         // If there is more, use it
  1223.  
  1224.                     if(Lines > Scroll)
  1225.                         Scroll = Lines;
  1226.                 }
  1227.                 else
  1228.                     Scroll = Lines;
  1229.  
  1230.                     // How tall is the current scroll region?
  1231.  
  1232.                 TotalLines = Bottom - Top + 1;
  1233.  
  1234.                     // Don't scroll more than the entire screenful
  1235.  
  1236.                 if(Scroll > TotalLines)
  1237.                     Scroll = TotalLines;
  1238.  
  1239.                     // Is it worth scrolling?
  1240.  
  1241.                 if(Scroll > 1)
  1242.                 {
  1243.                         // Scroll the region...
  1244.  
  1245.                     ScrollRegion(Scroll);
  1246.  
  1247.                         // Reposition the cursor
  1248.  
  1249.                     if(CursorY > Scroll)
  1250.                         CursorY -= Scroll;
  1251.                     else
  1252.                         CursorY = 0;
  1253.  
  1254.                     RepositionCursor();
  1255.                 }
  1256.             }
  1257.         }
  1258.     }
  1259.  
  1260.     if(InSequence)
  1261.     {
  1262.         while(Size--)
  1263.         {
  1264.             c = *String++;
  1265.  
  1266.             if(!(*AbortTable[c])(c))
  1267.             {
  1268.                 InSequence = FALSE;
  1269.  
  1270.                 break;
  1271.             }
  1272.         }
  1273.     }
  1274.  
  1275.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1276.     {
  1277.         while(Size-- > 0)
  1278.         {
  1279.             if(IsPrintable[c = *String++])
  1280.             {
  1281.                 if(SpecialTable[c])
  1282.                 {
  1283.                     if(Len)
  1284.                     {
  1285.                         (*ConDump)(ConTempBuffer,Len);
  1286.  
  1287.                         Len = 0;
  1288.                     }
  1289.  
  1290.                     if(InSequence = (*SpecialTable[c])(c))
  1291.                     {
  1292.                         while(Size-- > 0)
  1293.                         {
  1294.                             c = *String++;
  1295.  
  1296.                             if(!(*AbortTable[c])(c))
  1297.                             {
  1298.                                 InSequence = FALSE;
  1299.  
  1300.                                 break;
  1301.                             }
  1302.                         }
  1303.                     }
  1304.                 }
  1305.                 else
  1306.                 {
  1307.                     ConTempBuffer[Len] = c;
  1308.  
  1309.                     if(Len++ == 512)
  1310.                     {
  1311.                         (*ConDump)(ConTempBuffer,Len);
  1312.  
  1313.                         Len = 0;
  1314.                     }
  1315.                 }
  1316.             }
  1317.         }
  1318.     }
  1319.     else
  1320.     {
  1321.         while(Size-- > 0)
  1322.         {
  1323.             if(c = *String++)
  1324.             {
  1325.                 if(SpecialTable[c])
  1326.                 {
  1327.                     if(Len)
  1328.                     {
  1329.                         (*ConDump)(ConTempBuffer,Len);
  1330.  
  1331.                         Len = 0;
  1332.                     }
  1333.  
  1334.                     if(InSequence = (*SpecialTable[c])(c))
  1335.                     {
  1336.                         while(Size-- > 0)
  1337.                         {
  1338.                             c = *String++;
  1339.  
  1340.                             if(!(*AbortTable[c])(c))
  1341.                             {
  1342.                                 InSequence = FALSE;
  1343.  
  1344.                                 break;
  1345.                             }
  1346.                         }
  1347.                     }
  1348.                 }
  1349.                 else
  1350.                 {
  1351.                     ConTempBuffer[Len] = c;
  1352.  
  1353.                     if(Len++ == 512)
  1354.                     {
  1355.                         (*ConDump)(ConTempBuffer,Len);
  1356.  
  1357.                         Len = 0;
  1358.                     }
  1359.                 }
  1360.             }
  1361.         }
  1362.     }
  1363.  
  1364.     if(Len)
  1365.         (*ConDump)(ConTempBuffer,Len);
  1366. }
  1367.  
  1368.     /* ConProcessDataHex7(register STRPTR String,register LONG Size):
  1369.      *
  1370.      *    Process data, hex mode flavour, seven bits.
  1371.      */
  1372.  
  1373. VOID 
  1374. ConProcessDataHex7(register STRPTR String,register LONG Size)
  1375. {
  1376.     UBYTE    DummyBuffer[40],c;
  1377.     LONG    Fit,Spaces,Current;
  1378.  
  1379.         /* How many characters will fit into the line? */
  1380.  
  1381.     Fit    = (LastColumn + 1) / 4;
  1382.  
  1383.         /* Which position are we currently in? */
  1384.  
  1385.     Current    = CursorX / 3;
  1386.  
  1387.         /* Weird cursor position? */
  1388.  
  1389.     if(Current >= Fit || (CursorX % 3))
  1390.     {
  1391.         ConProcessData7("\r\n",2);
  1392.  
  1393.         Current = 0;
  1394.     }
  1395.  
  1396.         /* Check the font type. */
  1397.  
  1398.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1399.     {
  1400.         while(Size-- > 0)
  1401.         {
  1402.             c = (*String++) & 0x7F;
  1403.  
  1404.             Spaces = (Fit - Current) * 3 + Current - 3;
  1405.  
  1406.             if(c > ' ' && c < 127)
  1407.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1408.             else
  1409.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1410.  
  1411.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1412.  
  1413.             if(Current++ == Fit - 1)
  1414.             {
  1415.                 Current = 0;
  1416.  
  1417.                 ConProcessData7("\r\n",2);
  1418.             }
  1419.         }
  1420.     }
  1421.     else
  1422.     {
  1423.         while(Size-- > 0)
  1424.         {
  1425.             c = (*String++) & 0x7F;
  1426.  
  1427.             Spaces = (Fit - Current) * 3 + Current - 3;
  1428.  
  1429.             if(c && c != ' ')
  1430.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1431.             else
  1432.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1433.  
  1434.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1435.  
  1436.             if(Current++ == Fit - 1)
  1437.             {
  1438.                 Current = 0;
  1439.  
  1440.                 ConProcessData7("\r\n",2);
  1441.             }
  1442.         }
  1443.     }
  1444. }
  1445.  
  1446.     /* ConProcessDataHex8(register STRPTR String,register LONG Size):
  1447.      *
  1448.      *    Process data, hex mode flavour, eight bits.
  1449.      */
  1450.  
  1451. VOID 
  1452. ConProcessDataHex8(register STRPTR String,register LONG Size)
  1453. {
  1454.     UBYTE    DummyBuffer[40],c;
  1455.     LONG    Fit,Spaces,Current;
  1456.  
  1457.         /* How many characters will fit into the line? */
  1458.  
  1459.     Fit    = (LastColumn + 1) / 4;
  1460.  
  1461.         /* Which position are we currently in? */
  1462.  
  1463.     Current    = CursorX / 3;
  1464.  
  1465.         /* Weird cursor position? */
  1466.  
  1467.     if(Current >= Fit || (CursorX % 3))
  1468.     {
  1469.         ConProcessData8("\r\n",2);
  1470.  
  1471.         Current = 0;
  1472.     }
  1473.  
  1474.         /* Check the font type. */
  1475.  
  1476.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1477.     {
  1478.         while(Size-- > 0)
  1479.         {
  1480.             c = *String++;
  1481.  
  1482.             Spaces = (Fit - Current) * 3 + Current - 3;
  1483.  
  1484.             if((c > ' ' && c < 127) || c > 160)
  1485.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1486.             else
  1487.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1488.  
  1489.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1490.  
  1491.             if(Current++ == Fit - 1)
  1492.             {
  1493.                 Current = 0;
  1494.  
  1495.                 ConProcessData8("\r\n",2);
  1496.             }
  1497.         }
  1498.     }
  1499.     else
  1500.     {
  1501.         while(Size-- > 0)
  1502.         {
  1503.             c = *String++;
  1504.  
  1505.             Spaces = (Fit - Current) * 3 + Current - 3;
  1506.  
  1507.             if(c && c != ' ')
  1508.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1509.             else
  1510.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1511.  
  1512.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1513.  
  1514.             if(Current++ == Fit - 1)
  1515.             {
  1516.                 Current = 0;
  1517.  
  1518.                 ConProcessData8("\r\n",2);
  1519.             }
  1520.         }
  1521.     }
  1522. }
  1523.  
  1524.     /* ConTransferHost(STRPTR Buffer,LONG Len):
  1525.      *
  1526.      *    Process data read from the serial line,
  1527.      *    special XPR flavour.
  1528.      */
  1529.  
  1530. VOID 
  1531. ConTransferHost(STRPTR Buffer,LONG Len)
  1532. {
  1533.     Len = XProtocolHostMon(XprIO,Buffer,Len,SerialBufferSize);
  1534.  
  1535.     if(TransferWindow)
  1536.         TransferCleanup();
  1537.  
  1538.     if(Len)
  1539.         ConProcess(Buffer,Len);
  1540. }
  1541.  
  1542.     /* ConsoleCommand(STRPTR String):
  1543.      *
  1544.      *    Just like SerialCommand(), but addresses the local
  1545.      *    terminal side.
  1546.      */
  1547.  
  1548. VOID 
  1549. ConsoleCommand(STRPTR String)
  1550. {
  1551.     STATIC UBYTE __far LocalBuffer[256];
  1552.  
  1553.     LONG    Count = 0,i,Len = strlen(String);
  1554.  
  1555.     BYTE    GotControl    = FALSE,
  1556.         GotEscape    = FALSE;
  1557.  
  1558.         /* Scan the string. */
  1559.  
  1560.     for(i = 0 ; i < Len ; i++)
  1561.     {
  1562.             /* We are looking for plain characters
  1563.              * and the control ('\') and escape
  1564.              * ('^') characters.
  1565.              */
  1566.  
  1567.         if(!GotControl && !GotEscape)
  1568.         {
  1569.                 /* Got a control character,
  1570.                  * the next byte will probably be
  1571.                  * a command sequence.
  1572.                  */
  1573.  
  1574.             if(String[i] == '\\')
  1575.             {
  1576.                 GotControl = TRUE;
  1577.  
  1578.                 continue;
  1579.             }
  1580.  
  1581.                 /* Got an escape character,
  1582.                  * the next byte will be some
  1583.                  * kind of control character
  1584.                  * (such as XON, XOF, bell, etc.).
  1585.                  */
  1586.  
  1587.             if(String[i] == '^')
  1588.             {
  1589.                 GotEscape = TRUE;
  1590.  
  1591.                 continue;
  1592.             }
  1593.  
  1594.                 /* This tells us to wait another
  1595.                  * second before continuing with
  1596.                  * the scanning.
  1597.                  */
  1598.  
  1599.             if(String[i] == '~')
  1600.                 continue;
  1601.  
  1602.                 /* Stuff the character into the
  1603.                  * buffer.
  1604.                  */
  1605.  
  1606.             LocalBuffer[Count++] = String[i];
  1607.         }
  1608.         else
  1609.         {
  1610.                 /* Convert the character to a control
  1611.                  * style character (^C, etc.).
  1612.                  */
  1613.  
  1614.             if(GotEscape)
  1615.             {
  1616.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
  1617.                     LocalBuffer[Count++] = ToUpper(String[i]) - '@';
  1618.                 else
  1619.                     LocalBuffer[Count++] = String[i];
  1620.  
  1621.                 GotEscape = FALSE;
  1622.             }
  1623.  
  1624.                 /* The next character represents a command. */
  1625.  
  1626.             if(GotControl)
  1627.             {
  1628.                 switch(ToUpper(String[i]))
  1629.                 {
  1630.                         /* Translate code. */
  1631.  
  1632.                     case '*':
  1633.  
  1634.                         i++;
  1635.  
  1636.                         while(i < Len && String[i] == ' ')
  1637.                             i++;
  1638.  
  1639.                         if(i < Len)
  1640.                         {
  1641.                             UBYTE DummyBuffer[5],j = 0,Char;
  1642.  
  1643.                             if(String[i] >= '0' && String[i] <= '9')
  1644.                             {
  1645.                                 while(j < 3 && i < Len)
  1646.                                 {
  1647.                                     Char = String[i++];
  1648.  
  1649.                                     if(Char >= '0' && Char <= '9')
  1650.                                         DummyBuffer[j++] = Char;
  1651.                                     else
  1652.                                     {
  1653.                                         i--;
  1654.  
  1655.                                         break;
  1656.                                     }
  1657.                                 }
  1658.                             }
  1659.                             else
  1660.                             {
  1661.                                 while(j < 4 && i < Len)
  1662.                                 {
  1663.                                     Char = ToLower(String[i++]);
  1664.  
  1665.                                     if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  1666.                                         DummyBuffer[j++] = Char;
  1667.                                     else
  1668.                                     {
  1669.                                         i--;
  1670.  
  1671.                                         break;
  1672.                                     }
  1673.                                 }
  1674.                             }
  1675.  
  1676.                             DummyBuffer[j] = 0;
  1677.  
  1678.                             LocalBuffer[Count++] = NameToCode(DummyBuffer);
  1679.                         }
  1680.  
  1681.                         i--;
  1682.  
  1683.                         break;
  1684.  
  1685.                         /* Execute an AmigaDOS command. */
  1686.  
  1687.                     case 'D':
  1688.  
  1689.                         return;
  1690.  
  1691.                         /* Execute an ARexx command. */
  1692.  
  1693.                     case 'A':
  1694.  
  1695.                         return;
  1696.  
  1697.                         /* Add the control character ('\'). */
  1698.  
  1699.                     case '\\':
  1700.  
  1701.                         LocalBuffer[Count++] = '\\';
  1702.                         break;
  1703.  
  1704.                         /* This is a backspace. */
  1705.  
  1706.                     case 'B':
  1707.  
  1708.                         LocalBuffer[Count++] = '\b';
  1709.                         break;
  1710.  
  1711.                         /* This is a form feed. */
  1712.  
  1713.                     case 'F':
  1714.  
  1715.                         LocalBuffer[Count++] = '\f';
  1716.                         break;
  1717.  
  1718.                         /* This is a line feed. */
  1719.  
  1720.                     case 'N':
  1721.  
  1722.                         LocalBuffer[Count++] = '\n';
  1723.                         break;
  1724.  
  1725.                         /* Send the current password. */
  1726.  
  1727.                     case 'P':
  1728.  
  1729.                         break;
  1730.  
  1731.                         /* This is a carriage return. */
  1732.  
  1733.                     case 'R':
  1734.  
  1735.                         LocalBuffer[Count++] = '\r';
  1736.                         break;
  1737.  
  1738.                         /* This is a tab. */
  1739.  
  1740.                     case 'T':
  1741.  
  1742.                         LocalBuffer[Count++] = '\t';
  1743.                         break;
  1744.  
  1745.                         /* Send the current user name. */
  1746.  
  1747.                     case 'U':
  1748.  
  1749.                         break;
  1750.  
  1751.                         /* Send a break across the serial line. */
  1752.  
  1753.                     case 'X':
  1754.  
  1755.                         break;
  1756.  
  1757.                         /* Feed the contents of the
  1758.                          * clipboard into the input
  1759.                          * stream.
  1760.                          */
  1761.  
  1762.                     case 'I':
  1763.  
  1764.                         if(Count)
  1765.                             ConProcess(LocalBuffer,Count);
  1766.  
  1767.                         Count = LoadClip(LocalBuffer,256);
  1768.  
  1769.                         break;
  1770.  
  1771.                         /* Send a string to the clipboard. */
  1772.  
  1773.                     case 'G':
  1774.  
  1775.                         if(String[i + 1])
  1776.                             SaveClip(&String[i + 1],strlen(&String[i + 1]));
  1777.  
  1778.                         return;
  1779.  
  1780.                         /* Produce the escape character. */
  1781.  
  1782.                     case 'E':
  1783.  
  1784.                         LocalBuffer[Count++] = ESC;
  1785.                         break;
  1786.  
  1787.                         /* Call a menu item. */
  1788.  
  1789.                     case 'C':
  1790.  
  1791.                         break;
  1792.  
  1793.                         /* Stuff the character into the buffer. */
  1794.  
  1795.                     default:
  1796.  
  1797.                         LocalBuffer[Count++] = String[i];
  1798.                         break;
  1799.                 }
  1800.  
  1801.                 GotControl = FALSE;
  1802.             }
  1803.         }
  1804.  
  1805.             /* If the buffer is full, release it. */
  1806.  
  1807.         if(Count == 256)
  1808.         {
  1809.             ConProcess(LocalBuffer,Count);
  1810.  
  1811.             Count = 0;
  1812.         }
  1813.     }
  1814.  
  1815.     if(Count)
  1816.         ConProcess(LocalBuffer,Count);
  1817. }
  1818.  
  1819.     /* ConBypass(STRPTR String,LONG Size):
  1820.      *
  1821.      *    Bypass the `normal' ConOutput() data processing.
  1822.      */
  1823.  
  1824. VOID __regargs
  1825. ConBypass(STRPTR String,LONG Size)
  1826. {
  1827.     if(Size < 0)
  1828.         Size = strlen(String);
  1829.  
  1830.     if(Size > 0)
  1831.     {
  1832.         VOID (* ProcessData)(STRPTR,LONG);
  1833.  
  1834.         if(Config -> SerialConfig -> StripBit8)
  1835.             ProcessData = ConProcessData7;
  1836.         else
  1837.             ProcessData = ConProcessData8;
  1838.  
  1839.         ObtainSemaphore(&TerminalSemaphore);
  1840.  
  1841.         if(Marking)
  1842.             DropMarker();
  1843.  
  1844.         ClearCursor();
  1845.  
  1846.         (*ProcessData)(String,Size);
  1847.  
  1848.         DrawCursor();
  1849.  
  1850.         ReleaseSemaphore(&TerminalSemaphore);
  1851.     }
  1852. }
  1853.  
  1854.     /* ConProcess(STRPTR String,LONG Size):
  1855.      *
  1856.      *    Process the contents of a string to be sent to the
  1857.      *    console window.
  1858.      */
  1859.  
  1860. VOID 
  1861. ConProcess(register STRPTR String,register LONG Size)
  1862. {
  1863.         /* Feed the flow filter. */
  1864.  
  1865.     if(UseFlow)
  1866.     {
  1867.         if(Config -> SerialConfig -> StripBit8)
  1868.             FlowFilter(String,Size,0x7F);
  1869.         else
  1870.             FlowFilter(String,Size,0xFF);
  1871.     }
  1872.  
  1873.         /* In quiet mode no characters are echoed to the
  1874.          * console window, they are just passed through
  1875.          * the data flow filter. Usually, this mode is
  1876.          * enabled by the dial panel.
  1877.          */
  1878.  
  1879.     if(!Quiet)
  1880.     {
  1881.             /* Capture the data. */
  1882.  
  1883.         if(CaptureData)
  1884.             (*CaptureData)(String,Size);
  1885.  
  1886.             /* Remember the data. */
  1887.  
  1888.         if(RememberOutput)
  1889.             RememberOutputText(String,Size);
  1890.  
  1891.             /* Check the traps if necessary. */
  1892.  
  1893.         if(WatchTraps)
  1894.             TrapFilter(String,Size);
  1895.  
  1896.         if(Marking)
  1897.             DropMarker();
  1898.  
  1899.         if(TerminalQueue)
  1900.         {
  1901.             struct DataMsg *Msg;
  1902.  
  1903.             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + Size))
  1904.             {
  1905.                 Msg -> Data = (APTR)(Msg + 1);
  1906.                 Msg -> Size = Size;
  1907.  
  1908.                 CopyMem(String,Msg -> Data,Msg -> Size);
  1909.  
  1910.                 PutMsgItem(TerminalQueue,Msg);
  1911.             }
  1912.             else
  1913.             {
  1914.                 ClearCursor();
  1915.  
  1916.                 (*ConProcessData)(String,Size);
  1917.  
  1918.                 DrawCursor();
  1919.             }
  1920.         }
  1921.         else
  1922.         {
  1923.             ClearCursor();
  1924.  
  1925.             (*ConProcessData)(String,Size);
  1926.  
  1927.             DrawCursor();
  1928.         }
  1929.     }
  1930. }
  1931.  
  1932.     /* ConWrites(STRPTR String,...):
  1933.      *
  1934.      *    Output a string to the console.
  1935.      */
  1936.  
  1937. VOID __stdargs
  1938. ConWrites(STRPTR String,...)
  1939. {
  1940.     va_list    VarArgs;
  1941.  
  1942.     if(Marking)
  1943.         DropMarker();
  1944.  
  1945.     va_start(VarArgs,String);
  1946.     VSPrintf(SharedBuffer,String,VarArgs);
  1947.     va_end(VarArgs);
  1948.  
  1949.     ConProcess(SharedBuffer,strlen(SharedBuffer));
  1950. }
  1951.  
  1952.     /* FlowInit():
  1953.      *
  1954.      *    Set up the data flow parser. The parser scans the serial
  1955.      *    output data for more or less interesting modem output
  1956.      *    (carrier lost, connect, etc.).
  1957.      */
  1958.  
  1959. VOID __regargs
  1960. FlowInit(BYTE FullReset)
  1961. {
  1962.     WORD i;
  1963.  
  1964.         /* Set up `NO CARRIER' message. */
  1965.  
  1966.     if(Config -> ModemConfig -> NoCarrier[0])
  1967.         SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
  1968.     else
  1969.         AttentionBuffers[SCAN_NOCARRIER][0] = 0;
  1970.  
  1971.         /* Set up ZRQINIT message. */
  1972.  
  1973.     strcpy(AttentionBuffers[SCAN_ZMODEM],"*\030B01");
  1974.  
  1975.         /* Set up `CONNECT' message. */
  1976.  
  1977.     strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
  1978.  
  1979.         /* Set up `VOICE' message. */
  1980.  
  1981.     if(Config -> ModemConfig -> Voice[0])
  1982.         SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
  1983.     else
  1984.         AttentionBuffers[SCAN_VOICE][0] = 0;
  1985.  
  1986.         /* Set up `RING' message. */
  1987.  
  1988.     if(Config -> ModemConfig -> Ring[0])
  1989.         SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
  1990.     else
  1991.         AttentionBuffers[SCAN_RING][0] = 0;
  1992.  
  1993.         /* Set up `BUSY' message. */
  1994.  
  1995.     if(Config -> ModemConfig -> Busy[0])
  1996.         SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
  1997.     else
  1998.         AttentionBuffers[SCAN_BUSY][0] = 0;
  1999.  
  2000.         /* Set up `NO DIALTONE' message. */
  2001.  
  2002.     if(Config -> ModemConfig -> NoDialTone[0])
  2003.         SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
  2004.     else
  2005.         AttentionBuffers[SCAN_NODIALTONE][0] = 0;
  2006.  
  2007.         /* Set up `OK' message. */
  2008.  
  2009.     if(Config -> ModemConfig -> Ok[0])
  2010.         SPrintf(AttentionBuffers[SCAN_OK],"%s\r",Config -> ModemConfig -> Ok);
  2011.     else
  2012.         AttentionBuffers[SCAN_OK][0] = 0;
  2013.  
  2014.         /* Set up `ERROR' message. */
  2015.  
  2016.     if(Config -> ModemConfig -> Error[0])
  2017.         SPrintf(AttentionBuffers[SCAN_ERROR],"%s\r",Config -> ModemConfig -> Error);
  2018.     else
  2019.         AttentionBuffers[SCAN_ERROR][0] = 0;
  2020.  
  2021.         /* Reset match counter. */
  2022.  
  2023.     FlowCount = 0;
  2024.  
  2025.         /* Reset indices. */
  2026.  
  2027.     memset(AttentionCount,0,sizeof(AttentionCount));
  2028.  
  2029.         /* Determine lengths. */
  2030.  
  2031.     for(i = 0 ; i < SCAN_COUNT ; i++)
  2032.         AttentionLength[i] = strlen(AttentionBuffers[i]);
  2033.  
  2034.     if(FullReset)
  2035.     {
  2036.             /* No, we are not yet looking for a baud rate. */
  2037.  
  2038.         BaudPending = FALSE;
  2039.  
  2040.             /* Reset the flags. */
  2041.  
  2042.         memset(&FlowInfo,FALSE,sizeof(struct FlowInfo));
  2043.     }
  2044.  
  2045.         /* Is it safe to disable the flow filter? */
  2046.  
  2047.     ObtainSemaphore(&OnlineSemaphore);
  2048.  
  2049.     if(!FullCheck && Online && Config -> SerialConfig -> CheckCarrier && !Config -> MiscConfig -> AutoUpload)
  2050.         UseFlow = FALSE;
  2051.     else
  2052.         UseFlow = TRUE;
  2053.  
  2054.     ReleaseSemaphore(&OnlineSemaphore);
  2055.  
  2056.         /* Full data check is a lot slower than looking for
  2057.          * just a single sequence (such as the `CONNECT'
  2058.          * below). This mode is reserved for the dial panel.
  2059.          */
  2060.  
  2061.     if(FullCheck)
  2062.     {
  2063.         ScanStart    = 0;
  2064.         ScanEnd        = SCAN_COUNT - 1;
  2065.     }
  2066.     else
  2067.     {
  2068.         ObtainSemaphore(&OnlineSemaphore);
  2069.  
  2070.         if(Online)
  2071.         {
  2072.             ScanStart = SCAN_NOCARRIER;
  2073.  
  2074.             if(UsesZModem)
  2075.                 ScanEnd = SCAN_ZMODEM;
  2076.             else
  2077.                 ScanEnd = SCAN_NOCARRIER;
  2078.         }
  2079.         else
  2080.         {
  2081.             if(UsesZModem)
  2082.                 ScanStart = SCAN_ZMODEM;
  2083.             else
  2084.                 ScanStart = SCAN_CONNECT;
  2085.  
  2086.             ScanEnd = SCAN_RING;
  2087.         }
  2088.  
  2089.         ReleaseSemaphore(&OnlineSemaphore);
  2090.     }
  2091. }
  2092.  
  2093.     /* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
  2094.      *
  2095.      *    Text output, if necessary switching from gfx font
  2096.      *    to current default font.
  2097.      */
  2098.  
  2099. VOID __regargs
  2100. GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
  2101. {
  2102.     BYTE TextMode;
  2103.     LONG SameMode;
  2104.  
  2105.         /* Determine current text rendering mode. */
  2106.  
  2107.     if(GfxTable[Buffer[0]] == MODE_GFX)
  2108.         TextMode = MODE_GFX;
  2109.     else
  2110.     {
  2111.         TextMode = MODE_STANDARD;
  2112.  
  2113.         SetFont(RPort,TextFont);
  2114.     }
  2115.  
  2116.         /* Reset number of characters in common mode. */
  2117.  
  2118.     SameMode = 0;
  2119.  
  2120.         /* Scan until all input is processed. */
  2121.  
  2122.     FOREVER
  2123.     {
  2124.             /* Scan for characters in the current mode. */
  2125.  
  2126.         while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
  2127.             SameMode++;
  2128.  
  2129.             /* Output the text found. */
  2130.  
  2131.         Text(RPort,Buffer,SameMode);
  2132.  
  2133.             /* Decrement number of remaining bytes. */
  2134.  
  2135.         Length -= SameMode;
  2136.  
  2137.             /* Anything left? */
  2138.  
  2139.         if(Length)
  2140.         {
  2141.                 /* Skip to next character. */
  2142.  
  2143.             Buffer        += SameMode;
  2144.             SameMode     = 0;
  2145.  
  2146.                 /* Change text output mode. */
  2147.  
  2148.             if(TextMode == MODE_GFX)
  2149.             {
  2150.                 SetFont(RPort,TextFont);
  2151.  
  2152.                 TextMode = MODE_STANDARD;
  2153.             }
  2154.             else
  2155.             {
  2156.                 SetFont(RPort,GFX);
  2157.  
  2158.                 TextMode = MODE_GFX;
  2159.             }
  2160.         }
  2161.         else
  2162.             break;
  2163.     }
  2164.  
  2165.         /* Reset font type. */
  2166.  
  2167.     if(TextMode == MODE_STANDARD)
  2168.         SetFont(RPort,GFX);
  2169. }
  2170.  
  2171.     /* ConvertKey():
  2172.      *
  2173.      *    The actual key conversion routine.
  2174.      */
  2175.  
  2176. STATIC LONG __inline
  2177. ConvertKey(ULONG Qualifier,UWORD Code,ULONG Prev,STRPTR Buffer,LONG Len)
  2178. {
  2179.     LONG Actual;
  2180.  
  2181.         /* Fill in the defaults. */
  2182.  
  2183.     FakeInputEvent -> ie_Code        = Code;
  2184.     FakeInputEvent -> ie_Qualifier        = Qualifier;
  2185.     FakeInputEvent -> ie_position . ie_addr    = (APTR)Prev;
  2186.  
  2187.         /* Clear the buffer (sortof). */
  2188.  
  2189.     Buffer[0] = 0;
  2190.  
  2191.         /* Convert the codes. */
  2192.  
  2193.     if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
  2194.         return(Actual);
  2195.     else
  2196.         return(0);
  2197. }
  2198.  
  2199.     /* ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev):
  2200.      *
  2201.      *    Much more simplified raw key conversion routine.
  2202.      */
  2203.  
  2204. UBYTE __regargs
  2205. ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev)
  2206. {
  2207.     if(Buffer)
  2208.         Buffer[0] = 0;
  2209.  
  2210.     if(Len)
  2211.         *Len = 0;
  2212.  
  2213.         /* Key was pressed, not released. */
  2214.  
  2215.     if(!(Code & IECODE_UP_PREFIX))
  2216.     {
  2217.             /* These are the sequences mapped to special
  2218.              * control keys (cursor keys, function keys,
  2219.              * the help key).
  2220.              */
  2221.  
  2222.         STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
  2223.         {
  2224.             (STRPTR)"A",    CUP,
  2225.             (STRPTR)"B",    CDN,
  2226.             (STRPTR)"C",    CFW,
  2227.             (STRPTR)"D",    CBK,
  2228.  
  2229.             (STRPTR)"?~",    HLP,
  2230.  
  2231.             (STRPTR)"0~",    FN1,
  2232.             (STRPTR)"1~",    FN2,
  2233.             (STRPTR)"2~",    FN3,
  2234.             (STRPTR)"3~",    FN4,
  2235.             (STRPTR)"4~",    FN5,
  2236.             (STRPTR)"5~",    FN6,
  2237.             (STRPTR)"6~",    FN7,
  2238.             (STRPTR)"7~",    FN8,
  2239.             (STRPTR)"8~",    FN9,
  2240.             (STRPTR)"9~",    F10
  2241.         };
  2242.  
  2243.         STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
  2244.  
  2245.         UBYTE    ConvertBuffer[257];
  2246.         LONG    Actual;
  2247.  
  2248.             /* If it's a function or cursor key, clear the qualifier. */
  2249.  
  2250.         if(Code >= CURSOR_UP_CODE && Code <= F10_CODE)
  2251.             Qualifier = NULL;
  2252.         else
  2253.         {
  2254.                 /* Does it have a numeric keypad qualifier set? */
  2255.  
  2256.             if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
  2257.             {
  2258.                 STRPTR String = NULL;
  2259.  
  2260.                     /* Look at the vanilla result. */
  2261.  
  2262.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Code,Prev,ConvertBuffer,1))
  2263.                 {
  2264.                         /* Take a look at the results. */
  2265.  
  2266.                     switch(ConvertBuffer[0])
  2267.                     {
  2268.                         case '(':
  2269.                         case '[':
  2270.                         case '{':
  2271.  
  2272.                             String = "\033OP";
  2273.                             break;
  2274.  
  2275.                         case ')':
  2276.                         case ']':
  2277.                         case '}':
  2278.  
  2279.                             String = "\033OQ";
  2280.                             break;
  2281.  
  2282.                         case '/':
  2283.  
  2284.                             String = "\033OR";
  2285.                             break;
  2286.  
  2287.                         case '*':
  2288.  
  2289.                             String = "\033OS";
  2290.                             break;
  2291.  
  2292.                         default:
  2293.  
  2294.                             String = NULL;
  2295.                             break;
  2296.                     }
  2297.                 }
  2298.  
  2299.                 if(!String)
  2300.                 {
  2301.                     switch(Code)
  2302.                     {
  2303.                         case 0x5A:
  2304.  
  2305.                             String = "\033OP";
  2306.                             break;
  2307.  
  2308.                         case 0x5B:
  2309.  
  2310.                             String = "\033OQ";
  2311.                             break;
  2312.  
  2313.                         case 0x5C:
  2314.  
  2315.                             String = "\033OR";
  2316.                             break;
  2317.  
  2318.                         case 0x5D:
  2319.  
  2320.                             String = "\033OS";
  2321.                             break;
  2322.                     }
  2323.                 }
  2324.  
  2325.                     /* Return the PFx key code. */
  2326.  
  2327.                 if(String)
  2328.                 {
  2329.                     if(Buffer)
  2330.                         memcpy(Buffer,String,3);
  2331.  
  2332.                     if(Len)
  2333.                         *Len = 3;
  2334.  
  2335.                     return('\033');
  2336.                 }
  2337.             }
  2338.  
  2339.                 /* Does it have a shift qualifier set? */
  2340.  
  2341.             if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  2342.             {
  2343.                     /* Do the conversion... */
  2344.  
  2345.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Code,Prev,ConvertBuffer,1))
  2346.                 {
  2347.                         /* Did it produce a tab key? If so, transfer
  2348.                          * Esc tab instead.
  2349.                          */
  2350.  
  2351.                     if(ConvertBuffer[0] == '\t')
  2352.                     {
  2353.                         if(Len)
  2354.                             *Len = 2;
  2355.  
  2356.                         if(Buffer)
  2357.                             memcpy(Buffer,"\033\t",2);
  2358.  
  2359.                         return('\033');
  2360.                     }
  2361.                 }
  2362.             }
  2363.  
  2364.                 /* Does it have the control qualifier set? */
  2365.  
  2366.             if(Qualifier & IEQUALIFIER_CONTROL)
  2367.             {
  2368.                     /* Do the conversion... */
  2369.  
  2370.                 if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Code,Prev,ConvertBuffer,1))
  2371.                 {
  2372.                         /* Did it produce a space or an `at' sign? */
  2373.  
  2374.                     switch(ConvertBuffer[0])
  2375.                     {
  2376.                             /* NUL */
  2377.  
  2378.                         case ' ':
  2379.                         case '@':
  2380.                         case '2':
  2381.  
  2382.                             if(Len)
  2383.                                 *Len = 1;
  2384.  
  2385.                             if(Buffer)
  2386.                                 Buffer[0] = 0;
  2387.  
  2388.                             return(0);
  2389.  
  2390.                             /* Escape */
  2391.  
  2392.                         case '3':
  2393.                         case '[':
  2394.  
  2395.                             if(Len)
  2396.                                 *Len = 1;
  2397.  
  2398.                             if(Buffer)
  2399.                                 Buffer[0] = 0x1B;
  2400.  
  2401.                             return(0x1B);
  2402.  
  2403.                             /* FS */
  2404.  
  2405.                         case '4':
  2406.                         case '/':
  2407.  
  2408.                             if(Len)
  2409.                                 *Len = 1;
  2410.  
  2411.                             if(Buffer)
  2412.                                 Buffer[0] = 0x1C;
  2413.  
  2414.                             return(0x1C);
  2415.  
  2416.                             /* GS */
  2417.  
  2418.                         case '5':
  2419.                         case ']':
  2420.  
  2421.                             if(Len)
  2422.                                 *Len = 1;
  2423.  
  2424.                             if(Buffer)
  2425.                                 Buffer[0] = 0x1D;
  2426.  
  2427.                             return(0x1D);
  2428.  
  2429.                             /* RS */
  2430.  
  2431.                         case '6':
  2432.                         case '~':
  2433.  
  2434.                             if(Len)
  2435.                                 *Len = 1;
  2436.  
  2437.                             if(Buffer)
  2438.                                 Buffer[0] = 0x1E;
  2439.  
  2440.                             return(0x1E);
  2441.  
  2442.  
  2443.                             /* US */
  2444.  
  2445.                         case '7':
  2446.                         case '?':
  2447.  
  2448.                             if(Len)
  2449.                                 *Len = 1;
  2450.  
  2451.                             if(Buffer)
  2452.                                 Buffer[0] = 0x1F;
  2453.  
  2454.                             return(0x1F);
  2455.                     }
  2456.                 }
  2457.             }
  2458.         }
  2459.  
  2460.             /* Do the final conversion... */
  2461.  
  2462.         if(Actual = ConvertKey(Qualifier,Code,Prev,ConvertBuffer,256))
  2463.         {
  2464.                 /* Are we to swap the backspace and
  2465.                  * delete keys?
  2466.                  */
  2467.  
  2468.             if(Config -> EmulationConfig -> SwapBSDelete)
  2469.             {
  2470.                 register WORD i;
  2471.  
  2472.                 for(i = 0 ; i < Actual ; i++)
  2473.                 {
  2474.                     if(ConvertBuffer[i] == BKS)
  2475.                         ConvertBuffer[i] = DEL;
  2476.                     else
  2477.                     {
  2478.                         if(ConvertBuffer[i] == DEL)
  2479.                             ConvertBuffer[i] = BKS;
  2480.                     }
  2481.                 }
  2482.             }
  2483.  
  2484.                 /* Translated sequence starts
  2485.                  * with a CSI, let's have a look
  2486.                  * at the associated control
  2487.                  * key.
  2488.                  */
  2489.  
  2490.             if(ConvertBuffer[0] == CSI)
  2491.             {
  2492.                 register WORD i;
  2493.  
  2494.                 for(i = 0 ; i < sizeof(SeqLens) ; i++)
  2495.                 {
  2496.                         /* Does it match? */
  2497.  
  2498.                     if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
  2499.                     {
  2500.                             /* Store the length. */
  2501.  
  2502.                         if(Len)
  2503.                             *Len = 1;
  2504.  
  2505.                             /* Store the result. */
  2506.  
  2507.                         if(Buffer)
  2508.                         {
  2509.                             Buffer[0] = ConversionTable[i] . Result;
  2510.                             Buffer[1] = 0;
  2511.                         }
  2512.  
  2513.                         return(ConversionTable[i] . Result);
  2514.                     }
  2515.                 }
  2516.             }
  2517.  
  2518.                 /* Store the number of characters converted. */
  2519.  
  2520.             if(Len)
  2521.                 *Len = Actual;
  2522.  
  2523.                 /* Store the converted characters. */
  2524.  
  2525.             if(Buffer)
  2526.                 memcpy(Buffer,ConvertBuffer,Actual);
  2527.  
  2528.             return(ConvertBuffer[0]);
  2529.         }
  2530.     }
  2531.  
  2532.     return(0);
  2533. }
  2534.  
  2535.     /* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
  2536.      *
  2537.      *    Convert a raw key information according to the
  2538.      *    current keymap settings.
  2539.      */
  2540.  
  2541. UBYTE __regargs
  2542. KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
  2543. {
  2544.         /* Is this really a keyboard event? */
  2545.  
  2546.     if(Massage -> Class == IDCMP_RAWKEY)
  2547.         return(ConvertTheKey(Buffer,Len,Massage -> Code,Massage -> Qualifier,*(ULONG *)Massage -> IAddress));
  2548.     else
  2549.     {
  2550.         if(Buffer)
  2551.             Buffer[0] = 0;
  2552.  
  2553.         if(Len)
  2554.             *Len = 0;
  2555.  
  2556.         return(0);
  2557.     }
  2558. }
  2559.  
  2560.     /* DoBackspace():
  2561.      *
  2562.      *    Special function: perform backspace.
  2563.      */
  2564.  
  2565. BYTE 
  2566. DoBackspace()
  2567. {
  2568.     if(CursorX)
  2569.     {
  2570.         WORD DeltaX,MinX;
  2571.  
  2572.         CursorX--;
  2573.  
  2574.             // What backspace mode are we in?
  2575.  
  2576.         switch(Config -> EmulationConfig -> DestructiveBackspace)
  2577.         {
  2578.                 // Do nothing
  2579.  
  2580.             case 0:
  2581.  
  2582.                 RepositionCursor();
  2583.                 break;
  2584.  
  2585.                 // Shift the line to the left
  2586.  
  2587.             case 2:
  2588.  
  2589.                 BackupRender();
  2590.  
  2591.                 RasterEraseCharacters(1);
  2592.  
  2593.                 if(Config -> EmulationConfig -> FontScale == SCALE_NORMAL)
  2594.                 {
  2595.                     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2596.                     {
  2597.                         DeltaX    = TextFontWidth;
  2598.                         MinX    = MUL_X(CursorX);
  2599.                     }
  2600.                     else
  2601.                     {
  2602.                         DeltaX    = TextFontWidth / 2;
  2603.                         MinX    = MUL_X(CursorX) / 2;
  2604.                     }
  2605.                 }
  2606.                 else
  2607.                 {
  2608.                     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2609.                     {
  2610.                         DeltaX    = TextFontWidth / 2;
  2611.                         MinX    = MUL_X(CursorX) / 2;
  2612.                     }
  2613.                     else
  2614.                     {
  2615.                         DeltaX    = TextFontWidth;
  2616.                         MinX    = MUL_X(CursorX);
  2617.                     }
  2618.                 }
  2619.  
  2620.                 ScrollLineEraseCharacters(1);
  2621.  
  2622.                 ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2623.  
  2624.                 BackupRender();
  2625.  
  2626.                 RepositionCursor();
  2627.  
  2628.                 break;
  2629.  
  2630.                 // Clear the character below the cursor
  2631.  
  2632.             default:
  2633.  
  2634.                 RepositionCursor();
  2635.  
  2636.                 ObtainSemaphore(RasterSemaphore);
  2637.  
  2638.                 Raster[CursorY * RasterWidth + CursorX] = ' ';
  2639.  
  2640.                 ReleaseSemaphore(RasterSemaphore);
  2641.  
  2642.                 BackupRender();
  2643.  
  2644.                 if(FontScalingRequired)
  2645.                     PrintScaled(" ",1,CurrentFontScale);
  2646.                 else
  2647.                     Text(RPort," ",1);
  2648.  
  2649.                 BackupRender();
  2650.  
  2651.                 break;
  2652.         }
  2653.     }
  2654.  
  2655.     return(FALSE);
  2656. }
  2657.  
  2658.     /* DoBeep():
  2659.      *
  2660.      *    The real interface to the beep routine.
  2661.      */
  2662.  
  2663. BYTE 
  2664. DoBeep()
  2665. {
  2666.     BellSignal();
  2667.  
  2668.     return(FALSE);
  2669. }
  2670.  
  2671.     /* DoxON():
  2672.      *
  2673.      *    Perform XON (stop data flow).
  2674.      */
  2675.  
  2676. BYTE 
  2677. DoxON()
  2678. {
  2679.     if(Config -> SerialConfig -> xONxOFF)
  2680.         Status = STATUS_HOLDING;
  2681.  
  2682.     return(FALSE);
  2683. }
  2684.  
  2685.     /* DoLF():
  2686.      *
  2687.      *    Special function: perform line feed.
  2688.      */
  2689.  
  2690. BYTE 
  2691. DoLF()
  2692. {
  2693.     DownLine();
  2694.  
  2695.     RepositionCursor();
  2696.  
  2697.     return(FALSE);
  2698. }
  2699.  
  2700.     /* DoShiftIn():
  2701.      *
  2702.      *    Special function: Shift into graphics mode
  2703.      */
  2704.  
  2705. BYTE 
  2706. DoShiftIn()
  2707. {
  2708.     if(CharMode[1] == TABLE_GFX && GFX)
  2709.         CurrentFont = GFX;
  2710.  
  2711.     if(CharMode[1] == TABLE_ASCII)
  2712.         CurrentFont = TextFont;
  2713.  
  2714.     SetFont(RPort,CurrentFont);
  2715.  
  2716.     ConOutputUpdate();
  2717.  
  2718.     Charset = 1;
  2719.  
  2720.     return(FALSE);
  2721. }
  2722.  
  2723.     /* DoShiftOut():
  2724.      *
  2725.      *    Special function: Shift out of graphics mode
  2726.      */
  2727.  
  2728. BYTE 
  2729. DoShiftOut()
  2730. {
  2731.     if(CharMode[0] == TABLE_GFX && GFX)
  2732.         CurrentFont = GFX;
  2733.  
  2734.     if(CharMode[0] == TABLE_ASCII)
  2735.         CurrentFont = TextFont;
  2736.  
  2737.     SetFont(RPort,CurrentFont);
  2738.  
  2739.     ConOutputUpdate();
  2740.  
  2741.     Charset = 0;
  2742.  
  2743.     return(FALSE);
  2744. }
  2745.  
  2746.     /* DoCR_LF():
  2747.      *
  2748.      *    Special function: perform carriage return and line feed.
  2749.      */
  2750.  
  2751. BYTE 
  2752. DoCR_LF()
  2753. {
  2754.     CursorX = 0;
  2755.  
  2756.     DownLine();
  2757.  
  2758.     RepositionCursor();
  2759.  
  2760.     return(FALSE);
  2761. }
  2762.  
  2763.     /* DoFF():
  2764.      *
  2765.      *    Special function: perform form feed.
  2766.      */
  2767.  
  2768. BYTE 
  2769. DoFF()
  2770. {
  2771.     if(Config -> EmulationConfig -> NewLineMode)
  2772.     {
  2773.         CursorX = 0;
  2774.  
  2775.         DoCR_LF();
  2776.     }
  2777.     else
  2778.     {
  2779.         EraseScreen("2");
  2780.  
  2781.         CursorX = CursorY = 0;
  2782.  
  2783.         RepositionCursor();
  2784.  
  2785.         ConFontScaleUpdate();
  2786.     }
  2787.  
  2788.     return(FALSE);
  2789. }
  2790.  
  2791.     /* DoLF_FF_VT():
  2792.      *
  2793.      *    Special function: handle line feed, form feed and vertical
  2794.      *    tab.
  2795.      */
  2796.  
  2797. BYTE 
  2798. DoLF_FF_VT()
  2799. {
  2800.     if(Config -> EmulationConfig -> NewLineMode)
  2801.         DoCR_LF();
  2802.     else
  2803.         DoLF();
  2804.  
  2805.     return(FALSE);
  2806. }
  2807.  
  2808.     /* DoCR():
  2809.      *
  2810.      *    Special function: handle carriage return.
  2811.      */
  2812.  
  2813. BYTE 
  2814. DoCR()
  2815. {
  2816.     if(Config -> EmulationConfig -> NewLineMode)
  2817.         DoCR_LF();
  2818.     else
  2819.     {
  2820.         CursorX = 0;
  2821.  
  2822.         RepositionCursor();
  2823.     }
  2824.  
  2825.     return(FALSE);
  2826. }
  2827.  
  2828.     /* DoTab():
  2829.      *
  2830.      *    Special function: handle tab, move cursor to next
  2831.      *    tab stop.
  2832.      */
  2833.  
  2834. BYTE 
  2835. DoTab()
  2836. {
  2837.     WORD Column;
  2838.  
  2839.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2840.         Column = LastColumn;
  2841.     else
  2842.         Column = ((LastColumn + 1) / 2) - 1;
  2843.  
  2844.     if(Config -> EmulationConfig -> LineWrap)
  2845.     {
  2846.         if(CursorX >= LastColumn)
  2847.         {
  2848.             CursorX = 0;
  2849.  
  2850.             DownLine();
  2851.         }
  2852.         else
  2853.         {
  2854.             while(CursorX < Column)
  2855.             {
  2856.                 CursorX++;
  2857.  
  2858.                 if(TabStops[CursorX])
  2859.                     break;
  2860.             }
  2861.         }
  2862.     }
  2863.     else
  2864.     {
  2865.         while(CursorX < Column)
  2866.         {
  2867.             CursorX++;
  2868.  
  2869.             if(TabStops[CursorX])
  2870.                 break;
  2871.         }
  2872.     }
  2873.  
  2874.     RepositionCursor();
  2875.  
  2876.     return(FALSE);
  2877. }
  2878.  
  2879.     /* DoEnq():
  2880.      *
  2881.      *    Special function: send answerback message.
  2882.      */
  2883.  
  2884. BYTE 
  2885. DoEnq()
  2886. {
  2887.     if(Config -> EmulationConfig -> AnswerBack[0])
  2888.         SerialCommand(Config -> EmulationConfig -> AnswerBack);
  2889.  
  2890.     return(FALSE);
  2891. }
  2892.  
  2893.     /* DoEsc():
  2894.      *
  2895.      *    Start new control sequence.
  2896.      */
  2897.  
  2898. BYTE 
  2899. DoEsc()
  2900. {
  2901.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2902.         (* ConDump)("^",1);
  2903.  
  2904.     return(TRUE);
  2905. }
  2906.  
  2907.     /* DoCsi():
  2908.      *
  2909.      *    Start new control sequence.
  2910.      */
  2911.  
  2912. BYTE 
  2913. DoCsi()
  2914. {
  2915.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2916.         (* ConDump)("^[",2);
  2917.  
  2918.     ParseCode('[');
  2919.  
  2920.     return(TRUE);
  2921. }
  2922.  
  2923.     /* DoNewEsc(UBYTE Char):
  2924.      *
  2925.      *    Start new control sequence.
  2926.      */
  2927.  
  2928. BYTE 
  2929. DoNewEsc(UBYTE Char)
  2930. {
  2931.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2932.         (* ConDump)("^",1);
  2933.  
  2934.     DoCancel();
  2935.  
  2936.     return(TRUE);
  2937. }
  2938.  
  2939.     /* DoNewCsi(UBYTE Char):
  2940.      *
  2941.      *    Start new control sequence.
  2942.      */
  2943.  
  2944. BYTE 
  2945. DoNewCsi(UBYTE Char)
  2946. {
  2947.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  2948.         (* ConDump)("^[",2);
  2949.  
  2950.     DoCancel();
  2951.  
  2952.     return(ParseCode('['));
  2953. }
  2954.  
  2955. STATIC STRPTR    CR_Translation,
  2956.         LF_Translation;
  2957. STATIC WORD    CR_Trans_Len,
  2958.         LF_Trans_Len;
  2959.  
  2960. STATIC LONG __regargs
  2961. Translate_CR_LF_1(register STRPTR Data,register LONG Size)
  2962. {
  2963.     register STRPTR    String    = Data;
  2964.     register LONG    Count    = 0;
  2965.     register UBYTE    c;
  2966.  
  2967.     while(Size--)
  2968.     {
  2969.         switch(c = *Data++)
  2970.         {
  2971.             case '\r':
  2972.  
  2973.                 if(CR_Trans_Len)
  2974.                 {
  2975.                     *String++ = *CR_Translation;
  2976.  
  2977.                     Count++;
  2978.                 }
  2979.  
  2980.                 break;
  2981.  
  2982.             case '\n':
  2983.  
  2984.                 if(LF_Trans_Len)
  2985.                 {
  2986.                     *String++ = *LF_Translation;
  2987.  
  2988.                     Count++;
  2989.                 }
  2990.  
  2991.                 break;
  2992.  
  2993.             default:
  2994.  
  2995.                 *String++ = c;
  2996.  
  2997.                 Count++;
  2998.  
  2999.                 break;
  3000.         }
  3001.     }
  3002.  
  3003.     return(Count);
  3004. }
  3005.  
  3006. STATIC LONG __regargs
  3007. Translate_CR_LF_2x2(register STRPTR Data,register LONG Size)
  3008. {
  3009.     register STRPTR    String    = Data;
  3010.     register LONG    Count    = 0;
  3011.     register UBYTE    c;
  3012.  
  3013.     /* ALWAYS */
  3014.     {
  3015.         register BOOL GotIt = FALSE;
  3016.         register LONG i;
  3017.  
  3018.         for(i = 0 ; i < Size ; i++)
  3019.         {
  3020.             if(String[i] == '\r' || String[i] == '\n')
  3021.             {
  3022.                 GotIt = TRUE;
  3023.  
  3024.                 break;
  3025.             }
  3026.         }
  3027.  
  3028.         if(GotIt)
  3029.         {
  3030.             CopyMem(Data,StripBuffer,Size);
  3031.  
  3032.             String    = Data;
  3033.             Data    = StripBuffer;
  3034.         }
  3035.         else
  3036.             return(Size);
  3037.     }
  3038.  
  3039.     while(Size--)
  3040.     {
  3041.         switch(c = *Data++)
  3042.         {
  3043.             case '\r':
  3044.  
  3045.                 if(CR_Trans_Len)
  3046.                 {
  3047.                     register WORD i;
  3048.  
  3049.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3050.                     {
  3051.                         *String++ = CR_Translation[i];
  3052.  
  3053.                         Count++;
  3054.                     }
  3055.                 }
  3056.  
  3057.                 break;
  3058.  
  3059.             case '\n':
  3060.  
  3061.                 if(LF_Trans_Len)
  3062.                 {
  3063.                     register WORD i;
  3064.  
  3065.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3066.                     {
  3067.                         *String++ = LF_Translation[i];
  3068.  
  3069.                         Count++;
  3070.                     }
  3071.                 }
  3072.  
  3073.                 break;
  3074.  
  3075.             default:
  3076.  
  3077.                 *String++ = c;
  3078.  
  3079.                 Count++;
  3080.  
  3081.                 break;
  3082.         }
  3083.     }
  3084.  
  3085.     return(Count);
  3086. }
  3087.  
  3088. STATIC LONG __regargs
  3089. Translate_CR_LF_2LF(register STRPTR Data,register LONG Size)
  3090. {
  3091.     register STRPTR    String    = Data;
  3092.     register LONG    Count    = 0;
  3093.     register UBYTE    c;
  3094.  
  3095.     /* ALWAYS */
  3096.     {
  3097.         register BOOL GotIt = FALSE;
  3098.         register LONG i;
  3099.  
  3100.         for(i = 0 ; i < Size ; i++)
  3101.         {
  3102.             if(String[i] == '\n')
  3103.             {
  3104.                 GotIt = TRUE;
  3105.  
  3106.                 break;
  3107.             }
  3108.         }
  3109.  
  3110.         if(GotIt)
  3111.         {
  3112.             CopyMem(Data,StripBuffer,Size);
  3113.  
  3114.             String    = Data;
  3115.             Data    = StripBuffer;
  3116.         }
  3117.         else
  3118.             return(Size);
  3119.     }
  3120.  
  3121.     while(Size--)
  3122.     {
  3123.         switch(c = *Data++)
  3124.         {
  3125.             case '\r':
  3126.  
  3127.                 if(CR_Trans_Len)
  3128.                 {
  3129.                     register WORD i;
  3130.  
  3131.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3132.                     {
  3133.                         *String++ = CR_Translation[i];
  3134.  
  3135.                         Count++;
  3136.                     }
  3137.                 }
  3138.  
  3139.                 break;
  3140.  
  3141.             case '\n':
  3142.  
  3143.                 if(LF_Trans_Len)
  3144.                 {
  3145.                     register WORD i;
  3146.  
  3147.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3148.                     {
  3149.                         *String++ = LF_Translation[i];
  3150.  
  3151.                         Count++;
  3152.                     }
  3153.                 }
  3154.  
  3155.                 break;
  3156.  
  3157.             default:
  3158.  
  3159.                 *String++ = c;
  3160.  
  3161.                 Count++;
  3162.  
  3163.                 break;
  3164.         }
  3165.     }
  3166.  
  3167.     return(Count);
  3168. }
  3169.  
  3170. STATIC LONG __regargs
  3171. Translate_CR_LF_2CR(register STRPTR Data,register LONG Size)
  3172. {
  3173.     register STRPTR    String    = Data;
  3174.     register LONG    Count    = 0;
  3175.     register UBYTE    c;
  3176.  
  3177.     /* ALWAYS */
  3178.     {
  3179.         register BOOL GotIt = FALSE;
  3180.         register LONG i;
  3181.  
  3182.         for(i = 0 ; i < Size ; i++)
  3183.         {
  3184.             if(String[i] == '\r')
  3185.             {
  3186.                 GotIt = TRUE;
  3187.  
  3188.                 break;
  3189.             }
  3190.         }
  3191.  
  3192.         if(GotIt)
  3193.         {
  3194.             CopyMem(Data,StripBuffer,Size);
  3195.  
  3196.             String    = Data;
  3197.             Data    = StripBuffer;
  3198.         }
  3199.         else
  3200.             return(Size);
  3201.     }
  3202.  
  3203.     while(Size--)
  3204.     {
  3205.         switch(c = *Data++)
  3206.         {
  3207.             case '\r':
  3208.  
  3209.                 if(CR_Trans_Len)
  3210.                 {
  3211.                     register WORD i;
  3212.  
  3213.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3214.                     {
  3215.                         *String++ = CR_Translation[i];
  3216.  
  3217.                         Count++;
  3218.                     }
  3219.                 }
  3220.  
  3221.                 break;
  3222.  
  3223.             case '\n':
  3224.  
  3225.                 if(LF_Trans_Len)
  3226.                 {
  3227.                     register WORD i;
  3228.  
  3229.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3230.                     {
  3231.                         *String++ = LF_Translation[i];
  3232.  
  3233.                         Count++;
  3234.                     }
  3235.                 }
  3236.  
  3237.                 break;
  3238.  
  3239.             default:
  3240.  
  3241.                 *String++ = c;
  3242.  
  3243.                 Count++;
  3244.  
  3245.                 break;
  3246.         }
  3247.     }
  3248.  
  3249.     return(Count);
  3250. }
  3251.  
  3252. VOID
  3253. Update_CR_LF_Translation()
  3254. {
  3255.     Forbid();
  3256.  
  3257.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CRLF || Config -> TerminalConfig -> ReceiveCR == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_CRLF)
  3258.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize / 2;
  3259.     else
  3260.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize;
  3261.  
  3262.     switch(Config -> TerminalConfig -> ReceiveCR)
  3263.     {
  3264.         case EOL_IGNORE:
  3265.  
  3266.             CR_Trans_Len = 0;
  3267.             break;
  3268.  
  3269.         case EOL_CR:
  3270.  
  3271.             CR_Trans_Len    = 1;
  3272.             CR_Translation    = "\r";
  3273.             break;
  3274.  
  3275.         case EOL_LF:
  3276.  
  3277.             CR_Trans_Len    = 1;
  3278.             CR_Translation    = "\n";
  3279.             break;
  3280.  
  3281.         case EOL_CRLF:
  3282.  
  3283.             CR_Trans_Len    = 2;
  3284.             CR_Translation    = "\r\n";
  3285.             break;
  3286.  
  3287.         case EOL_LFCR:
  3288.  
  3289.             CR_Trans_Len    = 2;
  3290.             CR_Translation    = "\n\r";
  3291.             break;
  3292.     }
  3293.  
  3294.     switch(Config -> TerminalConfig -> ReceiveLF)
  3295.     {
  3296.         case EOL_IGNORE:
  3297.  
  3298.             LF_Trans_Len = 0;
  3299.             break;
  3300.  
  3301.         case EOL_LF:
  3302.  
  3303.             LF_Trans_Len    = 1;
  3304.             LF_Translation    = "\n";
  3305.             break;
  3306.  
  3307.         case EOL_CR:
  3308.  
  3309.             LF_Trans_Len    = 1;
  3310.             LF_Translation    = "\r";
  3311.             break;
  3312.  
  3313.         case EOL_LFCR:
  3314.  
  3315.             LF_Trans_Len    = 2;
  3316.             LF_Translation    = "\n\r";
  3317.             break;
  3318.  
  3319.         case EOL_CRLF:
  3320.  
  3321.             LF_Trans_Len    = 2;
  3322.             LF_Translation    = "\r\n";
  3323.             break;
  3324.     }
  3325.  
  3326.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CR && Config -> TerminalConfig -> ReceiveLF == EOL_LF)
  3327.         Translate_CR_LF = NULL;
  3328.     else
  3329.     {
  3330.         if(LF_Trans_Len <= 1 && CR_Trans_Len <= 1)
  3331.             Translate_CR_LF = Translate_CR_LF_1;
  3332.         else
  3333.         {
  3334.             if(LF_Trans_Len == 2 && CR_Trans_Len == 2)
  3335.                 Translate_CR_LF = Translate_CR_LF_2x2;
  3336.             else
  3337.             {
  3338.                 if(LF_Trans_Len == 2)
  3339.                     Translate_CR_LF = Translate_CR_LF_2LF;
  3340.                 else
  3341.                 {
  3342.                     if(CR_Trans_Len == 2)
  3343.                         Translate_CR_LF = Translate_CR_LF_2CR;
  3344.                     else
  3345.                         Translate_CR_LF = Translate_CR_LF_1;
  3346.                 }
  3347.             }
  3348.         }
  3349.     }
  3350.  
  3351.     Permit();
  3352. }
  3353.