Annotation of sbbs/sbbs3/ctrl/emulvt.pas, revision 1.1.1.1

1.1       root        1: {*_* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                      2: 
                      3: Program:      EMULVT.PAS
                      4: Description:  Delphi component which does Ansi terminal emulation
                      5:               Not every escape sequence is implemented, but a large subset.
                      6: Author:       Fran�ois PIETTE
                      7: EMail:        http://users.swing.be/francois.piette  [email protected]
                      8:               http://www.rtfm.be/fpiette             [email protected]
                      9:               [email protected]
                     10: Creation:     May, 1996
                     11: Version:      2.16
                     12: Support:      Use the mailing list [email protected] See website for details.
                     13: Legal issues: Copyright (C) 1997-2000 by Fran�ois PIETTE
                     14:               Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56
                     15:               <[email protected]>
                     16: 
                     17:               This software is provided 'as-is', without any express or
                     18:               implied warranty.  In no event will the author be held liable
                     19:               for any  damages arising from the use of this software.
                     20: 
                     21:               Permission is granted to anyone to use this software for any
                     22:               purpose, including commercial applications, and to alter it
                     23:               and redistribute it freely, subject to the following
                     24:               restrictions:
                     25: 
                     26:               1. The origin of this software must not be misrepresented,
                     27:                  you must not claim that you wrote the original software.
                     28:                  If you use this software in a product, an acknowledgment
                     29:                  in the product documentation would be appreciated but is
                     30:                  not required.
                     31: 
                     32:               2. Altered source versions must be plainly marked as such, and
                     33:                  must not be misrepresented as being the original software.
                     34: 
                     35:               3. This notice may not be removed or altered from any source
                     36:                  distribution.
                     37: 
                     38:               4. You must register this software by sending a picture postcard
                     39:                  to the author. Use a nice stamp and mention your name, street
                     40:                  address, EMail address and any comment you like to say.
                     41: 
                     42: Updates:
                     43: Jul 22, 1997  Some optimization
                     44:               Adapted to Delphi 3
                     45: Sep 05, 1997  Version 2.01
                     46: Dec 16, 1997  V2.02 Corrected a bug int the paint routine which caused GDI
                     47:                     resource leak when color was used.
                     48: Feb 24, 1998  V2.03 Added AddFKey function
                     49: Jul 15, 1998  V2.04 Adapted to Delphi 4 (moved DoKeyBuffer to protected section)
                     50: Dec 04, 1998  V2.05 Added 'single char paint' and 'char zoom' features.
                     51: Dec 09, 1998  V2.10 Added graphic char drawing using graphic primitives
                     52:                     Added (with permission) scroll back code developed by Steve
                     53:                     Endicott <[email protected]>
                     54: Dec 21, 1998  V2.11 Corrected some screen update problems related to scrollback.
                     55:                     Added fixes from Steve Endicott.
                     56:                     Beautified code.
                     57: Mar 14, 1999  V2.12 Added OnKeyDown event.
                     58:                     Corrected a missing band at right of screen when painting.
                     59: Aug 15, 1999  V2.13 Moved KeyPress procedure to public section for BCB4 compat.
                     60: Aug 20, 1999  V2.14 Added compile time options. Revised for BCB4.
                     61: Nov 12, 1999  V2.15 Corrected display attribute error in delete line.
                     62:                     Checked for range in SetLines/GetLine
                     63: Aug 09, 2000  V2.16 Wilfried Mestdagh" <[email protected]> and
                     64:                     Steve Endicott <[email protected]> corrected a
                     65:                     bug related to scroll back buffer. See WM + SE 09/08/00
                     66:                     tags in code.
                     67: 
                     68:  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                     69: unit Emulvt;
                     70: 
                     71: {$B-}           { Enable partial boolean evaluation   }
                     72: {$T-}           { Untyped pointers                    }
                     73: {$X+}           { Enable extended syntax              }
                     74: {$IFNDEF VER80} { Not for Delphi 1                    }
                     75:     {$H+}       { Use long strings                    }
                     76:     {$J+}       { Allow typed constant to be modified }
                     77: {$ENDIF}
                     78: {$IFDEF VER110} { C++ Builder V3.0                    }
                     79:     {$ObjExportAll On}
                     80: {$ENDIF}
                     81: {$IFDEF VER125} { C++ Builder V4.0                    }
                     82:     {$ObjExportAll On}
                     83: {$ENDIF}
                     84: 
                     85: interface
                     86: 
                     87: {$DEFINE SINGLE_CHAR_PAINT}
                     88: {$DEFINE CHAR_ZOOM}
                     89: 
                     90: uses
                     91:   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
                     92:   Forms, Dialogs, StdCtrls, ClipBrd;
                     93: 
                     94: const
                     95:   EmulVTVersion      = 216;
                     96:   CopyRight : String = ' TEmulVT (c) 1996-2000 F. Piette V2.16 ';
                     97:   MAX_ROW            = 50; 
                     98:   MAX_COL            = 132;
                     99:   TopMargin          = 4;
                    100:   LeftMargin         = 6;
                    101:   RightMargin        = 6;
                    102:   BottomMargin       = 4;
                    103:   NumPaletteEntries  = 16;
                    104: 
                    105: type
                    106:   TBackColors     = (vtsBlack, vtsRed,     vtsGreen, vtsYellow,
                    107:                      vtsBlue,  vtsMagenta, vtsCyan,  vtsWhite);
                    108: 
                    109:   TScreenOption   = (vtoBackColor, vtoCopyBackOnClear);
                    110:   TScreenOptions  = set of TScreenOption;
                    111:   TXlatTable      = array [0..255] of char;
                    112:   PXlatTable      = ^TXlatTable;
                    113:   TFuncKeyValue   = String[50];
                    114:   PFuncKeyValue   = ^TFuncKeyValue;
                    115:   TFuncKey        = record
                    116:                         ScanCode : Char;
                    117:                         Shift    : TShiftState;
                    118:                         Ext      : Boolean;
                    119:                         Value    : TFuncKeyValue;
                    120:                     end;
                    121:   TFuncKeysTable  = array [0..63] of TFuncKey;
                    122:   PFuncKeysTable  = ^TFuncKeysTable;
                    123:   TKeyBufferEvent = procedure (Sender : TObject; Buffer : PChar; Len : Integer) of object;
                    124:   TKeyDownEvent   = procedure (Sender        : TObject;
                    125:                                var VirtKey   : Integer;
                    126:                                var Shift     : TShiftState;
                    127:                                var ShiftLock : Boolean;
                    128:                                var ScanCode  : Char;
                    129:                                var Ext       : Boolean) of object;
                    130: 
                    131: 
                    132: type
                    133:   { TLine is an object used to hold one line of text on screen }
                    134:   TLine = class(TObject)
                    135:   public
                    136:     Txt : array [0..MAX_COL] of Char;
                    137:     Att : array [0..MAX_COL] of Byte;
                    138:     constructor Create;
                    139:     procedure   Clear(Attr : Byte);
                    140:   end;
                    141:   TLineArray      = array [0..16382] of TLine;
                    142:   PLineArray      = ^TLineArray;
                    143: 
                    144:   { TScreen is an object to hold an entire screen of line and handle }
                    145:   { Ansi escape sequences to update this virtual screen              }
                    146:   TScreen = class(TObject)
                    147:   public
                    148:     FLines           : PLineArray;
                    149:     FRow             : Integer;
                    150:     FCol             : Integer;
                    151:     FRowSaved        : Integer;
                    152:     FColSaved        : Integer;
                    153:     FScrollRowTop    : Integer;
                    154:     FScrollRowBottom : Integer;
                    155:     FAttribute       : Byte;
                    156:     FForceHighBit    : Boolean;
                    157:     FReverseVideo    : Boolean;
                    158:     FUnderLine       : Boolean;
                    159:     FRowCount        : Integer;
                    160:     FColCount        : Integer;
                    161:     FBackRowCount    : Integer;
                    162:     FBackEndRow      : Integer;
                    163:     FBackColor       : TBackColors;
                    164:     FOptions         : TScreenOptions;
                    165:     FEscBuffer       : String[80];
                    166:     FEscFlag         : Boolean;
                    167:     Focused          : Boolean;
                    168:     FAutoLF          : Boolean;
                    169:     FAutoCR          : Boolean;
                    170:     FAutoWrap        : Boolean;
                    171:     FCursorOff       : Boolean;
                    172:     FCKeyMode        : Boolean;
                    173:     FNoXlat          : Boolean;
                    174:     FNoXlatInitial   : Boolean;
                    175:     FCntLiteral      : Integer;
                    176:     FCarbonMode      : Boolean;
                    177:     FXlatInputTable  : PXlatTable;
                    178:     FXlatOutputTable : PXlatTable;
                    179:     FCharSetG0       : Char;
                    180:     FCharSetG1       : Char;
                    181:     FCharSetG2       : Char;
                    182:     FCharSetG3       : Char;
                    183:     FAllInvalid      : Boolean;
                    184:     FInvRect         : TRect;
                    185:     FOnCursorVisible : TNotifyEvent;
                    186:     constructor Create;
                    187:     destructor  Destroy; override;
                    188:     procedure   AdjustFLines(NewCount : Integer);
                    189:     procedure   CopyScreenToBack;
                    190:     procedure   SetRowCount(NewCount : Integer);
                    191:     procedure   SetBackRowCount(NewCount : Integer);
                    192:     procedure   InvRect(nRow, nCol : Integer);
                    193:     procedure   InvClear;
                    194:     procedure   SetLines(I : Integer; Value : TLine);
                    195:     function    GetLines(I : Integer) : TLine;
                    196:     procedure   WriteChar(Ch : Char);
                    197:     procedure   WriteStr(Str : String);
                    198:     function    ReadStr : String;
                    199:     procedure   GotoXY(X, Y : Integer);
                    200:     procedure   WriteLiteralChar(Ch : Char);
                    201:     procedure   ProcessEscape(EscCmd : Char);
                    202:     procedure   SetAttr(Att : Char);
                    203:     procedure   CursorRight;
                    204:     procedure   CursorLeft;
                    205:     procedure   CursorDown;
                    206:     procedure   CursorUp;
                    207:     procedure   CarriageReturn;
                    208:     procedure   ScrollUp;
                    209:     procedure   ScrollDown;
                    210:     procedure   ClearScreen;
                    211:     procedure   BackSpace;
                    212:     procedure   Eol;
                    213:     procedure   Eop;
                    214:     procedure   ProcessESC_D;                { Index                   }
                    215:     procedure   ProcessESC_M;                { Reverse index           }
                    216:     procedure   ProcessESC_E;                { Next line               }
                    217:     procedure   ProcessCSI_u;                { Restore Cursor          }
                    218:     procedure   ProcessCSI_I;                { Select IBM char set     }
                    219:     procedure   ProcessCSI_J;                { Clear the screen        }
                    220:     procedure   ProcessCSI_K;                { Erase to End of Line    }
                    221:     procedure   ProcessCSI_L;                { Insert Line             }
                    222:     procedure   ProcessCSI_M;                { Delete Line             }
                    223:     procedure   ProcessCSI_m_lc;             { Select Attributes       }
                    224:     procedure   ProcessCSI_n_lc;             { Cursor position report  }
                    225:     procedure   ProcessCSI_at;               { Insert character        }
                    226:     procedure   ProcessCSI_r_lc;             { Scrolling margins       }
                    227:     procedure   ProcessCSI_s_lc;             { Save cursor location    }
                    228:     procedure   ProcessCSI_u_lc;             { Restore cursor location }
                    229:     procedure   ProcessCSI_7;                { Save cursor location    }
                    230:     procedure   ProcessCSI_8;                { Restore cursor location }
                    231:     procedure   ProcessCSI_H;                { Set Cursor Position     }
                    232:     procedure   ProcessCSI_h_lc;             { Terminal mode set       }
                    233:     procedure   ProcessCSI_l_lc;             { Terminal mode reset     }
                    234:     procedure   ProcessCSI_A;                { Cursor Up               }
                    235:     procedure   ProcessCSI_B;                { Cursor Down             }
                    236:     procedure   ProcessCSI_C;                { Cursor Right            }
                    237:     procedure   ProcessCSI_D;                { Cursor Left             }
                    238:     procedure   ProcessCSI_P;                { Delete Character        }
                    239:     procedure   ProcessCSI_S;                { Scroll up               }
                    240:     procedure   ProcessCSI_T;                { Scroll down             }
                    241:     procedure   process_charset_G0(EscCmd : Char);{ G0 character set   }
                    242:     procedure   process_charset_G1(EscCmd : Char);{ G1 character set   }
                    243:     procedure   process_charset_G2(EscCmd : Char);{ G2 character set   }
                    244:     procedure   process_charset_G3(EscCmd : Char);{ G3 character set   }
                    245:     procedure   UnimplementedEscape(EscCmd : Char);
                    246:     procedure   InvalidEscape(EscCmd : Char);
                    247:     function    GetEscapeParam(From : Integer; var Value : Integer) : Integer;
                    248:     property    OnCursorVisible : TNotifyEvent read  FonCursorVisible
                    249:                                                write FOnCursorVisible;
                    250:     property    Lines[I : Integer] : TLine read GetLines write SetLines;
                    251:   end;
                    252: 
                    253:   { TCustomEmulVT is an visual component wich does the actual display }
                    254:   { of a TScreen object wich is the virtual screen                    }
                    255:   { No property is published. See TEmulVT class                       }
                    256:   TCustomEmulVT = class(TCustomControl)
                    257:   private
                    258:     FScreen          : TScreen;
                    259:     FFileHandle      : TextFile;
                    260:     FCursorVisible   : Boolean;
                    261:     FCaretShown      : Boolean;
                    262:     FCaretCreated    : Boolean;
                    263:     FLineHeight      : Integer;
                    264:     FLineZoom        : Single;
                    265:     FCharWidth       : Integer;
                    266:     FCharZoom        : Single;
                    267:     FGraphicDraw     : Boolean;
                    268:     FInternalLeading : Integer;
                    269:     FBorderStyle     : TBorderStyle;
                    270:     FBorderWidth     : Integer;
                    271:     FAutoRepaint     : Boolean;
                    272:     FFont            : TFont;
                    273:     FVScrollBar      : TScrollBar;
                    274:     FTopLine         : Integer;
                    275:     FLocalEcho       : Boolean;
                    276:     FOnKeyBuffer     : TKeyBufferEvent;
                    277:     FOnKeyDown       : TKeyDownEvent;
                    278:     FFKeys           : Integer;
                    279:     FMonoChrome      : Boolean;
                    280:     FLog             : Boolean;
                    281:     FAppOnMessage    : TMessageEvent;
                    282:     FFlagCirconflexe : Boolean;
                    283:     FFlagTrema       : Boolean;
                    284:     FSelectRect      : TRect;
                    285:     FPal             : HPalette;
                    286:     FPaletteEntries  : array[0..NumPaletteEntries - 1] of TPaletteEntry;
                    287:     procedure   WMPaint(var Message: TWMPaint); message WM_PAINT;
                    288:     procedure   WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
                    289:     procedure   WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
                    290:     procedure   WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
                    291:     procedure   WMPaletteChanged(var Message : TMessage); message WM_PALETTECHANGED;
                    292:     procedure   VScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
                    293:     procedure   SetCaret;
                    294:     procedure   AdjustScrollBar;
                    295:     function    ProcessFKeys(ScanCode: Char; Shift: TShiftState; Ext: Boolean) : Boolean;
                    296:     function    FindFKeys(ScanCode: Char; Shift: TShiftState;
                    297:                           Ext: Boolean) : PFuncKeyValue;
                    298:     procedure   CursorVisibleEvent(Sender : TObject);
                    299:     procedure   SetFont(Value : TFont);
                    300:     procedure   SetAutoLF(Value : Boolean);
                    301:     procedure   SetAutoCR(Value : Boolean);
                    302:     procedure   SetXlat(Value : Boolean);
                    303:     procedure   SetLog(Value : Boolean);
                    304:     procedure   SetRows(Value : Integer);
                    305:     procedure   SetCols(Value : Integer);
                    306:     procedure   SetBackRows(Value : Integer);
                    307:     procedure   SetTopLine(Value : Integer);
                    308:     procedure   SetBackColor(Value : TBackColors);
                    309:     procedure   SetOptions(Value : TScreenOptions);
                    310:     procedure   SetLineHeight(Value : Integer);
                    311:     function    GetAutoLF : Boolean;
                    312:     function    GetAutoCR : Boolean;
                    313:     function    GetXlat : Boolean;
                    314:     function    GetRows : Integer;
                    315:     function    GetCols : Integer;
                    316:     function    GetBackRows : Integer;
                    317:     function    GetBackColor : TBackColors;
                    318:     function    GetOptions : TScreenOptions;
                    319:   protected
                    320:     procedure   AppMessageHandler(var Msg: TMsg; var Handled: Boolean);
                    321:     procedure   DoKeyBuffer(Buffer : PChar; Len : Integer); virtual;
                    322:     procedure   PaintGraphicChar(DC   : HDC;
                    323:                                  X, Y : Integer;
                    324:                                  rc   : PRect;
                    325:                                  ch   : Char);
                    326:   public
                    327:     constructor Create(AOwner: TComponent); override;
                    328:     destructor  Destroy; override;
                    329:     procedure   ShowCursor;
                    330:     procedure   SetCursor(Row, Col : Integer);
                    331:     procedure   WriteChar(Ch : Char);
                    332:     procedure   WriteStr(Str : String);
                    333:     procedure   WriteBuffer(Buffer : Pointer; Len : Integer);
                    334:     function    ReadStr : String;
                    335:     procedure   CopyHostScreen;
                    336:     procedure   Clear;
                    337:     procedure   UpdateScreen;
                    338:     function    SnapPixelToRow(Y : Integer) : Integer;
                    339:     function    SnapPixelToCol(X : Integer) : Integer;
                    340:     function    PixelToRow(Y : Integer) : Integer;
                    341:     function    PixelToCol(X : Integer) : Integer;
                    342:     procedure   MouseToCell(X, Y: Integer; var ACol, ARow: Longint);
                    343:     procedure   SetLineZoom(newValue : Single);
                    344:     procedure   SetCharWidth(newValue : Integer);
                    345:     procedure   SetCharZoom(newValue : Single);
                    346:     procedure   KeyPress(var Key: Char); override;
                    347:     property    LineZoom  : Single        read FLineZoom    write SetLineZoom;
                    348:     property    CharWidth : Integer       read FCharWidth   write SetCharWidth;
                    349:     property    CharZoom  : Single        read FCharZoom    write SetCharZoom;
                    350:     property    GraphicDraw : Boolean     read FGraphicDraw write FGraphicDraw;
                    351:     property    TopLine     : Integer     read FTopLine     write SetTopLine;
                    352:     property    VScrollBar  : TScrollBar  read FVScrollBar;
                    353:   private
                    354:     procedure   PaintOneLine(DC: HDC; Y, Y1 : Integer; const Line : TLine;
                    355:                              nColFrom : Integer; nColTo : Integer);
                    356:     procedure   SetupFont;
                    357:     property Text : String read ReadStr write WriteStr;
                    358:     property OnMouseMove;
                    359:     property OnMouseDown;
                    360:     property OnMouseUp;
                    361:     property OnClick;
                    362:     property OnKeyPress;
                    363:     property OnKeyBuffer : TKeyBufferEvent read FOnKeyBuffer write FOnKeyBuffer;
                    364:     property OnKeyDown   : TKeyDownEvent   read FOnKeyDown   write FOnKeyDown;
                    365:     property Ctl3D;
                    366:     property Align;
                    367:     property TabStop;
                    368:     property TabOrder;
                    369:     property BorderStyle: TBorderStyle read FBorderStyle write FBorderStyle;
                    370:     property AutoRepaint : Boolean     read FAutoRepaint write FAutoRepaint;
                    371:     property Font : TFont              read FFont        write SetFont;
                    372:     property LocalEcho : Boolean       read FLocalEcho   write FLocalEcho;
                    373:     property AutoLF : Boolean          read GetAutoLF    write SetAutoLF;
                    374:     property AutoCR : Boolean          read GetAutoCR    write SetAutoCR;
                    375:     property Xlat : Boolean            read GetXlat      write SetXlat;
                    376:     property MonoChrome : Boolean      read FMonoChrome  write FMonoChrome;
                    377:     property Log : Boolean             read FLog         write SetLog;
                    378:     property Rows : Integer            read GetRows      write SetRows;
                    379:     property Cols : Integer            read GetCols      write SetCols;
                    380:     property LineHeight : Integer      read FLineHeight  write SetLineHeight;
                    381:     property FKeys : Integer           read FFKeys       write FFKeys;
                    382:     property SelectRect : TRect        read FSelectRect  write FSelectRect;
                    383:     property BackRows : Integer        read GetBackRows  write SetBackRows;
                    384:     property BackColor : TBackColors   read GetBackColor write SetBackColor;
                    385:     property Options : TScreenOptions  read GetOptions   write SetOptions;
                    386:   end;
                    387: 
                    388:   { Same as TCustomEmulVT, but with published properties }
                    389:   TEmulVT = class(TCustomEmulVT)
                    390:   public
                    391:     property Screen : TScreen read FScreen;
                    392:     property SelectRect;
                    393:     property Text;
                    394:   published
                    395:     property OnMouseMove;
                    396:     property OnMouseDown;
                    397:     property OnMouseUp;
                    398:     property OnClick;
                    399:     property OnKeyPress;
                    400:     property OnKeyDown;
                    401:     property OnKeyBuffer;
                    402:     property Ctl3D;
                    403:     property Align;
                    404:     property BorderStyle;
                    405:     property AutoRepaint;
                    406:     property Font;
                    407:     property LocalEcho;
                    408:     property AutoLF;
                    409:     property AutoCR;
                    410:     property Xlat;
                    411:     property MonoChrome;
                    412:     property Log;
                    413:     property Rows;
                    414:     property Cols;
                    415:     property BackRows;
                    416:     property BackColor;
                    417:     property Options;
                    418:     property LineHeight;
                    419:     property CharWidth;
                    420:     property TabStop;
                    421:     property TabOrder;
                    422:     property FKeys;
                    423:   end;
                    424: 
                    425: const
                    426:   F_BLACK   = $00;
                    427:   F_BLUE    = $01;
                    428:   F_GREEN   = $02;
                    429:   F_CYAN    = $03;
                    430:   F_RED     = $04;
                    431:   F_MAGENTA = $05;
                    432:   F_BROWN   = $06;
                    433:   F_WHITE   = $07;
                    434: 
                    435:   B_BLACK   = $00;
                    436:   B_BLUE    = $01;
                    437:   B_GREEN   = $02;
                    438:   B_CYAN    = $03;
                    439:   B_RED     = $04;
                    440:   B_MAGENTA = $05;
                    441:   B_BROWN   = $06;
                    442:   B_WHITE   = $07;
                    443: 
                    444:   F_INTENSE = $08;
                    445:   B_BLINK   = $80;
                    446: 
                    447:   { Function keys (SCO Console) }
                    448:   FKeys1 : TFuncKeysTable = (
                    449:       (ScanCode: #$48; Shift: []; Ext: TRUE ; Value: #$1B + '[A'),   { UP    }
                    450:       (ScanCode: #$50; Shift: []; Ext: TRUE ; Value: #$1B + '[B'),   { DOWN  }
                    451:       (ScanCode: #$4D; Shift: []; Ext: TRUE ; Value: #$1B + '[C'),   { RIGHT }
                    452:       (ScanCode: #$4B; Shift: []; Ext: TRUE ; Value: #$1B + '[D'),   { LEFT  }
                    453:       (ScanCode: #$49; Shift: []; Ext: TRUE ; Value: #$1B + '[I'),   { PREV  }
                    454:       (ScanCode: #$51; Shift: []; Ext: TRUE ; Value: #$1B + '[G'),   { NEXT  }
                    455:       (ScanCode: #$47; Shift: []; Ext: TRUE ; Value: #$1B + '[H'),   { HOME  }
                    456:       (ScanCode: #$4F; Shift: []; Ext: TRUE ; Value: #$1B + '[F'),   { END   }
                    457:       (ScanCode: #$52; Shift: []; Ext: TRUE ; Value: #$1B + '[L'),   { INS   }
                    458:       (ScanCode: #$0F; Shift: []; Ext: FALSE; Value: #$1B + '[Z'),   { RTAB  }
                    459:       (ScanCode: #$53; Shift: []; Ext: TRUE ; Value: #$7F       ),   { DEL   }
                    460:       (ScanCode: #$3B; Shift: []; Ext: FALSE; Value: #$1B + '[M'),   { F1    }
                    461:       (ScanCode: #$3C; Shift: []; Ext: FALSE; Value: #$1B + '[N'),
                    462:       (ScanCode: #$3D; Shift: []; Ext: FALSE; Value: #$1B + '[O'),
                    463:       (ScanCode: #$3E; Shift: []; Ext: FALSE; Value: #$1B + '[P'),
                    464:       (ScanCode: #$3F; Shift: []; Ext: FALSE; Value: #$1B + '[Q'),
                    465:       (ScanCode: #$40; Shift: []; Ext: FALSE; Value: #$1B + '[R'),
                    466:       (ScanCode: #$41; Shift: []; Ext: FALSE; Value: #$1B + '[S'),
                    467:       (ScanCode: #$42; Shift: []; Ext: FALSE; Value: #$1B + '[T'),
                    468:       (ScanCode: #$43; Shift: []; Ext: FALSE; Value: #$1B + '[U'),
                    469:       (ScanCode: #$44; Shift: []; Ext: FALSE; Value: #$1B + '[V'),   { F10   }
                    470:       (ScanCode: #$85; Shift: []; Ext: FALSE; Value: #$1B + '[W'),   { F11   }
                    471:       (ScanCode: #$86; Shift: []; Ext: FALSE; Value: #$1B + '[X'),   { F12   }
                    472:       (ScanCode: #$3B; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[V'),{ SF1 should be 'Y' }
                    473:       (ScanCode: #$3C; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[Z'),
                    474:       (ScanCode: #$3D; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[a'),
                    475:       (ScanCode: #$3E; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[b'),
                    476:       (ScanCode: #$3F; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[c'),
                    477:       (ScanCode: #$40; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[d'),
                    478:       (ScanCode: #$41; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[e'),
                    479:       (ScanCode: #$42; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[f'),
                    480:       (ScanCode: #$43; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[g'),
                    481:       (ScanCode: #$44; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[h'),
                    482:       (ScanCode: #$85; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[i'),
                    483:       (ScanCode: #$86; Shift: [ssShift]; Ext: FALSE; Value: #$1B + '[j'),{ SF10 }
                    484:       (ScanCode: #$3B; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[k'), { CF1  }
                    485:       (ScanCode: #$3C; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[l'),
                    486:       (ScanCode: #$3D; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[m'),
                    487:       (ScanCode: #$3E; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[n'),
                    488:       (ScanCode: #$3F; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[o'),
                    489:       (ScanCode: #$40; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[p'),
                    490:       (ScanCode: #$41; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[q'),
                    491:       (ScanCode: #$42; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[r'),
                    492:       (ScanCode: #$43; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[s'),
                    493:       (ScanCode: #$44; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[t'),
                    494:       (ScanCode: #$85; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[u'),
                    495:       (ScanCode: #$86; Shift: [ssCtrl]; Ext: FALSE; Value: #$1B + '[v'),   { CF12 }
                    496:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    497:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    498:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    499:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    500:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    501:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    502:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    503:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    504:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    505:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    506:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    507:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    508:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    509:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    510:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    511:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    512:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         )
                    513:       );
                    514: 
                    515: { Alternate function keys (ordinary VT keys) }
                    516:   FKeys2 : TFuncKeysTable = (
                    517:       (ScanCode: #$48; Shift: []; Ext: TRUE ; Value: #$1B + '[A'),   { UP      }
                    518:       (ScanCode: #$50; Shift: []; Ext: TRUE ; Value: #$1B + '[B'),   { DOWN    }
                    519:       (ScanCode: #$4D; Shift: []; Ext: TRUE ; Value: #$1B + '[C'),   { RIGHT   }
                    520:       (ScanCode: #$4B; Shift: []; Ext: TRUE ; Value: #$1B + '[D'),   { LEFT    }
                    521:       (ScanCode: #$49; Shift: []; Ext: TRUE ; Value: #$1B + '[5~'),  { PREV    }
                    522:       (ScanCode: #$51; Shift: []; Ext: TRUE ; Value: #$1B + '[6~'),  { NEXT    }
                    523:       (ScanCode: #$52; Shift: []; Ext: TRUE ; Value: #$1B + '[2~'),  { INSERT  }
                    524:       (ScanCode: #$53; Shift: []; Ext: TRUE ; Value: #$7F       ),   { DELETE  }
                    525:       (ScanCode: #$3B; Shift: []; Ext: FALSE; Value: #$1B + 'OP'),   { F1->PF1 }
                    526:       (ScanCode: #$3C; Shift: []; Ext: FALSE; Value: #$1B + 'OQ'),   { F2->PF2 }
                    527:       (ScanCode: #$3D; Shift: []; Ext: FALSE; Value: #$1B + 'OR'),   { F3->PF3 }
                    528:       (ScanCode: #$3E; Shift: []; Ext: FALSE; Value: #$1B + 'OS'),   { F4->PF4 }
                    529:       (ScanCode: #$57; Shift: []; Ext: FALSE; Value: #$1B + '[28~'), { F11->Aide }
                    530:       (ScanCode: #$58; Shift: []; Ext: FALSE; Value: #$1B + '[29~'), { F12->Ex�cuter }
                    531:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    532:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    533:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    534:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    535:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    536:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    537:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    538:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    539:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    540:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    541:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    542:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    543:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    544:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    545:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    546:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    547:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    548:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    549:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    550:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    551:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    552:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    553:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    554:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    555:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    556:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    557:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    558:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    559:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    560:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    561:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    562:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    563:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    564:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    565:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    566:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    567:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    568:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    569:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    570:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    571:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    572:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    573:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    574:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    575:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    576:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    577:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    578:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    579:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    580:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         )
                    581:       );
                    582: 
                    583: { A-Series Telnet function keys (ordinary VT100 keys + specials) }
                    584:   FKeys3 : TFuncKeysTable = (
                    585:       (ScanCode: #$48; Shift: []; Ext: TRUE ; Value: #$1B + '[A'),   { UP      }
                    586:       (ScanCode: #$50; Shift: []; Ext: TRUE ; Value: #$1B + '[B'),   { DOWN    }
                    587:       (ScanCode: #$4D; Shift: []; Ext: TRUE ; Value: #$1B + '[C'),   { RIGHT   }
                    588:       (ScanCode: #$4B; Shift: []; Ext: TRUE ; Value: #$1B + '[D'),   { LEFT    }
                    589:       (ScanCode: #$49; Shift: []; Ext: TRUE ; Value: #$1B + '-'),    { PREV    }
                    590:       (ScanCode: #$51; Shift: []; Ext: TRUE ; Value: #$1B + '+'),    { NEXT    }
                    591:       (ScanCode: #$47; Shift: []; Ext: TRUE ; Value: #$1B + 'H'),    { HOME    }
                    592:       (ScanCode: #$47; Shift: [ssCtrl]; Ext: TRUE ; Value: #$1B + 'C'),{ HOME  }
                    593:       (ScanCode: #$4F; Shift: []; Ext: TRUE ; Value: #$1B + 'R'),    { END     }
                    594:       (ScanCode: #$52; Shift: []; Ext: TRUE ; Value: #$1B + 'I'),    { INSERT  }
                    595:       (ScanCode: #$53; Shift: []; Ext: TRUE ; Value: #$7F       ),   { DELETE  }
                    596:       (ScanCode: #$3B; Shift: []; Ext: FALSE; Value: #$1B + 'OP'),   { F1->PF1 }
                    597:       (ScanCode: #$3C; Shift: []; Ext: FALSE; Value: #$1B + 'OQ'),   { F2->PF2 }
                    598:       (ScanCode: #$3D; Shift: []; Ext: FALSE; Value: #$1B + 'OR'),   { F3->PF3 }
                    599:       (ScanCode: #$3E; Shift: []; Ext: FALSE; Value: #$1B + 'OS'),   { F4->PF4 }
                    600:       (ScanCode: #$43; Shift: []; Ext: FALSE; Value: #$1B + 'OP'),   { F9      }
                    601:       (ScanCode: #$44; Shift: []; Ext: FALSE; Value: ''),            { F10     }
                    602:       (ScanCode: #$57; Shift: []; Ext: FALSE; Value: #$1B + 'OQ'),   { F11     }
                    603:       (ScanCode: #$58; Shift: []; Ext: FALSE; Value: #$1B + 'OS'),   { F12     }
                    604:       (ScanCode: #$0F; Shift: []; Ext: FALSE; Value: #$1B + 'Z'),    { RTAB    }
                    605:       (ScanCode: #$40; Shift: []; Ext: FALSE; Value: #$1B + 'K'),    { F6      }
                    606:       (ScanCode: #$53; Shift: [ssCtrl]; Ext: TRUE ; Value: #$1B + 'D'), { CDEL }
                    607:       (ScanCode: #$52; Shift: [ssCtrl]; Ext: TRUE ; Value: #$1B + 'L'), { CINS }
                    608:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    609:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    610:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    611:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    612:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    613:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    614:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    615:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    616:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    617:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    618:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    619:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    620:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    621:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    622:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    623:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    624:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    625:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    626:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    627:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    628:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    629:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    630:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    631:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    632:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    633:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    634:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    635:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    636:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    637:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    638:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    639:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    640:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    641:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    642:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    643:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    644:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    645:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    646:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    647:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         ),
                    648:       (ScanCode: #$00; Shift: []; Ext: FALSE; Value: ''         )
                    649:       );
                    650: 
                    651:   { Ethernet to screen }
                    652:   ibm_iso8859_1_G0 : TXlatTable = (
                    653:       #$00, #$01, #$02, #$03, #$04, #$05, #$06, #$07,   { 00 - 07 }
                    654:       #$08, #$09, #$0A, #$0B, #$0C, #$0D, #$0E, #$0F,   { 08 - 0F }
                    655:       #$10, #$11, #$12, #$13, #$14, #$15, #$16, #$17,   { 10 - 17 }
                    656:       #$18, #$19, #$1A, #$1B, #$1C, #$1D, #$1E, #$1F,   { 18 - 1F }
                    657:       #$20, #$21, #$22, #$23, #$24, #$25, #$26, #$27,   { 20 - 27 }
                    658:       #$28, #$29, #$2A, #$2B, #$2C, #$2D, #$2E, #$2F,   { 28 - 2F }
                    659:       #$30, #$31, #$32, #$33, #$34, #$35, #$36, #$37,   { 30 - 37 }
                    660:       #$38, #$39, #$3A, #$3B, #$3C, #$3D, #$3E, #$3F,   { 38 - 3F }
                    661:       #$40, #$41, #$42, #$43, #$44, #$45, #$46, #$47,   { 40 - 47 }
                    662:       #$48, #$49, #$4A, #$4B, #$4C, #$4D, #$4E, #$4F,   { 48 - 4F }
                    663:       #$50, #$51, #$52, #$53, #$54, #$55, #$56, #$57,   { 50 - 57 }
                    664:       #$58, #$59, #$5A, #$5B, #$5C, #$5D, #$5E, #$5F,   { 58 - 5F }
                    665:       #$60, #$61, #$62, #$63, #$64, #$65, #$66, #$67,   { 60 - 67 }
                    666:       #$68, #$69, #$6A, #$6B, #$6C, #$6D, #$6E, #$6F,   { 68 - 6F }
                    667:       #$70, #$71, #$72, #$73, #$74, #$75, #$76, #$77,   { 70 - 77 }
                    668:       #$78, #$79, #$7A, #$7B, #$7C, #$7D, #$7E, #$7F,   { 78 - 7F }
                    669:       #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20,   { 80 - 87 }
                    670:       #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20,   { 88 - 8F }
                    671:       #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20,   { 90 - 97 }
                    672:       #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20,   { 98 - 9F }
                    673:       #$B1, #$AD, #$9B, #$9C, #$0F, #$9D, #$B3, #$15,   { A0 - A7 }
                    674:       #$20, #$43, #$A6, #$AE, #$AA, #$C4, #$52, #$C4,   { A8 - AF }
                    675:       #$F8, #$F1, #$FD, #$20, #$27, #$E6, #$14, #$FA,   { B0 - B7 }
                    676:       #$2C, #$20, #$A7, #$AF, #$AC, #$AB, #$20, #$A8,   { B8 - BF }
                    677:       #$41, #$41, #$41, #$41, #$8E, #$8F, #$92, #$80,   { C0 - C7 }
                    678:       #$45, #$45, #$45, #$45, #$45, #$49, #$49, #$49,   { C8 - CF }
                    679:       #$44, #$A5, #$4F, #$4F, #$4F, #$4F, #$4F, #$78,   { D0 - D7 }
                    680:       #$ED, #$55, #$55, #$55, #$55, #$59, #$70, #$E1,   { D8 - DF }
                    681:       #$85, #$A0, #$83, #$61, #$84, #$86, #$91, #$87,   { E0 - E7 }
                    682:       #$8A, #$82, #$88, #$89, #$8D, #$A1, #$8C, #$49,   { E8 - EF }
                    683:       #$64, #$A4, #$95, #$A2, #$93, #$6F, #$94, #$F6,   { F0 - F7 }
                    684:       #$ED, #$97, #$A3, #$96, #$9A, #$79, #$70, #$98);  { F8 - FF }
                    685: 
                    686: { Ethernet to screen }
                    687:   ibm_iso8859_1_G1 : TXlatTable = (
                    688:       #$00, #$01, #$02, #$03, #$04, #$05, #$06, #$07,   { 00 - 07 }
                    689:       #$08, #$09, #$0A, #$0B, #$0C, #$0D, #$0E, #$0F,   { 08 - 0F }
                    690:       #$10, #$11, #$12, #$13, #$14, #$15, #$16, #$17,   { 10 - 17 }
                    691:       #$18, #$19, #$1A, #$1B, #$1C, #$1D, #$1E, #$1F,   { 18 - 1F }
                    692:       #$20, #$21, #$22, #$23, #$24, #$25, #$26, #$27,   { 20 - 27 }
                    693:       #$28, #$29, #$2A, #$2B, #$2C, #$2D, #$2E, #$2F,   { 28 - 2F }
                    694:       #$30, #$31, #$32, #$33, #$34, #$35, #$36, #$37,   { 30 - 37 }
                    695:       #$38, #$39, #$3A, #$3B, #$3C, #$3D, #$3E, #$3F,   { 38 - 3F }
                    696:       #$40, #$41, #$42, #$43, #$44, #$45, #$46, #$47,   { 40 - 47 }
                    697:       #$48, #$49, #$4A, #$4B, #$4C, #$4D, #$4E, #$4F,   { 48 - 4F }
                    698:       #$50, #$51, #$52, #$53, #$54, #$55, #$56, #$57,   { 50 - 57 }
                    699:       #$58, #$59, #$5A, #$5B, #$5C, #$5D, #$5E, #$5F,   { 58 - 5F }
                    700:       #$60, #$61, #$62, #$63, #$64, #$65, #$66, #$67,   { 60 - 67 }
                    701:       #$68, #$69, #$D9, #$BF, #$DA, #$C0, #$C5, #$6F,   { 68 - 6F }
                    702:       #$70, #$C4, #$72, #$73, #$C3, #$B4, #$C1, #$C2,   { 70 - 77 }
                    703:       #$B3, #$79, #$7A, #$7B, #$7C, #$7D, #$7E, #$7F,   { 78 - 7F }
                    704:       #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20,   { 80 - 87 }
                    705:       #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20,   { 88 - 8F }
                    706:       #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20,   { 90 - 97 }
                    707:       #$20, #$20, #$20, #$20, #$20, #$20, #$20, #$20,   { 98 - 9F }
                    708:       #$B1, #$AD, #$9B, #$9C, #$0F, #$9D, #$B3, #$15,   { A0 - A7 }
                    709:       #$20, #$43, #$A6, #$AE, #$AA, #$C4, #$52, #$C4,   { A8 - AF }
                    710:       #$F8, #$F1, #$FD, #$20, #$27, #$E6, #$14, #$FA,   { B0 - B7 }
                    711:       #$2C, #$20, #$A7, #$AF, #$AC, #$AB, #$20, #$A8,   { B8 - BF }
                    712:       #$41, #$41, #$41, #$41, #$8E, #$8F, #$92, #$80,   { C0 - C7 }
                    713:       #$45, #$45, #$45, #$45, #$45, #$49, #$49, #$49,   { C8 - CF }
                    714:       #$44, #$A5, #$4F, #$4F, #$4F, #$4F, #$4F, #$78,   { D0 - D7 }
                    715:       #$ED, #$55, #$55, #$55, #$55, #$59, #$70, #$E1,   { D8 - DF }
                    716:       #$85, #$A0, #$83, #$61, #$84, #$86, #$91, #$87,   { E0 - E7 }
                    717:       #$8A, #$82, #$88, #$89, #$8D, #$A1, #$8C, #$49,   { E8 - EF }
                    718:       #$64, #$A4, #$95, #$A2, #$93, #$6F, #$94, #$F6,   { F0 - F7 }
                    719:       #$ED, #$97, #$A3, #$96, #$9A, #$79, #$70, #$98);  { F8 - FF }
                    720: 
                    721: { Keyboard to Ethernet }
                    722:   Output : TXlatTable = (
                    723:       #$00, #$01, #$02, #$03, #$04, #$05, #$06, #$07,   { 00 - 07 }
                    724:       #$08, #$09, #$0A, #$0B, #$0C, #$0D, #$0E, #$0F,   { 08 - 0F }
                    725:       #$10, #$11, #$12, #$13, #$14, #$15, #$16, #$17,   { 10 - 17 }
                    726:       #$18, #$19, #$1A, #$1B, #$1C, #$1D, #$1E, #$1F,   { 18 - 1F }
                    727:       #$20, #$21, #$22, #$23, #$24, #$25, #$26, #$27,   { 20 - 27 }
                    728:       #$28, #$29, #$2A, #$2B, #$2C, #$2D, #$2E, #$2F,   { 28 - 2F }
                    729:       #$30, #$31, #$32, #$33, #$34, #$35, #$36, #$37,   { 30 - 37 }
                    730:       #$38, #$39, #$3A, #$3B, #$3C, #$3D, #$3E, #$3F,   { 38 - 3F }
                    731:       #$40, #$41, #$42, #$43, #$44, #$45, #$46, #$47,   { 40 - 47 }
                    732:       #$48, #$49, #$4A, #$4B, #$4C, #$4D, #$4E, #$4F,   { 48 - 4F }
                    733:       #$50, #$51, #$52, #$53, #$54, #$55, #$56, #$57,   { 50 - 57 }
                    734:       #$58, #$59, #$5A, #$5B, #$5C, #$5D, #$5E, #$5F,   { 58 - 5F }
                    735:       #$60, #$61, #$62, #$63, #$64, #$65, #$66, #$67,   { 60 - 67 }
                    736:       #$68, #$69, #$6A, #$6B, #$6C, #$6D, #$6E, #$6F,   { 68 - 6F }
                    737:       #$70, #$71, #$72, #$73, #$74, #$75, #$76, #$77,   { 70 - 77 }
                    738:       #$78, #$79, #$7A, #$7B, #$7C, #$7D, #$7E, #$7F,   { 78 - 7F }
                    739:       #$C7, #$FC, #$E9, #$E2, #$E4, #$E0, #$E5, #$E7,   { 80 - 87 }
                    740:       #$EA, #$EB, #$E8, #$EF, #$EE, #$EC, #$C4, #$C5,   { 88 - 8F }
                    741:       #$C9, #$E6, #$C6, #$F4, #$F6, #$F2, #$FB, #$F9,   { 90 - 97 }
                    742:       #$FF, #$F6, #$FC, #$A2, #$A3, #$A5, #$DE, #$20,   { 98 - 9F }
                    743:       #$E1, #$ED, #$F3, #$FA, #$F1, #$D1, #$AA, #$BA,   { A0 - A7 }
                    744:       #$BF, #$20, #$AC, #$BD, #$BC, #$A1, #$AB, #$BB,   { A8 - AF }
                    745:       #$A0, #$A0, #$A0, #$A6, #$A6, #$A6, #$A6, #$AD,   { B0 - B7 }
                    746:       #$2B, #$A6, #$A6, #$2B, #$2B, #$2B, #$2B, #$2B,   { B8 - BF }
                    747:       #$2B, #$AD, #$AD, #$AD, #$A6, #$AD, #$2B, #$A6,   { C0 - C7 }
                    748:       #$2B, #$2B, #$AD, #$AD, #$A6, #$AD, #$2B, #$AD,   { C8 - CF }
                    749:       #$AD, #$AD, #$AD, #$2B, #$2B, #$2B, #$2B, #$2B,   { D0 - D7 }
                    750:       #$2B, #$2B, #$2B, #$A0, #$A0, #$A0, #$A0, #$A0,   { D8 - DF }
                    751:       #$20, #$20, #$20, #$AD, #$20, #$20, #$B5, #$20,   { E0 - E7 }
                    752:       #$20, #$20, #$20, #$20, #$20, #$F8, #$20, #$20,   { E8 - EF }
                    753:       #$A0, #$B1, #$20, #$20, #$20, #$20, #$F7, #$20,   { F0 - F7 }
                    754:       #$B0, #$B0, #$B0, #$20, #$20, #$B2, #$A0, #$20);  { F8 - FF }
                    755: 
                    756: procedure Register;
                    757: procedure FKeysToFile(var FKeys : TFuncKeysTable; FName : String);
                    758: procedure FileToFKeys(var FKeys : TFuncKeysTable; FName : String);
                    759: function  AddFKey(var FKeys : TFuncKeysTable;
                    760:                   ScanCode  : Char;
                    761:                   Shift     : TShiftState;
                    762:                   Ext       : Boolean;
                    763:                   Value     : TFuncKeyValue) : Boolean;
                    764: 
                    765: 
                    766: 
                    767: implementation
                    768: {$DEFINE Debug}      { Add or remove minus sign before dollar sign to }
                    769:                      { generate code for debug message output         }
                    770: var
                    771:     FCharPos : array [0..MAX_COL + 1] of integer;
                    772:     FLinePos : array [0..MAX_ROW + 1] of integer;
                    773: 
                    774: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    775: procedure Register;
                    776: begin
                    777:     RegisterComponents('FPiette', [TEmulVT]);
                    778: end;
                    779: 
                    780: 
                    781: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    782: function ShiftStateToString(var State : TShiftState) : String;
                    783: begin
                    784:     Result := '';
                    785:     if ssShift in State then
                    786:         Result := Result + 'ssShift ';
                    787:     if ssAlt in State then
                    788:         Result := Result + 'ssAlt ';
                    789:     if ssCtrl in State then
                    790:         Result := Result + 'ssCtrl ';
                    791:     if ssLeft in State then
                    792:         Result := Result + 'ssLeft ';
                    793:     if ssRight in State then
                    794:         Result := Result + 'ssRight ';
                    795:     if ssMiddle in State then
                    796:         Result := Result + 'ssMiddle ';
                    797:     if ssDouble in State then
                    798:         Result := Result + 'ssDouble ';
                    799:     if Result = '' then
                    800:         Result := 'ssNormal';
                    801: end;
                    802: 
                    803: 
                    804: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    805: function StringToShiftState(var S : String) : TShiftState;
                    806: begin
                    807:     Result := [];
                    808:     if Pos('ssShift', S) <> 0 then
                    809:         Result := Result + [ssShift];
                    810:     if Pos('ssAlt', S) <> 0 then
                    811:         Result := Result + [ssAlt];
                    812:     if Pos('ssCtrl', S) <> 0 then
                    813:         Result := Result + [ssCtrl];
                    814:     if Pos('ssLeft', S) <> 0 then
                    815:         Result := Result + [ssLeft];
                    816:     if Pos('ssRight', S) <> 0 then
                    817:         Result := Result + [ssRight];
                    818:     if Pos('ssMiddle', S) <> 0 then
                    819:         Result := Result + [ssMiddle];
                    820:     if Pos('ssDouble', S) <> 0 then
                    821:         Result := Result + [ssDouble];
                    822: end;
                    823: 
                    824: 
                    825: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    826: function xdigit(Ch : char) : integer;
                    827: begin
                    828:     if ch in ['0'..'9'] then
                    829:         Result := Ord(ch) - ord('0')
                    830:     else if ch in ['A'..'Z'] then
                    831:         Result := Ord(ch) - Ord('A') + 10
                    832:     else if ch in ['a'..'z'] then
                    833:         Result := Ord(ch) - Ord('a') + 10
                    834:     else
                    835:         Result := 0;
                    836: end;
                    837: 
                    838: 
                    839: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    840: function xdigit2(S : PChar) : integer;
                    841: begin
                    842:     Result := 16 * xdigit(S[0]) + xdigit(S[1]);
                    843: end;
                    844: 
                    845: 
                    846: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    847: function FuncKeyValueToString(var S : TFuncKeyValue) : String;
                    848: var
                    849:     I : Integer;
                    850: begin
                    851:     Result := '';
                    852:     for I := 1 to Length(S) do begin
                    853:         if (Ord(S[I]) < 32) or (Ord(S[I]) >= 127) or
                    854:            (S[I] = '''') or (S[I] = '\') then
                    855:             Result := Result + '\x' + IntToHex(Ord(S[I]), 2)
                    856:         else
                    857:             Result := Result + S[I];
                    858:     end;
                    859: end;
                    860: 
                    861: 
                    862: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    863: function StringToFuncKeyValue(var S : String) : TFuncKeyValue;
                    864: var
                    865:     I : Integer;
                    866: begin
                    867:     Result := '';
                    868:     I := 1;
                    869:     while I <= Length(S) do begin
                    870:         if (S[I] = '\') and
                    871:            ((I + 3) <= Length(S)) and
                    872:            (S[I + 1] = 'x') then begin
                    873:             Result := Result + chr(xdigit2(@S[I + 2]));
                    874:             I := I + 3;
                    875:         end
                    876:         else
                    877:             Result := Result + S[I];
                    878:         Inc(I);
                    879:     end;
                    880: end;
                    881: 
                    882: 
                    883: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    884: function AddFKey(var FKeys : TFuncKeysTable;
                    885:                   ScanCode  : Char;
                    886:                   Shift     : TShiftState;
                    887:                   Ext       : Boolean;
                    888:                   Value     : TFuncKeyValue) : Boolean;
                    889: var
                    890:     I : Integer;
                    891: begin
                    892:     { Search for existing key definition to replace it }
                    893:     for I := Low(FKeys) to High(FKeys) do begin
                    894:         if (FKeys[I].ScanCode = ScanCode) and
                    895:            (FKeys[I].Shift    = Shift) and
                    896:            (FKeys[I].Ext      = Ext) then begin
                    897:             FKeys[I].Value := Value;
                    898:             Result         := TRUE;     { Success}
                    899:             Exit;
                    900:         end;
                    901:     end;
                    902: 
                    903:     { Key not existing, add in an empty space }
                    904:     for I := Low(FKeys) to High(FKeys) do begin
                    905:         if FKeys[I].ScanCode = #0 then begin
                    906:             FKeys[I].ScanCode := ScanCode;
                    907:             FKeys[I].Shift    := Shift;
                    908:             FKeys[I].Ext      := Ext;
                    909:             FKeys[I].Value    := Value;
                    910:             Result            := TRUE;     { Success}
                    911:             Exit;
                    912:         end;
                    913:     end;
                    914: 
                    915:     { Failure, no more space available }
                    916:     Result := FALSE;
                    917: end;
                    918: 
                    919: 
                    920: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    921: procedure FKeysToFile(var FKeys : TFuncKeysTable; FName : String);
                    922: var
                    923:     I : Integer;
                    924:     F : TextFile;
                    925: begin
                    926:     AssignFile(F, FName);
                    927:     Rewrite(F);
                    928:     for I := Low(FKeys) to High(FKeys) do begin
                    929:         with FKeys[I] do begin
                    930:             if ScanCode <> chr(0) then
                    931:                 WriteLn(F, IntToHex(Ord(ScanCode), 2), ', ',
                    932:                            ShiftStateToString(Shift), ', ',
                    933:                            Ext, ', ''',
                    934:                            FuncKeyValueToString(Value), '''');
                    935:         end;
                    936:     end;
                    937:     CloseFile(F);
                    938: end;
                    939: 
                    940: 
                    941: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    942: function GetToken(var S : String; var I : Integer; Delim : Char) : String;
                    943: begin
                    944:     Result := '';
                    945:     while (I <= Length(S)) and (S[I] = ' ') do
                    946:         Inc(I);
                    947:     while (I <= Length(S)) and (S[I] <> Delim) do begin
                    948:         Result := Result + S[I];
                    949:         Inc(I);
                    950:     end;
                    951: end;
                    952: 
                    953: 
                    954: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                    955: procedure FileToFKeys(var FKeys : TFuncKeysTable; FName : String);
                    956: var
                    957:     I, J : Integer;
                    958:     F : TextFile;
                    959:     S, T : String;
                    960:     sc   : Integer;
                    961: begin
                    962:     AssignFile(F, FName);
                    963:  {$I-}
                    964:     Reset(F);
                    965:     if IOResult <> 0 then begin
                    966:         { File do not exist, create default one }
                    967:         FKeysToFile(FKeys, FName);
                    968:         Exit;
                    969:     end;
                    970: 
                    971:     for I := Low(FKeys) to High(FKeys) do begin
                    972:         with FKeys[I] do begin
                    973:             ScanCode := chr(0);
                    974:             Shift    := [];
                    975:             Ext      := FALSE;
                    976:             Value    := '';
                    977:             if not Eof(F) then begin
                    978:                 { 71, ssNormal, TRUE, '\x1B[H' }
                    979:                 ReadLn(F, S);
                    980:                 J  := 1;
                    981:                 T  := GetToken(S, J, ',');
                    982:                 if (Length(T) > 0) and (T[1] <> ';') then begin
                    983:                     sc := xdigit2(@T[1]);
                    984:                     if sc <> 0 then begin
                    985:                         ScanCode := chr(sc);
                    986:                         Inc(J);
                    987:                         T := GetToken(S, J, ',');
                    988:                         Shift := StringToShiftState(T);
                    989:                         Inc(J);
                    990:                         T := GetToken(S, J, ',');
                    991:                         Ext := UpperCase(T) = 'TRUE';
                    992:                         Inc(J);
                    993:                         T := GetToken(S, J, '''');
                    994:                         Inc(J);
                    995:                         T := GetToken(S, J, '''');
                    996:                         Value := StringToFuncKeyValue(T);
                    997:                     end;
                    998:                 end;
                    999:             end;
                   1000:         end;
                   1001:     end;
                   1002:     CloseFile(F);
                   1003: {$I+}
                   1004: end;
                   1005: 
                   1006: 
                   1007: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1008: procedure DebugString(Msg : String);
                   1009: const
                   1010:     Cnt : Integer = 0;
                   1011: var
                   1012:     Buf : String[20];
                   1013: begin
                   1014: {$IFDEF Debug}
                   1015:     Cnt := Cnt + 1;
                   1016:     Buf := IntToHex(Cnt, 4) + ' ' + #0;
                   1017:     OutputDebugString(@Buf[1]);
                   1018: 
                   1019: {$IFNDEF WIN32}
                   1020:     if Length(Msg) < High(Msg) then
                   1021:         Msg[Length(Msg) + 1] := #0;
                   1022: {$ENDIF}
                   1023: 
                   1024:     OutputDebugString(@Msg[1]);
                   1025: {$ENDIF}
                   1026: end;
                   1027: 
                   1028: 
                   1029: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1030: {$IFNDEF WIN32}
                   1031: procedure SetLength(var S: string; NewLength: Integer);
                   1032: begin
                   1033:     S[0] := chr(NewLength);
                   1034: end;
                   1035: {$ENDIF}
                   1036: 
                   1037: 
                   1038: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1039: constructor TLine.Create;
                   1040: begin
                   1041:     inherited Create;
                   1042:     FillChar(Txt, SizeOf(Txt), ' ');
                   1043:     FillChar(Att, SizeOf(Att), Chr(F_WHITE));
                   1044: end;
                   1045: 
                   1046: 
                   1047: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1048: procedure TLine.Clear(Attr : Byte);
                   1049: begin
                   1050:     FillChar(Txt, SizeOF(Txt), ' ');
                   1051:     FillChar(Att, SizeOf(Att), Attr);
                   1052: end;
                   1053: 
                   1054: 
                   1055: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1056: constructor TScreen.Create;
                   1057: begin
                   1058:     inherited Create;
                   1059:     FRowCount        := 0;
                   1060:     FBackRowCount    := 0;
                   1061:     FBackEndRow      := 0;
                   1062:     FBackColor       := vtsWhite;
                   1063:     FOptions         := [vtoBackColor];
                   1064:     SetRowCount(25);
                   1065:     FColCount        := 80;
                   1066:     FRowSaved        := -1;
                   1067:     FColSaved        := -1;
                   1068:     FScrollRowTop    := 0;
                   1069:     {FScrollRowBottom := FRowCount - 1; // WM + SE 09/08/00 }
                   1070:     FAttribute       := F_WHITE;
                   1071:     InvClear;
                   1072: end;
                   1073: 
                   1074: 
                   1075: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1076: destructor TScreen.Destroy;
                   1077: var
                   1078:     nRow : Integer;
                   1079: begin
                   1080:     for nRow := 0 to FRowCount + FBackRowCount - 1 do
                   1081:         FLines^[nRow].Free;
                   1082:     FreeMem (FLines, (FRowCount + FBackRowCount) * SizeOf(TObject));
                   1083: end;
                   1084: 
                   1085: 
                   1086: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1087: procedure TScreen.AdjustFLines(NewCount : Integer);
                   1088: var
                   1089:     NewLines        : PLineArray;
                   1090:     CurrCount       : Integer;
                   1091:     nRow            : Integer;
                   1092: begin
                   1093:     CurrCount := FRowCount + FBackRowCount;
                   1094:     if  (NewCount <> CurrCount) and (NewCount > 0) then begin
                   1095:         GetMem(NewLines, NewCount * SizeOf(TObject));
                   1096:         if NewCount > CurrCount then begin
                   1097:             if CurrCount <> 0 then
                   1098:                 Move(FLines^, NewLines^, CurrCount * SizeOf(TObject));
                   1099:             for nRow := CurrCount to NewCount - 1 do
                   1100:                 NewLines^[nRow] := TLine.Create;
                   1101:             if CurrCount <> 0 then
                   1102:                 FreeMem(FLines, CurrCount * SizeOf(TObject));
                   1103:         end
                   1104:         else begin
                   1105:             Move (FLines^, NewLines^, NewCount * SizeOf(TObject));
                   1106:             for nRow := NewCount to CurrCount - 1 do
                   1107:                 FLines^[nRow].Free;
                   1108:             FreeMem(FLines, CurrCount * SizeOf(TObject));
                   1109:         end;
                   1110:         FLines := NewLines;
                   1111:     end;
                   1112: end;
                   1113: 
                   1114: 
                   1115: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1116: procedure TScreen.SetRowCount(NewCount : Integer);
                   1117: begin
                   1118:     if NewCount <> FRowCount then begin
                   1119:         AdjustFLines(NewCount + FBackRowCount);
                   1120:         FRowCount := NewCount;
                   1121:         FScrollRowBottom := FRowCount - 1; { WM + SE 09/08/00 }
                   1122:     end;
                   1123: end;
                   1124: 
                   1125: 
                   1126: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1127: procedure TScreen.SetBackRowCount(NewCount : Integer);
                   1128: begin
                   1129:     if NewCount <> FBackRowCount then begin
                   1130:         AdjustFLines(FRowCount + NewCount);
                   1131:         FBackRowCount := NewCount;
                   1132:     end;
                   1133: end;
                   1134: 
                   1135: 
                   1136: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1137: procedure TScreen.CopyScreenToBack;
                   1138: { Copies the current host screen into the scrollback buffer. }
                   1139: var
                   1140:     Temp : TLine;
                   1141:     Row  : Integer;
                   1142:     Pass : Integer;
                   1143:     nCol : Integer;
                   1144: begin
                   1145:     if FBackRowCount >= FRowCount then begin
                   1146:         Dec (FBackEndRow, FRowCount);
                   1147:         if (0 - FBackEndRow) >= FBackRowCount then
                   1148:             FBackEndRow := 1 - FBackRowCount;
                   1149:         { We have to make  FRowCount  lines available at the head of the
                   1150:           scrollback buffer.  These will come from the end of the scrollback
                   1151:           buffer.  We'll make  FRowCount  passes through the scrollback buffer
                   1152:           moving the available lines up to the top and the existing lines
                   1153:           down a page at a time.
                   1154:           Net result is that we only move each line once. }
                   1155:         For Pass := 0 To FRowCount - 1 Do begin
                   1156:             Row := FBackEndRow + Pass;
                   1157:             Temp := Lines[Row];
                   1158:             Inc (Row, FRowCount);
                   1159:             While Row < 0 Do begin
                   1160:                 Lines[Row - FRowCount] := Lines[Row];
                   1161:                 Inc (Row, FRowCount);
                   1162:             end;
                   1163:             Lines[Row - FRowCount] := Temp;
                   1164:         end;
                   1165: 
                   1166:         { Now, copy the host screen lines to the ons we made available. }
                   1167:         For Row := 0 To FRowCount - 1 Do begin
                   1168:             Move (Lines[Row].Txt, Lines[Row - FRowCount].Txt, FColCount);
                   1169:             Move (Lines[Row].Att, Lines[Row - FRowCount].Att, FColCount);
                   1170:             if vtoBackColor in FOptions then begin
                   1171:                 with Lines[Row - FRowCount] do begin
                   1172:                     for nCol := 0 to FColCount - 1 do begin
                   1173:                         Att[nCol] := Att[nCol] And $8F Or (Ord (FBackColor) shl 4);
                   1174:                     end;
                   1175:                 end;
                   1176:             end;
                   1177:         end;
                   1178:     end;
                   1179: end;
                   1180: 
                   1181: 
                   1182: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1183: procedure TScreen.ScrollUp;
                   1184: var
                   1185:     Temp : TLine;
                   1186:     Row  : Integer;
                   1187:     nCol : Integer;
                   1188: begin
                   1189:     if FBackRowCount > 0 then begin
                   1190:         if (0 - FBackEndRow) < (FBackRowCount - 1) then
                   1191:             Dec (FBackEndRow);
                   1192:         Temp := Lines[FBackEndRow];
                   1193:         For Row := FBackEndRow + 1 To -1 Do begin
                   1194:             Lines[Row - 1] := Lines[Row];
                   1195:         end;
                   1196:         Lines[-1] := Lines[FScrollRowTop];
                   1197:             if vtoBackColor in FOptions then begin
                   1198:                 with Lines[-1] do begin
                   1199:                     for nCol := 0 to FColCount - 1 do begin
                   1200:                         Att[nCol] := Att[nCol] And $8F Or (Ord (FBackColor) shl 4);
                   1201:                     end;
                   1202:                 end;
                   1203:             end;
                   1204: 
                   1205:     end
                   1206:     else
                   1207:         Temp := Lines[FScrollRowTop];
                   1208: 
                   1209:     for Row := FScrollRowTop + 1 to FScrollRowBottom do
                   1210:         Lines[Row - 1] := Lines[Row];
                   1211:     Lines[FScrollRowBottom] := Temp;
                   1212:     Temp.Clear(F_WHITE {FAttribute});
                   1213:     FAllInvalid := TRUE;
                   1214: end;
                   1215: 
                   1216: 
                   1217: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1218: procedure TScreen.ScrollDown;
                   1219: var
                   1220:     Temp : TLine;
                   1221:     Row  : Integer;
                   1222: begin
                   1223:     Temp := Lines[FScrollRowBottom];
                   1224:     for Row := FScrollRowBottom DownTo FScrollRowTop + 1 do
                   1225:         Lines[Row] := Lines[Row - 1];
                   1226:     Lines[FScrollRowTop] := Temp;
                   1227:     Temp.Clear(F_WHITE {FAttribute});
                   1228:     FAllInvalid := TRUE;
                   1229: end;
                   1230: 
                   1231: 
                   1232: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1233: procedure TScreen.CursorDown;
                   1234: begin
                   1235:     Inc(FRow);
                   1236:     if FRow > FScrollRowBottom then begin
                   1237:         FRow := FScrollRowBottom;
                   1238:         ScrollUp;
                   1239:     end;
                   1240: end;
                   1241: 
                   1242: 
                   1243: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1244: procedure TScreen.CursorUp;
                   1245: begin
                   1246:     Dec(FRow);
                   1247:     if FRow < 0 then begin
                   1248:         Inc(FRow);
                   1249:         ScrollDown;
                   1250:     end;
                   1251: end;
                   1252: 
                   1253: 
                   1254: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1255: procedure TScreen.CursorRight;
                   1256: begin
                   1257:     Inc(FCol);
                   1258:     if FCol >= FColCount then begin
                   1259:         FCol := 0;
                   1260:         CursorDown;
                   1261:     end;
                   1262: end;
                   1263: 
                   1264: 
                   1265: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1266: procedure TScreen.CursorLeft;
                   1267: begin
                   1268:     Dec(FCol);
                   1269:     if FCol < 0 then begin
                   1270:         FCol := FColCount - 1;
                   1271:         CursorUp;
                   1272:     end;
                   1273: end;
                   1274: 
                   1275: 
                   1276: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1277: procedure TScreen.CarriageReturn;
                   1278: begin
                   1279:     FCol := 0;
                   1280: end;
                   1281: 
                   1282: 
                   1283: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1284: function TScreen.GetEscapeParam(From : Integer; var Value : Integer) : Integer;
                   1285: begin
                   1286:     while (From <= Length(FEscBuffer)) and (FEscBuffer[From] = ' ') do
                   1287:         From := From + 1;
                   1288: 
                   1289:     Value := 0;
                   1290:     while (From <= Length(FEscBuffer)) and (FEscBuffer[From] in ['0'..'9']) do begin
                   1291:         Value := Value * 10 + Ord(FEscBuffer[From]) - Ord('0');
                   1292:         From := From + 1;
                   1293:     end;
                   1294: 
                   1295:     Result := From;
                   1296: end;
                   1297: 
                   1298: 
                   1299: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1300: procedure TScreen.UnimplementedEscape(EscCmd : Char);
                   1301: {var
                   1302:     Buf : String;}
                   1303: begin
                   1304:     DebugString('Unimplemented Escape Sequence: ' + FEscBuffer + EscCmd + #13 + #10);
                   1305: {   Buf := FEscBuffer + EscCmd + #0;
                   1306:     MessageBox(0, @Buf[1], 'Unimplemented Escape Sequence', MB_OK); }
                   1307: end;
                   1308: 
                   1309: 
                   1310: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1311: procedure TScreen.InvalidEscape(EscCmd : Char);
                   1312: {var
                   1313:     Buf : String;}
                   1314: begin
                   1315:     DebugString('Invalid Escape Sequence: ' + FEscBuffer + EscCmd + #13 + #10);
                   1316: {   Buf := FEscBuffer + EscCmd + #0;
                   1317:     MessageBox(0, @Buf[1], 'Invalid Escape Sequence', MB_OK); }
                   1318: end;
                   1319: 
                   1320: 
                   1321: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1322: procedure TScreen.ProcessESC_D;                   { Index                   }
                   1323: begin
                   1324:     UnimplementedEscape('D');
                   1325: end;
                   1326: 
                   1327: 
                   1328: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1329: { Move cursor Up, scroll down if necessary                                  }
                   1330: procedure TScreen.ProcessESC_M;                   { Reverse index           }
                   1331: begin
                   1332:     Dec(FRow);
                   1333:     if FRow < FScrollRowTop then begin
                   1334:         FRow := FScrollRowTop;
                   1335:         ScrollDown;
                   1336:     end;
                   1337: end;
                   1338: 
                   1339: 
                   1340: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1341: procedure TScreen.ProcessESC_E;                   { Next line               }
                   1342: begin
                   1343:     UnimplementedEscape('E');
                   1344: end;
                   1345: 
                   1346: 
                   1347: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1348: procedure TScreen.ProcessCSI_u;                  { Restore Cursor          }
                   1349: begin
                   1350:     UnimplementedEscape('u');
                   1351: end;
                   1352: 
                   1353: 
                   1354: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1355: { IBM character set operation (not part of the ANSI standard)              }
                   1356: { <ESC>[0I             => Set IBM character set                            }
                   1357: { <ESC>[1;nnnI         => Literal mode for nnn next characters             }
                   1358: { <ESC>[2;onoffI       => Switch carbon mode on (1) or off (0)             }
                   1359: { <ESC>[3;ch;cl;sh;slI => Receive carbon mode keyboard code                }
                   1360: { <ESC>[4I              => Select ANSI character set                        }
                   1361: procedure TScreen.ProcessCSI_I;
                   1362: var
                   1363:     From, mode, nnn : Integer;
                   1364:     ch, cl, sh, sl  : Integer;
                   1365: begin
                   1366:     From := GetEscapeParam(2, Mode);
                   1367: 
                   1368:     case Mode of
                   1369:     0:  begin                { Select IBM character set                     }
                   1370:             FNoXlat := TRUE;
                   1371:         end;
                   1372:     1: begin                { Set literal mode for next N characters       }
                   1373:             if FEscBuffer[From] = ';' then
                   1374:                 GetEscapeParam(From + 1, FCntLiteral)
                   1375:             else
                   1376:                 FCntLiteral := 1;
                   1377:         end;
                   1378:     2: begin                { Switch carbon mode on or off                 }
                   1379:             if FEscBuffer[From] = ';' then
                   1380:                 GetEscapeParam(From + 1, nnn)
                   1381:             else
                   1382:                 nnn := 0;
                   1383:             FCarbonMode := (nnn <> 0);
                   1384:         end;
                   1385:     3: begin                { Receive carbon mode key code                 }
                   1386:             ch := 0; cl := 0; sh := 0; sl := 0;
                   1387:             if FEscBuffer[From] = ';' then begin
                   1388:                 From := GetEscapeParam(From + 1, cl);
                   1389:                 if FEscBuffer[From] = ';' then begin
                   1390:                     From := GetEscapeParam(From + 1, ch);
                   1391:                     if FEscBuffer[From] = ';' then begin
                   1392:                         From := GetEscapeParam(From + 1, sl);
                   1393:                         if FEscBuffer[From] = ';' then begin
                   1394:                             GetEscapeParam(From + 1, sh);
                   1395:                         end;
                   1396:                     end;
                   1397:                 end;
                   1398:             end;
                   1399:             DebugString('Special key ' +
                   1400:                         IntToHex(ch, 2) + IntToHex(cl, 2) + ' ' +
                   1401:                         IntToHex(sh, 2) + IntToHex(sl, 2));
                   1402:         end;
                   1403:     4: begin                { Select ANSI character set                    }
                   1404:             FNoXlat := FALSE;
                   1405:         end;
                   1406:     else
                   1407:         UnimplementedEscape('I');
                   1408:     end;
                   1409: end;
                   1410: 
                   1411: 
                   1412: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1413: procedure TScreen.BackSpace;
                   1414: begin
                   1415:     if FCol > 0 then
                   1416:         Dec(FCol);
                   1417: end;
                   1418: 
                   1419: 
                   1420: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1421: procedure TScreen.ClearScreen;
                   1422: var
                   1423:     Row : Integer;
                   1424: begin
                   1425:     for Row := 0 to FRowCount - 1 do
                   1426:         Lines[Row].Clear(FAttribute);
                   1427:     FRow := 0;
                   1428:     FCol := 0;
                   1429:     FAllInvalid := TRUE;
                   1430: end;
                   1431: 
                   1432: 
                   1433: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1434: procedure TScreen.InvClear;
                   1435: begin
                   1436:     with FInvRect do begin
                   1437:         Top    := 9999;
                   1438:         Left   := 9999;
                   1439:         Right  := -1;
                   1440:         Bottom := -1;
                   1441:     end;
                   1442:     FAllInvalid := FALSE;
                   1443: end;
                   1444: 
                   1445: 
                   1446: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1447: procedure TScreen.InvRect(nRow, nCol : Integer);
                   1448: begin
                   1449:     if not FAllInvalid then begin
                   1450:         if FInvRect.Top > nRow then
                   1451:             FInvRect.Top := nRow;
                   1452:         if FInvRect.Bottom < nRow then
                   1453:             FInvRect.Bottom := nRow;
                   1454:         if FInvRect.Left > nCol then
                   1455:             FInvRect.Left := nCol;
                   1456:         if FInvRect.Right < nCol then
                   1457:             FInvRect.Right := nCol;
                   1458:     end;
                   1459: end;
                   1460: 
                   1461: 
                   1462: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1463: { The FLines array is inverted with the last host line at position 0 and
                   1464:   the first host line as position FRowCount - 1. }
                   1465: procedure Tscreen.SetLines(I : Integer; Value : TLine);
                   1466: begin
                   1467:     if I >= FRowCount then
                   1468:         FLines^[0] := Value
                   1469:     else
                   1470:         FLines^[FRowCount - 1 - I] := Value;
                   1471: end;
                   1472: 
                   1473: 
                   1474: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1475: function TScreen.GetLines(I : Integer) : TLine;
                   1476: begin
                   1477:     if I >= FRowCount then
                   1478:         Result := FLines^[0]
                   1479:     else
                   1480:         Result := FLines^[FRowCount - 1 - I];
                   1481: end;
                   1482: 
                   1483: 
                   1484: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1485: procedure TScreen.Eol;
                   1486: begin
                   1487:     with Lines[FRow] do begin
                   1488:         FillChar(Txt[FCol], FColCount - FCol, ' ');
                   1489:         FillChar(Att[FCol], (FColCount - FCol) * SizeOf(Att[FCol]), FAttribute);
                   1490:     end;
                   1491:     InvRect(Frow, FCol);
                   1492:     InvRect(Frow, FColCount);
                   1493: end;
                   1494: 
                   1495: 
                   1496: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1497: procedure TScreen.Eop;
                   1498: var
                   1499:     Row : Integer;
                   1500: begin
                   1501:     Eol;
                   1502:     for Row := FRow + 1 to FRowCount - 1 do
                   1503:         Lines[Row].Clear(FAttribute);
                   1504:     if FRow = 0 then
                   1505:         FAllInvalid := TRUE
                   1506:     else begin
                   1507:        InvRect(FRow, 0);
                   1508:        InvRect(FRowCount, FColCount);
                   1509:     end;
                   1510: end;
                   1511: 
                   1512: 
                   1513: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1514: procedure TScreen.ProcessCSI_J;                  { Clear the screen         }
                   1515: var
                   1516:     Mode : Integer;
                   1517:     Row  : Integer;
                   1518: begin
                   1519:     GetEscapeParam(2, Mode);
                   1520:     case Mode of
                   1521:     0: begin                                   { Cursor to end of screen    }
                   1522:            FAttribute := F_WHITE;
                   1523:            Eop;
                   1524:        end;
                   1525:     1: begin                                   { Start of screen to cursor  }
                   1526:            for Row := 0 to FRow do
                   1527:                Lines[Row].Clear(FAttribute);
                   1528:            InvRect(0, 0);
                   1529:            InvRect(FRow, FColCount);
                   1530:        end;
                   1531:     2: begin                                   { Entire screen              }
                   1532:            if vtoCopyBackOnClear in FOptions then CopyScreenToBack;
                   1533:            ClearScreen;
                   1534:        end;
                   1535:     else
                   1536:         InvalidEscape('J');
                   1537:     end;
                   1538: end;
                   1539: 
                   1540: 
                   1541: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1542: procedure TScreen.ProcessCSI_K;                  { Erase to End of Line    }
                   1543: begin
                   1544:     Eol;
                   1545: end;
                   1546: 
                   1547: 
                   1548: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1549: procedure TScreen.ProcessCSI_L;                   { Insert Line             }
                   1550: var
                   1551:     nLine : Integer;
                   1552:     nRow  : Integer;
                   1553:     Temp  : TLine;
                   1554: begin
                   1555:     FCol := 0;
                   1556:     GetEscapeParam(2, nLine);
                   1557:     if nLine = 0 then
                   1558:         nLine := 1;
                   1559: 
                   1560:     if (FRow + nLine) > FScrollRowBottom then begin
                   1561:         for nRow := FRow to FScrollRowBottom do
                   1562:             Lines[nRow].Clear(FAttribute);
                   1563:         Exit;
                   1564:     end;
                   1565: 
                   1566:     for nRow := FScrollRowBottom downto FRow + nLine do begin
                   1567:         Temp                := Lines[nRow];
                   1568:         Lines[nRow]         := Lines[nRow - nLine];
                   1569:         Lines[nRow - nLine] := Temp;
                   1570:     end;
                   1571: 
                   1572:     for nRow := FRow to FRow + nLine - 1 do
                   1573:         Lines[nRow].Clear(FAttribute);
                   1574: 
                   1575:     FAllInvalid := TRUE;
                   1576: end;
                   1577: 
                   1578: 
                   1579: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1580: procedure TScreen.ProcessCSI_M;                   { Delete Line             }
                   1581: var
                   1582:     nLine : Integer;
                   1583:     nRow  : Integer;
                   1584:     Temp  : TLine;
                   1585: begin
                   1586:     FAllInvalid := TRUE;
                   1587:     FCol := 0;
                   1588:     GetEscapeParam(2, nLine);
                   1589:     if nLine = 0 then
                   1590:         nLine := 1;
                   1591: 
                   1592:     if (FRow + nLine) > FScrollRowBottom then begin
                   1593:         for nRow := FRow to FScrollRowBottom do
                   1594:             Lines[nRow].Clear(FAttribute);
                   1595:         Exit;
                   1596:     end;
                   1597: 
                   1598:     for nRow := FRow to FRow + nLine - 1 do
                   1599:         Lines[nRow].Clear(F_WHITE {FAttribute});  { 12/11/99 }
                   1600:     for nRow := FRow to FScrollRowBottom - nLine do begin
                   1601:         Temp                := Lines[nRow];
                   1602:         Lines[nRow]         := Lines[nRow + nLine];
                   1603:         Lines[nRow + nLine] := Temp;
                   1604:     end;
                   1605: end;
                   1606: 
                   1607: 
                   1608: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1609: procedure TScreen.ProcessCSI_m_lc;               { Select Attributes       }
                   1610: var
                   1611:     From, n : Integer;
                   1612: begin
                   1613:     if FEscBuffer[1] <> '[' then
                   1614:         Exit;
                   1615: 
                   1616:     if Length(FEscBuffer) < 2 then begin
                   1617:         FAttribute    := F_WHITE;
                   1618:         FReverseVideo := FALSE;
                   1619:         Exit;
                   1620:     end;
                   1621: 
                   1622:     From := 2;
                   1623:     while From <= Length(FEscBuffer) do begin
                   1624:         if FEscBuffer[From] in [' ', '[', ';'] then
                   1625:             Inc(From)
                   1626:         else begin
                   1627:             From := GetEscapeParam(From, n);
                   1628:             case n of
                   1629:            0:  begin                   { All attributes off       }
                   1630:                    FAttribute    := F_WHITE;
                   1631:                    FReverseVideo := FALSE;
                   1632:                     FUnderLine    := FALSE;
                   1633:                 end;
                   1634:            1:  begin                   { High intensity           }
                   1635:                    FAttribute := FAttribute or F_INTENSE;
                   1636:                end;
                   1637:             4:  begin                   { Underline                }
                   1638:                     FUnderLine := TRUE;
                   1639:                 end;
                   1640:            5:  begin                   { Blinking                 }
                   1641:                    FAttribute := FAttribute or B_BLINK;
                   1642:                end;
                   1643:            7:  begin                   { Reverse video            }
                   1644:                    FReverseVideo := TRUE;
                   1645:                end;
                   1646:            8:  begin                   { Secret                   }
                   1647:                    FAttribute := 0;
                   1648:                end;
                   1649:            10: begin                   { Don't force high bit     }
                   1650:                    FForceHighBit := FALSE;
                   1651:                end;
                   1652:            12: begin                   { Force high bit on        }
                   1653:                    FForceHighBit := TRUE;
                   1654:                end;
                   1655:            22: begin                   { Normal intensity         }
                   1656:                    FAttribute := FAttribute and (not F_INTENSE);
                   1657:                end;
                   1658:            27: begin                   { Normal characters        }
                   1659:                    FAttribute    := F_WHITE;
                   1660:                    FReverseVideo := FALSE;
                   1661:                end;
                   1662:            30, 31, 32, 33, 34, 35, 36, 37:
                   1663:                 begin                  { Foreground color         }
                   1664:                    FAttribute := (n mod 10) or (FAttribute and $F8);
                   1665:                end;
                   1666:            40, 41, 42, 43, 44, 45, 46, 47:
                   1667:                 begin                   { Background color        }
                   1668:                    FAttribute := ((n mod 10) shl 4) or (FAttribute and $8F);
                   1669:                end;
                   1670:            else
                   1671:                InvalidEscape('m');
                   1672:            end;
                   1673:         end;
                   1674:     end;
                   1675:     if FReverseVideo then begin
                   1676:         FAttribute := ((FAttribute and 7) shl 4) or
                   1677:                       ((FAttribute shr 4) and 7) or
                   1678:                       (FAttribute and $88);
                   1679:     end;
                   1680: end;
                   1681: 
                   1682: 
                   1683: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1684: procedure TScreen.ProcessCSI_n_lc;                { Cursor position report  }
                   1685: begin
                   1686:     UnimplementedEscape('n');
                   1687: end;
                   1688: 
                   1689: 
                   1690: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1691: procedure TScreen.ProcessCSI_at;                 { Insert character        }
                   1692: var
                   1693:     nChar : Integer;
                   1694:     nCnt  : Integer;
                   1695:     nCol  : Integer;
                   1696:     Line  : TLine;
                   1697: begin
                   1698:     GetEscapeParam(2, nChar);
                   1699:     if nChar = 0 then
                   1700:         nChar := 1;
                   1701: 
                   1702:     nCnt := FColCount - FCol - nChar;
                   1703:     if nCnt <= 0 then begin
                   1704:         Eol;
                   1705:         Exit;
                   1706:     end;
                   1707: 
                   1708:     Line := Lines[FRow];
                   1709:     for nCol := FColCount - 1 downto FCol + nChar do begin
                   1710:         Line.Txt[nCol] := Line.Txt[nCol - nChar];
                   1711:         Line.Att[nCol] := Line.Att[nCol - nChar];
                   1712:         InvRect(Frow, nCol);
                   1713:     end;
                   1714: 
                   1715:     for nCol := FCol to FCol + nChar - 1 do begin
                   1716:         Line.Txt[nCol] := ' ';
                   1717:         Line.Att[nCol] := FAttribute;
                   1718:         InvRect(Frow, nCol);
                   1719:     end;
                   1720: 
                   1721: end;
                   1722: 
                   1723: 
                   1724: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1725: procedure TScreen.ProcessCSI_r_lc;                { Scrolling margins       }
                   1726: var
                   1727:     From, Top, Bottom : Integer;
                   1728: begin
                   1729:     From := GetEscapeParam(2, Top);
                   1730:     if Top = 0 then begin                         { Default = full screen   }
                   1731:         FScrollRowTop    := 0;
                   1732:         FScrollRowBottom := FRowCount - 1;
                   1733:     end
                   1734:     else begin
                   1735:         while (From <= Length(FEscBuffer)) and (FEscBuffer[From] = ' ') do
                   1736:             From := From + 1;
                   1737:         if FEscBuffer[From] = ';' then
                   1738:             GetEscapeParam(From + 1, Bottom)
                   1739:         else
                   1740:             Bottom := 1;
                   1741: 
                   1742:         FScrollRowTop    := Top    - 1;
                   1743:         FScrollRowBottom := Bottom - 1;
                   1744: 
                   1745:         if (FScrollRowBottom <= FScrollRowTop) or
                   1746:            (FScrollRowTop < 0) or
                   1747:            (FScrollRowBottom >= FRowCount) then begin
                   1748:             FScrollRowTop    := 0;
                   1749:             FScrollRowBottom := FRowCount - 1;
                   1750:         end;
                   1751:     end;
                   1752: end;
                   1753: 
                   1754: 
                   1755: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1756: procedure TScreen.ProcessCSI_s_lc;                { Save cursor location    }
                   1757: begin
                   1758:     ProcessCSI_7;
                   1759: end;
                   1760: 
                   1761: 
                   1762: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1763: procedure TScreen.ProcessCSI_u_lc;                { Restore cursor location }
                   1764: begin
                   1765:     ProcessCSI_8;
                   1766: end;
                   1767: 
                   1768: 
                   1769: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1770: procedure TScreen.ProcessCSI_7;                   { Save cursor location    }
                   1771: begin
                   1772:     FRowSaved := FRow;
                   1773:     FColSaved := FCol;
                   1774: end;
                   1775: 
                   1776: 
                   1777: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1778: procedure TScreen.ProcessCSI_8;                   { Restore cursor location }
                   1779: begin
                   1780:     if FRowSaved = -1 then
                   1781:         GotoXY(0, 0)
                   1782:     else
                   1783:         GotoXY(FColSaved, FRowSaved);
                   1784:     FRowSaved := -1;
                   1785:     FColSaved := -1;
                   1786: end;
                   1787: 
                   1788: 
                   1789: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1790: procedure TScreen.ProcessCSI_H;                   { Set Cursor Position     }
                   1791: var
                   1792:     From, Row, Col : Integer;
                   1793: begin
                   1794:     From := GetEscapeParam(2, Row);
                   1795:     while (From <= Length(FEscBuffer)) and (FEscBuffer[From] = ' ') do
                   1796:         From := From + 1;
                   1797:     if FEscBuffer[From] = ';' then
                   1798:         GetEscapeParam(From + 1, Col)
                   1799:     else
                   1800:         Col := 1;
                   1801: 
                   1802:     GotoXY(Col - 1, Row - 1);
                   1803: end;
                   1804: 
                   1805: 
                   1806: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1807: procedure TScreen.ProcessCSI_h_lc;                { Terminal mode set       }
                   1808: var
                   1809:     Priv : Boolean;
                   1810:     Mode : Integer;
                   1811: begin
                   1812:     if FEscBuffer[1] <> '[' then begin
                   1813:         UnimplementedEscape('h');
                   1814:         Exit;
                   1815:     end;
                   1816: 
                   1817:     Priv := (FEscBuffer[2] = '?');
                   1818:     if not Priv then begin
                   1819:         UnimplementedEscape('h');
                   1820:         Exit;
                   1821:     end;
                   1822: 
                   1823:     GetEscapeParam(3, Mode);
                   1824:     case Mode of
                   1825:     1 :  { ANSI cursor keys }
                   1826:          FCKeyMode := TRUE;
                   1827:     4 :  { Smooth scroll OFF }
                   1828:          { Ignore };
                   1829:     7:   { Auto-wrap OFF }
                   1830:          FAutoWrap := TRUE;
                   1831:     25:  { Cursor visible }
                   1832:          begin
                   1833:              FCursorOff := FALSE;
                   1834:              if Assigned(FOnCursorVisible) then
                   1835:                  FOnCursorVisible(Self);
                   1836:          end;
                   1837:     else
                   1838:         UnimplementedEscape('h');
                   1839:     end;
                   1840: end;
                   1841: 
                   1842: 
                   1843: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1844: procedure TScreen.ProcessCSI_l_lc;                { Terminal mode reset     }
                   1845: var
                   1846:     Priv : Boolean;
                   1847:     Mode : Integer;
                   1848: begin
                   1849:     if FEscBuffer[1] <> '[' then begin
                   1850:         UnimplementedEscape('l');
                   1851:         Exit;
                   1852:     end;
                   1853: 
                   1854:     Priv := (FEscBuffer[2] = '?');
                   1855:     if not Priv then begin
                   1856:         UnimplementedEscape('l');
                   1857:         Exit;
                   1858:     end;
                   1859: 
                   1860:     GetEscapeParam(3, Mode);
                   1861:     case Mode of
                   1862:     1 :  { ANSI cursor keys }
                   1863:          FCKeyMode := FALSE;
                   1864:     4 :  { Smooth scroll OFF }
                   1865:          { Ignore };
                   1866:     7:   { Auto-wrap OFF }
                   1867:          FAutoWrap := FALSE;
                   1868:     25:  { Cursor invisible }
                   1869:          begin
                   1870:              FCursorOff := TRUE;
                   1871:              if Assigned(FOnCursorVisible) then
                   1872:                  FOnCursorVisible(Self);
                   1873:          end;
                   1874:     else
                   1875:         UnimplementedEscape('l');
                   1876:     end;
                   1877: end;
                   1878: 
                   1879: 
                   1880: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1881: procedure TScreen.ProcessCSI_A;                   { Cursor Up               }
                   1882: var
                   1883:     Row : Integer;
                   1884: begin
                   1885:     GetEscapeParam(2, Row);
                   1886:     if Row <= 0 then
                   1887:         Row := 1;
                   1888:     FRow := FRow - Row;
                   1889:     if FRow < 0 then
                   1890:         FRow := 0;
                   1891: end;
                   1892: 
                   1893: 
                   1894: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1895: procedure TScreen.ProcessCSI_B;                   { Cursor Down             }
                   1896: var
                   1897:     Row : Integer;
                   1898: begin
                   1899:     GetEscapeParam(2, Row);
                   1900:     if Row <= 0 then
                   1901:         Row := 1;
                   1902:     FRow := FRow + Row;
                   1903:     if FRow >= FRowCount then
                   1904:         FRow := FRowCount - 1;
                   1905: end;
                   1906: 
                   1907: 
                   1908: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1909: procedure TScreen.ProcessCSI_C;                   { Cursor Right            }
                   1910: var
                   1911:     Col : Integer;
                   1912: begin
                   1913:     GetEscapeParam(2, Col);
                   1914:     if Col <= 0 then
                   1915:         Col := 1;
                   1916:     FCol := FCol + Col;
                   1917:     if FCol >= FColCount then begin
                   1918:         if FAutoWrap then begin
                   1919:             FCol := FCol - FColCount;
                   1920:             Inc(FRow);
                   1921:             if FRow >= FRowCount then
                   1922:                 FRow := FRowCount - 1;
                   1923:         end
                   1924:         else
                   1925:             FCol := FColCount - 1;
                   1926:     end;
                   1927: end;
                   1928: 
                   1929: 
                   1930: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1931: procedure TScreen.ProcessCSI_D;                   { Cursor Left             }
                   1932: var
                   1933:     Col : Integer;
                   1934: begin
                   1935:     GetEscapeParam(2, Col);
                   1936:     if Col <= 0 then
                   1937:         Col := 1;
                   1938:     FCol := FCol - Col;
                   1939:     if FCol < 0 then
                   1940:         FCol := 0;
                   1941: end;
                   1942: 
                   1943: 
                   1944: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1945: procedure TScreen.ProcessCSI_P;                   { Delete Character        }
                   1946: var
                   1947:     Count : Integer;
                   1948:     nCol  : Integer;
                   1949: begin
                   1950:     GetEscapeParam(2, Count);
                   1951:     if Count <= 0 then
                   1952:         Count := 1;
                   1953:     with Lines[FRow] do begin
                   1954:         for nCol := Fcol to FColCount - Count - 1 do begin
                   1955:             Txt[nCol] := Txt[nCol + Count];
                   1956:             Att[nCol] := Att[nCol + Count];
                   1957:         end;
                   1958:         for nCol := FcolCount - Count - 1 to FColCount - 1 do begin
                   1959:             Txt[nCol] := ' ';
                   1960:             Att[nCol] := F_WHITE;
                   1961:         end;
                   1962:     end;
                   1963:     InvRect(Frow, FCol);
                   1964:     InvRect(Frow, FColCount);
                   1965: end;
                   1966: 
                   1967: 
                   1968: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1969: procedure TScreen.ProcessCSI_S;                   { Scroll up               }
                   1970: begin
                   1971:     ScrollUp;
                   1972: end;
                   1973: 
                   1974: 
                   1975: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1976: procedure TScreen.ProcessCSI_T;                  { Scroll down             }
                   1977: begin
                   1978:     UnimplementedEscape('T');
                   1979: end;
                   1980: 
                   1981: 
                   1982: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   1983: procedure TScreen.process_charset_G0(EscCmd : Char); { G0 character set     }
                   1984: begin
                   1985:     case EscCmd of
                   1986:     '0': begin
                   1987:              FCharSetG0       := EscCmd;
                   1988:              FXlatInputTable  := @ibm_iso8859_1_G1;
                   1989:              FXlatOutputTable := @ibm_iso8859_1_G1;
                   1990:              FNoXlat          := FNoXlatInitial;
                   1991: {             FNoXlat          := FALSE;}
                   1992:          end;
                   1993:     'B': begin
                   1994:              FCharSetG0       := EscCmd;
                   1995:              FXlatInputTable  := @ibm_iso8859_1_G0;
                   1996:              FXlatOutputTable := @ibm_iso8859_1_G0;
                   1997:              FNoXlat          := FNoXlatInitial;
                   1998:          end;
                   1999:     else
                   2000:         InvalidEscape(EscCmd);
                   2001:     end;
                   2002: end;
                   2003: 
                   2004: 
                   2005: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2006: procedure TScreen.process_charset_G1(EscCmd : Char); { G1 character set     }
                   2007: begin
                   2008:     FCharSetG1 := EscCmd;
                   2009: end;
                   2010: 
                   2011: 
                   2012: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2013: procedure TScreen.process_charset_G2(EscCmd : Char); { G2 character set     }
                   2014: begin
                   2015:     FCharSetG2 := EscCmd;
                   2016: end;
                   2017: 
                   2018: 
                   2019: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2020: procedure TScreen.process_charset_G3(EscCmd : Char); { G2 character set     }
                   2021: begin
                   2022:     FCharSetG3 := EscCmd;
                   2023: end;
                   2024: 
                   2025: 
                   2026: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2027: procedure TScreen.ProcessEscape(EscCmd : Char);
                   2028: begin
                   2029:     if Length(FEscBuffer) = 0 then begin
                   2030:         case EscCmd of
                   2031:         'D': ProcessESC_D;         { Index                   }
                   2032:         'M': ProcessESC_M;         { Reverse index           }
                   2033:         'E': ProcessESC_E;         { Next line               }
                   2034:         'H': ;                     { Tabulation set          }
                   2035:         '7': ProcessCSI_7;         { Save cursor             }
                   2036:         '8': ProcessCSI_8;      { Restore Cursor          }
                   2037:         '=': ;     { VT52 }        { Enter Alternate keypad  }
                   2038:         '>': ;     { VT52 }        { Exit Alternate keypad   }
                   2039:         '<': ;     { VT52 }        { Enter ANSI mode         }
                   2040:         else
                   2041:             InvalidEscape(EscCmd);
                   2042:             WriteLiteralChar(EscCmd);
                   2043:         end;
                   2044: 
                   2045:         Exit;
                   2046:     end;
                   2047: 
                   2048:     case FEscBuffer[1] of
                   2049:     ' ': begin
                   2050:              case EscCmd of
                   2051:              'F': ;
                   2052:              else
                   2053:                  InvalidEscape(EscCmd);
                   2054:              end;
                   2055:          end;
                   2056:     '[': begin
                   2057:              case EscCmd of
                   2058:              'I': ProcessCSI_I;                { Select IBM char set     }
                   2059:                                                 { Extension F. Piette !!  }
                   2060:              'J': ProcessCSI_J;                { Clear the screen        }
                   2061:              'K': ProcessCSI_K;                { Erase to End of Line    }
                   2062:              'L': ProcessCSI_L;                { Insert Line             }
                   2063:              'M': ProcessCSI_M;                { Delete Line             }
                   2064:              'm': ProcessCSI_m_lc;             { Select Attributes       }
                   2065:              'n': ProcessCSI_n_lc;             { Cursor position report  }
                   2066:              '@': ProcessCSI_at;               { Insert character        }
                   2067:              'r': ProcessCSI_r_lc;             { Set Top and Bottom marg }
                   2068:              's': ProcessCSI_s_lc;             { Save cursor location    }
                   2069:              'u': ProcessCSI_u_lc;             { Restore cursor location }
                   2070:              'H': ProcessCSI_H;                { Set Cursor Position     }
                   2071:              'f': ProcessCSI_H;                { Set Cursor Position     }
                   2072:              'g': ;                            { Tabulation Clear        }
                   2073:              'h': ProcessCSI_h_lc;             { Terminal mode set       }
                   2074:              'l': ProcessCSI_l_lc;             { Terminal mode reset     }
                   2075:              'A': ProcessCSI_A;                { Cursor Up               }
                   2076:              'B': ProcessCSI_B;                { Cursor Down             }
                   2077:              'C': ProcessCSI_C;                { Cursor Right            }
                   2078:              'D': ProcessCSI_D;                { Cursor Left             }
                   2079:              'P': ProcessCSI_P;                { Delete Character        }
                   2080:              'S': ProcessCSI_S;                { Scroll up               }
                   2081:              'T': ProcessCSI_T;                { Scroll down             }
                   2082:              '>': ;                            {                         }
                   2083:              else
                   2084:                  InvalidEscape(EscCmd);
                   2085:              end;
                   2086:          end;
                   2087:     '(': process_charset_G0(EscCmd);           { G0 character set        }
                   2088:     ')': process_charset_G1(EscCmd);           { G1 character set        }
                   2089:     '*': process_charset_G2(EscCmd);           { G2 character set        }
                   2090:     '+': process_charset_G3(EscCmd);           { G3 character set        }
                   2091:     else
                   2092:         InvalidEscape(EscCmd);
                   2093:     end;
                   2094: end;
                   2095: 
                   2096: 
                   2097: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2098: procedure TScreen.WriteLiteralChar(Ch : Char);
                   2099: var
                   2100:     Line : TLine;
                   2101: begin
                   2102:     if FCol >= FColCount then begin
                   2103:         if FAutoWrap then begin
                   2104:             FCol := 0;
                   2105:             Inc(FRow);
                   2106:             if FRow >= FRowCount then begin
                   2107:                 Dec(FRow);
                   2108:                 ScrollUp;
                   2109:             end;
                   2110:         end;
                   2111:     end;
                   2112: 
                   2113:     if FForceHighBit then
                   2114:         Ch := Chr(ord(ch) or $80);
                   2115: 
                   2116:     Line := Lines[FRow];
                   2117:     Line.Txt[FCol] := Ch;
                   2118:     Line.Att[FCol] := FAttribute;
                   2119:     InvRect(Frow, FCol);
                   2120: 
                   2121:     if FCol < High(Line.Txt) then
                   2122:         Inc(FCol);
                   2123: end;
                   2124: 
                   2125: 
                   2126: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2127: procedure TScreen.SetAttr(Att : Char);
                   2128: begin
                   2129:      { Not implemented }
                   2130: end;
                   2131: 
                   2132: 
                   2133: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2134: { Write a single character at current cursor location.                      }
                   2135: { Update cursor position.                                                   }
                   2136: procedure TScreen.WriteChar(Ch : Char);
                   2137: var
                   2138:     bProcess : Boolean;
                   2139: begin
                   2140:     if FCntLiteral > 0 then begin
                   2141:         if (FCntLiteral and 1) <> 0 then
                   2142:             WriteLiteralChar(Ch)
                   2143:         else
                   2144:             SetAttr(Ch);
                   2145:         Dec(FCntLiteral);
                   2146:         Exit;
                   2147:     end;
                   2148: 
                   2149:     if FNoXlat then
                   2150:         Ch := FXlatInputTable^[ord(Ch)];
                   2151: 
                   2152:     if FEscFLag then begin
                   2153:         bProcess := FALSE;
                   2154:         if (Length(FEscBuffer) = 0) and
                   2155:            (Ch in ['D', 'M', 'E', 'H', '7', '8', '=', '>', '<']) then
                   2156:              bProcess := TRUE
                   2157:         else if (Length(FEscBuffer) = 1) and
                   2158:            (FEscBuffer[1] in ['(', ')', '*', '+']) then
                   2159:             bProcess := TRUE
                   2160:         else if (Ch in ['0'..'9', ';', '?', ' ']) or
                   2161:                 ((Length(FEscBuffer) = 0) and
                   2162:                  (ch in ['[', '(', ')', '*', '+'])) then begin
                   2163:             FEscBuffer := FEscBuffer + Ch;
                   2164:             if Length(FEscBuffer) >= High(FEscBuffer) then begin
                   2165:                 MessageBeep(MB_ICONASTERISK);
                   2166:                 FEscBuffer := '';
                   2167:                 FEscFlag   := FALSE;
                   2168:             end;
                   2169:         end
                   2170:         else
                   2171:             bProcess := TRUE;
                   2172: 
                   2173:         if bProcess then begin
                   2174:             ProcessEscape(Ch);
                   2175:             FEscBuffer := '';
                   2176:             FEscFlag   := FALSE;
                   2177:         end;
                   2178: 
                   2179:         Exit;
                   2180:     end;
                   2181: 
                   2182:     case Ch of
                   2183:     #0:  ;
                   2184:     #7:  MessageBeep(MB_ICONASTERISK);
                   2185:     #8:  BackSpace;
                   2186:     #9:  begin
                   2187:              repeat
                   2188:                  Inc(FCol);
                   2189:              until (FCol Mod 8) = 0;
                   2190:          end;
                   2191:     #10: begin
                   2192:              CursorDown;
                   2193:              if FAutoCR then
                   2194:                  CarriageReturn;
                   2195:          end;
                   2196:     #13: begin
                   2197:              CarriageReturn;
                   2198:              if FAutoLF then
                   2199:                  CursorDown;
                   2200:          end;
                   2201:     #14: begin
                   2202:              FXlatInputTable  := @ibm_iso8859_1_G1;
                   2203:              FXlatOutputTable := @ibm_iso8859_1_G1;
                   2204:          end;
                   2205:     #15: begin
                   2206:              FXlatInputTable  := @ibm_iso8859_1_G0;
                   2207:              FXlatOutputTable := @ibm_iso8859_1_G0;
                   2208:          end;
                   2209:     #27: begin
                   2210:              FEscBuffer := '';
                   2211:              FEscFlag   := TRUE;
                   2212:          end;
                   2213:     else
                   2214:         WriteLiteralChar(Ch);
                   2215:     end;
                   2216: end;
                   2217: 
                   2218: 
                   2219: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2220: { Write characters at current cursor location. Update cursor position.      }
                   2221: procedure TScreen.WriteStr(Str : String);
                   2222: var
                   2223:     I : Integer;
                   2224: begin
                   2225:     for I := 1 to Length(Str) do
                   2226:         WriteChar(Str[I]);
                   2227: end;
                   2228: 
                   2229: 
                   2230: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2231: { Read characters from the cursor to end of line                            }
                   2232: function TScreen.ReadStr : String;
                   2233: var
                   2234:     Line : TLine;
                   2235:     Len  : Integer;
                   2236: begin
                   2237:     Line := Lines[FRow];
                   2238:     Len  := FColCount - FCol;
                   2239:     if Len <= 0 then
                   2240:         Result := ''
                   2241:     else begin
                   2242:         SetLength(Result, Len);
                   2243:         Move(Line.Txt[FCol], Result[1], Len);
                   2244:     end;
                   2245: end;
                   2246: 
                   2247: 
                   2248: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2249: procedure TScreen.GotoXY(X, Y : Integer);
                   2250: begin
                   2251:     if X < 0 then
                   2252:         FCol := 0
                   2253:     else if X >= FColCount then
                   2254:         FCol := FColCount - 1
                   2255:     else
                   2256:         FCol := X;
                   2257: 
                   2258:     if Y < 0 then
                   2259:         FRow := 0
                   2260:     else if Y >= FRowCount then
                   2261:         FRow := FRowCount - 1
                   2262:     else
                   2263:         FRow := Y;
                   2264: end;
                   2265: 
                   2266: 
                   2267: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2268: procedure TCustomEmulVT.SetCaret;
                   2269: begin
                   2270: {$IFDEF CHAR_ZOOM}
                   2271:     SetCaretPos(FCharPos[FScreen.FCol] + LeftMargin + 2,
                   2272:                 FLinePos[FScreen.FRow - FTopLine] + TopMargin + 3);
                   2273: {$ELSE}
                   2274:     SetCaretPos(FScreen.FCol * FCharWidth + LeftMargin,
                   2275:                 (FScreen.FRow - FTopLine) * FLineHeight + TopMargin);
                   2276: {$ENDIF}
                   2277: end;
                   2278: 
                   2279: 
                   2280: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2281: { Adjusts the scrollbar properties to match the number of host and scrollback
                   2282:   lines that we can scroll through. }
                   2283: procedure TCustomEmulVT.AdjustScrollBar;
                   2284: var
                   2285:     VisibleLines    : Integer;
                   2286: begin
                   2287:     FVScrollBar.Min := FScreen.FBackEndRow;
                   2288: {$IFDEF CHAR_ZOOM}
                   2289:     VisibleLines := Trunc((Height - TopMargin - BottomMargin) / (LineHeight * FLineZoom));
                   2290: {$ELSE}
                   2291:     VisibleLines := (Height - TopMargin - BottomMargin) Div LineHeight;
                   2292: {$ENDIF}
                   2293:     if VisibleLines > FScreen.FRowCount then
                   2294:         VisibleLines := FScreen.FRowCount;
                   2295:     FVScrollBar.Max         := FScreen.FRowCount - VisibleLines;
                   2296:     FVScrollBar.Position    := FTopLine;
                   2297:     FVScrollBar.SmallChange := 1;
                   2298:     FVScrollBar.LargeChange := VisibleLines;
                   2299:     FVScrollBar.Enabled     := FVScrollBar.Max > FVScrollBar.Min;
                   2300: end;
                   2301: 
                   2302: 
                   2303: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2304: procedure TCustomEmulVT.Clear;
                   2305: begin
                   2306:     FScreen.ClearScreen;
                   2307: end;
                   2308: 
                   2309: 
                   2310: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2311: procedure TCustomEmulVT.SetCursor(Row, Col : Integer);
                   2312: begin
                   2313:     FScreen.GotoXY(Col - 1, Row - 1);
                   2314: {    SetCaret; }
                   2315: end;
                   2316: 
                   2317: 
                   2318: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2319: procedure TCustomEmulVT.WriteChar(Ch : Char);
                   2320: begin
                   2321:     if FCaretCreated and FCaretShown then begin
                   2322:         HideCaret(Handle);
                   2323:         FCaretShown := FALSE;
                   2324:     end;
                   2325: 
                   2326:     if FLog then
                   2327:         Write(FFileHandle, Ch);
                   2328:     FScreen.WriteChar(ch);
                   2329:     if FAutoRepaint then
                   2330:         UpdateScreen;
                   2331: {    SetCaret;   }
                   2332: end;
                   2333: 
                   2334: 
                   2335: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2336: procedure TCustomEmulVT.WriteStr(Str : String);
                   2337: var
                   2338:     I : Integer;
                   2339: begin
                   2340:     if FCaretCreated and FCaretShown then begin
                   2341:         HideCaret(Handle);
                   2342:         FCaretShown := FALSE;
                   2343:     end;
                   2344: 
                   2345:     for I := 1 to Length(Str) do begin
                   2346:         if FLog then
                   2347:             Write(FFileHandle, Str[I]);
                   2348:         FScreen.WriteChar(Str[I]);
                   2349:     end;
                   2350:     if FAutoRepaint then
                   2351:         UpdateScreen;
                   2352: {    SetCaret; }
                   2353: end;
                   2354: 
                   2355: 
                   2356: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2357: procedure TCustomEmulVT.WriteBuffer(Buffer : Pointer; Len : Integer);
                   2358: var
                   2359:     I : Integer;
                   2360: begin
                   2361:     if FCaretCreated and FCaretShown then begin
                   2362:         HideCaret(Handle);
                   2363:         FCaretShown := FALSE;
                   2364:     end;
                   2365: 
                   2366:     for I := 0 to Len - 1 do begin
                   2367:         if FLog then
                   2368:             Write(FFileHandle, PChar(Buffer)[I]);
                   2369:         FScreen.WriteChar(PChar(Buffer)[I]);
                   2370:     end;
                   2371:     if FAutoRepaint then
                   2372:         UpdateScreen;
                   2373: {    SetCaret; }
                   2374: end;
                   2375: 
                   2376: 
                   2377: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2378: function TCustomEmulVT.ReadStr : String;
                   2379: begin
                   2380:     Result := FScreen.ReadStr;
                   2381: end;
                   2382: 
                   2383: 
                   2384: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2385: procedure TCustomEmulVT.CopyHostScreen;
                   2386: begin
                   2387:     FScreen.CopyScreenToBack;
                   2388:     AdjustScrollBar;
                   2389: end;
                   2390: 
                   2391: 
                   2392: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2393: constructor TCustomEmulVT.Create(AOwner: TComponent);
                   2394: type
                   2395:     TMyLogPalette = record
                   2396:         palVersion: Word;
                   2397:         palNumEntries: Word;
                   2398:         palPalEntry: array[0..NumPaletteEntries - 1] of TPaletteEntry;
                   2399:     end;
                   2400:     TPLogPalette = ^TLogPalette;
                   2401: var
                   2402:     plgpl      : ^TMyLogPalette;
                   2403:     I          : Integer;
                   2404: begin
                   2405:     inherited Create(AOwner);
                   2406:     ControlStyle := ControlStyle + [csOpaque];
                   2407: 
                   2408:     New(plgpl);
                   2409:     plgpl^.palNumEntries := High(plgpl^.palPalEntry) + 1;
                   2410:     plgpl^.palVersion    := $300;
                   2411: 
                   2412:     FPaletteEntries[0].peRed    := 0;                { Black }
                   2413:     FPaletteEntries[0].peGreen  := 0;
                   2414:     FPaletteEntries[0].peBlue   := 0;
                   2415:     FPaletteEntries[1].peRed    := 168;              { Red }
                   2416:     FPaletteEntries[1].peGreen  := 0;
                   2417:     FPaletteEntries[1].peBlue   := 0;
                   2418:     FPaletteEntries[2].peRed    := 0;                { Green  }
                   2419:     FPaletteEntries[2].peGreen  := 168;
                   2420:     FPaletteEntries[2].peBlue   := 0;
                   2421:     FPaletteEntries[3].peRed    := 168;              { Yellow }
                   2422:     FPaletteEntries[3].peGreen  := 168;
                   2423:     FPaletteEntries[3].peBlue   := 0;
                   2424:     FPaletteEntries[4].peRed    := 0;                { Dark Blue }
                   2425:     FPaletteEntries[4].peGreen  := 0;
                   2426:     FPaletteEntries[4].peBlue   := 168;
                   2427:     FPaletteEntries[5].peRed    := 168;              { Magenta }
                   2428:     FPaletteEntries[5].peGreen  := 0;
                   2429:     FPaletteEntries[5].peBlue   := 168;
                   2430:     FPaletteEntries[6].peRed    := 0;                { Cyan }
                   2431:     FPaletteEntries[6].peGreen  := 112;
                   2432:     FPaletteEntries[6].peBlue   := 216;
                   2433:     FPaletteEntries[7].peRed    := 200;              { White }
                   2434:     FPaletteEntries[7].peGreen  := 200;
                   2435:     FPaletteEntries[7].peBlue   := 200;
                   2436:     FPaletteEntries[8].peRed    := 84;               { Grey }
                   2437:     FPaletteEntries[8].peGreen  := 84;
                   2438:     FPaletteEntries[8].peBlue   := 84;
                   2439:     FPaletteEntries[9].peRed    := 84;               { Red Highlight }
                   2440:     FPaletteEntries[9].peGreen  := 84;
                   2441:     FPaletteEntries[9].peBlue   := 212;
                   2442:     FPaletteEntries[10].peRed   := 84;               { Green Highlight }
                   2443:     FPaletteEntries[10].peGreen := 255;
                   2444:     FPaletteEntries[10].peBlue  := 84;
                   2445:     FPaletteEntries[11].peRed   := 255;              { Yellow Highlight }
                   2446:     FPaletteEntries[11].peGreen := 255;
                   2447:     FPaletteEntries[11].peBlue  := 84;
                   2448:     FPaletteEntries[12].peRed   := 84;               { Blue Highlight }
                   2449:     FPaletteEntries[12].peGreen := 84;
                   2450:     FPaletteEntries[12].peBlue  := 255;
                   2451:     FPaletteEntries[13].peRed   := 255;              { Magenta Highlight }
                   2452:     FPaletteEntries[13].peGreen := 84;
                   2453:     FPaletteEntries[13].peBlue  := 255;
                   2454:     FPaletteEntries[14].peRed   := 84;               { Cyan highlight }
                   2455:     FPaletteEntries[14].peGreen := 255;
                   2456:     FPaletteEntries[14].peBlue  := 255;
                   2457:     FPaletteEntries[15].peRed   := 255;              { White Highlight }
                   2458:     FPaletteEntries[15].peGreen := 255;
                   2459:     FPaletteEntries[15].peBlue  := 255;
                   2460: 
                   2461:     for I := 0 to High(plgpl^.palPalEntry) do begin
                   2462:         plgpl^.PalPalEntry[I].peRed   := FPaletteEntries[I].peRed;
                   2463:         plgpl^.PalPalEntry[I].peGreen := FPaletteEntries[I].peGreen;
                   2464:         plgpl^.PalPalEntry[I].peBlue  := FPaletteEntries[I].peBlue;
                   2465:         plgpl^.PalPalEntry[I].peFlags := PC_NOCOLLAPSE;
                   2466:     end;
                   2467: 
                   2468:     FPal := CreatePalette(TPLogPalette(plgpl)^);
                   2469:     Dispose(plgpl);
                   2470: 
                   2471:     FScreen             := TScreen.Create;
                   2472:     FVScrollBar         := TScrollBar.Create(Self);
                   2473:     FFont               := TFont.Create;
                   2474:     FFont.Name          := 'Terminal';
                   2475:     FFont.Size          := 12;
                   2476:     FFont.Style         := [];
                   2477:     FCharZoom           := 1.0;
                   2478:     FLineZoom           := 1.0;
                   2479:     SetupFont;
                   2480: 
                   2481:     FScreen.FXlatInputTable     := @ibm_iso8859_1_G0;
                   2482:     FScreen.FXlatOutputTable    := @ibm_iso8859_1_G0;
                   2483:     FScreen.OnCursorVisible     := CursorVisibleEvent;
                   2484: 
                   2485:     FCursorVisible      := TRUE;
                   2486:     Width               := 250;
                   2487:     Height              := 100;
                   2488:     FBorderStyle        := bsSingle;
                   2489:     FBorderWidth        := 1;
                   2490:     FAutoRepaint        := TRUE;
                   2491:     FFkeys              := 1;
                   2492:     FGraphicDraw        := FALSE;
                   2493: 
                   2494:     with FVScrollBar do begin
                   2495:         Parent   := Self;
                   2496:         Kind     := sbVertical;
                   2497:         Width    := 16;
                   2498:         Visible  := TRUE;
                   2499:         Align    := alRight;
                   2500:         OnScroll := VScrollBarScroll;
                   2501:     end;
                   2502:     AdjustScrollBar;
                   2503: 
                   2504:     with FScreen do begin
                   2505:         GotoXY(0, 0);
                   2506:         WriteStr('EmulVT');
                   2507:         GotoXY(0, 1);
                   2508:     end;
                   2509: end;
                   2510: 
                   2511: 
                   2512: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2513: procedure TCustomEmulVT.SetRows(Value : Integer);
                   2514: begin
                   2515:     with FScreen do begin
                   2516:         if FRowCount <> Value then begin
                   2517:             SetRowCount(Value);
                   2518:             AdjustScrollBar;
                   2519:             ClearScreen;
                   2520:             Repaint;
                   2521:         end;
                   2522:     end;
                   2523: end;
                   2524: 
                   2525: 
                   2526: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2527: function TCustomEmulVT.GetRows : Integer;
                   2528: begin
                   2529:     Result := FScreen.FRowCount;
                   2530: end;
                   2531: 
                   2532: 
                   2533: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2534: procedure TCustomEmulVT.SetCols(Value : Integer);
                   2535: begin
                   2536:     with FScreen do begin
                   2537:         if FColCount <> Value then begin
                   2538:             FColCount := Value;
                   2539:             ClearScreen;
                   2540:             Repaint;
                   2541:         end;
                   2542:     end;
                   2543: end;
                   2544: 
                   2545: 
                   2546: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2547: function TCustomEmulVT.GetCols : Integer;
                   2548: begin
                   2549:     Result := FScreen.FColCount;
                   2550: end;
                   2551: 
                   2552: 
                   2553: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2554: procedure TCustomEmulVT.CursorVisibleEvent(Sender : TObject);
                   2555: begin
                   2556:     if FScreen.FCursorOff then begin
                   2557:         if FCaretShown then begin
                   2558:             HideCaret(Handle);
                   2559:             FCaretShown := FALSE;
                   2560:         end;
                   2561:     end
                   2562:     else begin
                   2563:         if FScreen.Focused and not FCaretShown then begin
                   2564:             ShowCaret(Handle);
                   2565:             FCaretShown := TRUE;
                   2566:         end;
                   2567:     end;
                   2568: end;
                   2569: 
                   2570: 
                   2571: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2572: procedure TCustomEmulVT.SetAutoLF(Value : Boolean);
                   2573: begin
                   2574:     FScreen.FAutoLF := Value;
                   2575: end;
                   2576: 
                   2577: 
                   2578: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2579: procedure TCustomEmulVT.SetAutoCR(Value : Boolean);
                   2580: begin
                   2581:     FScreen.FAutoCR := Value;
                   2582: end;
                   2583: 
                   2584: 
                   2585: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2586: procedure TCustomEmulVT.SetLog(Value : Boolean);
                   2587: begin
                   2588:     if FLog = Value then
                   2589:         Exit;
                   2590: 
                   2591:     FLog := Value;
                   2592: 
                   2593:     if FLog then begin
                   2594: {$I-}
                   2595:         AssignFile(FFileHandle, 'EMULVT.LOG');
                   2596:         Append(FFileHandle);
                   2597:         if IOResult <> 0 then
                   2598:             Rewrite(FFileHandle);
                   2599:         Write(FFileHandle, '<Open>');
                   2600: {$I+}
                   2601:     end
                   2602:     else begin
                   2603:         Write(FFileHandle, '<Close>');
                   2604:         CloseFile(FFileHandle);
                   2605:     end;
                   2606: end;
                   2607: 
                   2608: 
                   2609: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2610: procedure TCustomEmulVT.SetXlat(Value : Boolean);
                   2611: begin
                   2612:     FScreen.FNoXlat        := not Value;
                   2613:     FScreen.FNoXlatInitial := not Value;
                   2614: end;
                   2615: 
                   2616: 
                   2617: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2618: function TCustomEmulVT.GetXlat : Boolean;
                   2619: begin
                   2620:     Result := not FScreen.FNoXlatInitial;
                   2621: end;
                   2622: 
                   2623: 
                   2624: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2625: function TCustomEmulVT.GetAutoLF : Boolean;
                   2626: begin
                   2627:     Result := FScreen.FAutoLF;
                   2628: end;
                   2629: 
                   2630: 
                   2631: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2632: function TCustomEmulVT.GetAutoCR : Boolean;
                   2633: begin
                   2634:     Result := FScreen.FAutoCR;
                   2635: end;
                   2636: 
                   2637: 
                   2638: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2639: destructor TCustomEmulVT.Destroy;
                   2640: begin
                   2641:     if FLog then
                   2642:         Log := FALSE;
                   2643: 
                   2644:     FFont.Free;
                   2645:     FVScrollBar.Free;
                   2646:     FScreen.Free;
                   2647:     DeleteObject(FPal);
                   2648:     inherited Destroy;
                   2649: end;
                   2650: 
                   2651: 
                   2652: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2653: procedure TCustomEmulVT.SetBackRows(Value : Integer);
                   2654: begin
                   2655:     with FScreen do begin
                   2656:         if FBackRowCount <> Value then begin
                   2657:             SetBackRowCount(Value);
                   2658:             AdjustScrollBar;
                   2659:         end;
                   2660:     end;
                   2661: end;
                   2662: 
                   2663: 
                   2664: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2665: procedure TCustomEmulVT.SetTopLine(Value : Integer);
                   2666: begin
                   2667:     if Value < FVScrollBar.Min then
                   2668:         Value := FVScrollBar.Min;
                   2669:     if Value > FVScrollBar.Max then
                   2670:         Value := FVScrollBar.Max;
                   2671:     FTopLine := Value;
                   2672:     FVScrollBar.Position := FTopLine;
                   2673:     Repaint;
                   2674: end;
                   2675: 
                   2676: 
                   2677: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2678: function TCustomEmulVT.GetBackRows : Integer;
                   2679: begin
                   2680:     Result := FScreen.FBackRowCount;
                   2681: end;
                   2682: 
                   2683: 
                   2684: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2685: procedure TCustomEmulVT.SetBackColor(Value : TBackColors);
                   2686: begin
                   2687:     FScreen.FBackColor := Value;
                   2688: end;
                   2689: 
                   2690: 
                   2691: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2692: function TCustomEmulVT.GetBackColor : TBackColors;
                   2693: begin
                   2694:     Result := FScreen.FBackColor;
                   2695: end;
                   2696: 
                   2697: 
                   2698: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2699: procedure TCustomEmulVT.SetOptions(Value : TScreenOptions);
                   2700: begin
                   2701:     FScreen.FOptions := Value;
                   2702: end;
                   2703: 
                   2704: 
                   2705: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2706: function TCustomEmulVT.GetOptions : TScreenOptions;
                   2707: begin
                   2708:     Result := FScreen.FOptions;
                   2709: end;
                   2710: 
                   2711: 
                   2712: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2713: procedure TCustomEmulVT.SetupFont;
                   2714: var
                   2715:     DC      : HDC;
                   2716:     Metrics : TTextMetric;
                   2717:     hObject : THandle;
                   2718: begin
                   2719:     DC      := GetDC(0);
                   2720:     hObject := SelectObject(DC, FFont.Handle);
                   2721:     GetTextMetrics(DC, Metrics);
                   2722:     SelectObject(DC, hOBject);
                   2723:     ReleaseDC(0, DC);
                   2724: 
                   2725:     SetCharWidth(Metrics.tmMaxCharWidth);
                   2726:     SetLineHeight(Metrics.tmHeight);
                   2727:     FInternalLeading := Metrics.tmInternalLeading;
                   2728: end;
                   2729: 
                   2730: 
                   2731: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2732: procedure TCustomEmulVT.SetCharWidth(newValue : Integer);
                   2733: var
                   2734:     nCol : Integer;
                   2735: begin
                   2736:     FCharWidth := newValue;
                   2737:     for nCol := Low(FCharPos) to High(FCharPos) do
                   2738:         FCharPos[nCol] := Trunc(FCharWidth * nCol * FCharZoom);
                   2739: end;
                   2740: 
                   2741: 
                   2742: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2743: procedure TCustomEmulVT.SetCharZoom(newValue : Single);
                   2744: begin
                   2745:     FCharZoom := newValue;
                   2746:     SetCharWidth(FCharWidth);
                   2747: end;
                   2748: 
                   2749: 
                   2750: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2751: procedure TCustomEmulVT.SetLineHeight(Value : Integer);
                   2752: var
                   2753:     nRow : Integer;
                   2754: begin
                   2755:     FLineHeight := Value;
                   2756:     for nRow := 0 to MAX_ROW do
                   2757:         FLinePos[nRow] := Trunc(FLineHeight * nRow * FLineZoom);
                   2758: end;
                   2759: 
                   2760: 
                   2761: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2762: procedure TCustomEmulVT.SetLineZoom(newValue : Single);
                   2763: begin
                   2764:     FLineZoom := newValue;
                   2765:     SetLineHeight(FLineHeight);
                   2766: end;
                   2767: 
                   2768: 
                   2769: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2770: procedure TCustomEmulVT.SetFont(Value : TFont);
                   2771: begin
                   2772:     FFont.Assign(Value);
                   2773: {$IFNDEF SINGLE_CHAR_PAINT}
                   2774:     FFont.Pitch := fpFixed;
                   2775: {$ENDIF}
                   2776:     SetupFont;
                   2777:     SetCaret;
                   2778: end;
                   2779: 
                   2780: 
                   2781: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2782: procedure TCustomEmulVT.WMLButtonDown(var Message: TWMLButtonDown);
                   2783: begin
                   2784:     inherited;
                   2785:     SetFocus;
                   2786: end;
                   2787: 
                   2788: 
                   2789: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2790: procedure TCustomEmulVT.VScrollBarScroll(Sender: TObject; ScrollCode: TScrollCode; var ScrollPos: Integer);
                   2791: begin
                   2792:     FTopLine := ScrollPos;
                   2793:     Repaint;
                   2794:     SetFocus;
                   2795: end;
                   2796: 
                   2797: 
                   2798: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2799: procedure TCustomEmulVT.DoKeyBuffer(Buffer : PChar; Len : Integer);
                   2800: var
                   2801:     J : Integer;
                   2802:     ch : Char;
                   2803: begin
                   2804:     if Assigned(FOnKeyBuffer) then
                   2805:         FOnKeyBuffer(Self, Buffer, Len)
                   2806:     else begin
                   2807:         for J := 0 to Len - 1 do begin
                   2808:             ch := Buffer[J];
                   2809:             KeyPress(ch);
                   2810:         end;
                   2811:     end;
                   2812: end;
                   2813: 
                   2814: 
                   2815: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2816: function TCustomEmulVT.FindFKeys(ScanCode: Char; Shift: TShiftState;
                   2817:                                  Ext: Boolean) : PFuncKeyValue;
                   2818: var
                   2819:     I      : Integer;
                   2820:     pFKeys : PFuncKeysTable;
                   2821: begin
                   2822:     Result := nil;
                   2823:     case FKeys of
                   2824:     0 : pFKeys := @FKeys1;
                   2825:     1 : pFKeys := @FKeys2;
                   2826:     2 : pFKeys := @FKeys3;
                   2827:     else
                   2828:         pFKeys := @FKeys2;
                   2829:     end;
                   2830: 
                   2831:     for I := Low(pFKeys^) to High(pFKeys^) do begin
                   2832:         if (pFKeys^[I].ScanCode <> #0) and (pFKeys^[I].ScanCode = ScanCode) and
                   2833:            (pFKeys^[I].Shift = Shift) and
                   2834:            (pFKeys^[I].Ext = Ext) then begin
                   2835:             Result := @pFKeys^[I].Value;
                   2836:             Break;
                   2837:         end;
                   2838:     end;
                   2839: end;
                   2840: 
                   2841: 
                   2842: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2843: function TCustomEmulVT.ProcessFKeys(ScanCode: Char; Shift: TShiftState;
                   2844:                                     Ext: Boolean) : Boolean;
                   2845: var
                   2846:     I      : Integer;
                   2847:     pFKeys : PFuncKeysTable;
                   2848: begin
                   2849:     Result := FALSE;
                   2850:     case FKeys of
                   2851:     0 : pFKeys := @FKeys1;
                   2852:     1 : pFKeys := @FKeys2;
                   2853:     2 : pFKeys := @FKeys3;
                   2854:     else
                   2855:         pFKeys := @FKeys2;
                   2856:     end;
                   2857: 
                   2858:     for I := Low(pFKeys^) to High(pFKeys^) do begin
                   2859:         if (pFKeys^[I].ScanCode <> #0) and (pFKeys^[I].ScanCode = ScanCode) and
                   2860:            (pFKeys^[I].Shift = Shift) and
                   2861:            (pFKeys^[I].Ext = Ext) then begin
                   2862:             Result := TRUE;
                   2863:             DoKeyBuffer(@pFKeys^[I].Value[1], Length(pFKeys^[I].Value));
                   2864:             Break;
                   2865:         end;
                   2866:     end;
                   2867: end;
                   2868: 
                   2869: 
                   2870: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   2871: procedure TCustomEmulVT.AppMessageHandler(var Msg: TMsg; var Handled: Boolean);
                   2872: const
                   2873:     v1 : String = 'aeiou';
                   2874:     v2 : String = '�����';
                   2875:     v3 : String = '�����';
                   2876:     SpyFlag : Boolean = FALSE;
                   2877: var
                   2878:     Shift     : TShiftState;
                   2879:     ShiftLock : Boolean;
                   2880:     VirtKey   : Integer;
                   2881:     Key       : Char;
                   2882:     I         : Integer;
                   2883:     ScanCode  : Char;
                   2884:     Ext       : Boolean;
                   2885:     SpyBuffer : String;
                   2886:     FnBuffer  : String;
                   2887:     pFV       : PFuncKeyValue;
                   2888: begin
                   2889:     if (Msg.hWnd = Handle) and (Msg.Message = WM_KEYDOWN) then begin
                   2890:         VirtKey   := Msg.wParam;
                   2891:         Key       := chr(Msg.wParam and $FF);
                   2892: {        DebugString('AppMessageHandler KEYDOWN ' + IntToHex(Msg.wParam, 4) + #13 + #10); }
                   2893:         Shift     := KeyDataToShiftState(Msg.lParam);
                   2894:         ShiftLock := ((GetKeyState(VK_CAPITAL) and 1) > 0);
                   2895:         ScanCode  := Chr(LOBYTE(HIWORD(Msg.lParam)));
                   2896:         Ext       := ((Msg.lParam and $1000000) <> 0);
                   2897: 
                   2898:         if Assigned(FOnKeyDown) then begin
                   2899:             FOnKeyDown(Self, VirtKey, Shift, ShiftLock, ScanCode, Ext);
                   2900:             if VirtKey = 0 then begin
                   2901:                 Handled := TRUE;
                   2902:                 Exit;
                   2903:             end;
                   2904:         end;
                   2905: 
                   2906:         if (Msg.wParam <> VK_SHIFT) and
                   2907:            (Msg.wParam <> VK_CONTROL) and
                   2908:            (Msg.wParam <> VK_MENU) then begin
                   2909:             if (ScanCode = '7') and
                   2910:                (Shift = [ssAlt, ssCtrl]) and (Ext = FALSE) then begin
                   2911:                 { This is CTRL-ALT-* (on num pad) }
                   2912:                 SpyFlag := TRUE;
                   2913:                 Handled := TRUE;
                   2914:                 Exit;
                   2915:             end;
                   2916: 
                   2917:             if SpyFlag then begin
                   2918:                 SpyFlag   := FALSE;
                   2919:                 pFV       := FindFKeys(ScanCode, Shift, Ext);
                   2920:                 SpyBuffer := IntToHex(Ord(ScanCode), 2) + ', ' +
                   2921:                              ShiftStateToString(Shift) + ', ';
                   2922: 
                   2923:                 if Ext then
                   2924:                     SpyBuffer := SpyBuffer + 'TRUE'
                   2925:                 else
                   2926:                     SpyBuffer := SpyBuffer + 'FALSE';
                   2927: 
                   2928:                 if pFV <> nil then
                   2929:                     SpyBuffer := SpyBuffer + ', ''' +
                   2930:                                  FuncKeyValueToString(pFV^) + '''';
                   2931: 
                   2932:                 SpyBuffer := SpyBuffer + #0;
                   2933:                 ClipBoard.SetTextBuf(@SpyBuffer[1]);
                   2934: 
                   2935:                 FnBuffer := 'Key definition from tnchrk' +
                   2936:                             IntToStr(FKeys) + '.cfg' + #0;
                   2937:                 Application.MessageBox(@SpyBuffer[1], @FnBuffer[1], MB_OK);
                   2938:                 Handled := TRUE;
                   2939:                 Exit;
                   2940:             end;
                   2941: 
                   2942:             if ProcessFKeys(ScanCode, Shift, Ext) then begin
                   2943:                 Handled := TRUE;
                   2944:                 Exit;
                   2945:             end;
                   2946:         end;
                   2947: 
                   2948:         case Msg.wParam of
                   2949:         VK_SHIFT, VK_CONTROL, VK_MENU: ;
                   2950: 
                   2951:         VK_NEXT, VK_PRIOR, VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_HOME, VK_END:
                   2952:             begin
                   2953:                 if ProcessFKeys(ScanCode, Shift, TRUE) then begin
                   2954:                     Handled := TRUE;
                   2955:                     Exit;
                   2956:                 end;
                   2957:             end;
                   2958:         VK_TAB, VK_RETURN, VK_ESCAPE, VK_BACK:
                   2959:             begin
                   2960:                 Handled := TRUE;
                   2961:             end;
                   2962: 
                   2963:         $DD:
                   2964:             begin
                   2965:                 if not (ssAlt in Shift) then begin
                   2966:                     Key     := #0;
                   2967:                     Handled := TRUE;
                   2968:                     if (ssShift in Shift) then
                   2969:                         FFlagTrema := TRUE
                   2970:                     else
                   2971:                         FFlagCirconflexe := TRUE;
                   2972:                 end;
                   2973:             end;
                   2974: 
                   2975:         ord('A')..ord('Z') :
                   2976:             begin
                   2977:                 if (ssCtrl in Shift) then
                   2978:                     Key := chr(Word(Key) and $1F)
                   2979:                 else if not ShiftLock and not (ssShift in Shift) then
                   2980:                     Key := chr(Word(Key) or $20);
                   2981:                 if (FFlagCirconflexe) then begin
                   2982:                     for I := Length(v1) downto 1 do begin
                   2983:                         if Key = v1[I] then begin
                   2984:                             Key := v2[I];
                   2985:                             Break;
                   2986:                         end;
                   2987:                     end;
                   2988:                     FFlagCirconflexe := FALSE;
                   2989:                 end;
                   2990:                 if (FFlagTrema) then begin
                   2991:                     for I := Length(v1) downto 1 do begin
                   2992:                         if Key = v1[I] then begin
                   2993:                             Key := v3[I];
                   2994:                             Break;
                   2995:                         end;
                   2996:                     end;
                   2997:                     FFlagTrema       := FALSE;
                   2998:                 end;
                   2999:                 Handled := TRUE;
                   3000:             end;
                   3001:         end;
                   3002: 
                   3003: {        DebugString('Char = ' + IntToHex(Integer(Key), 2) + #13 + #10); }
                   3004:         if Handled and (Key <> #0) then
                   3005:             KeyPress(Key);
                   3006:     end;
                   3007: 
                   3008:     if not Handled and Assigned(FAppOnMessage) then
                   3009:         FAppOnMessage(Msg, Handled);
                   3010: end;
                   3011: 
                   3012: 
                   3013: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3014: procedure TCustomEmulVT.KeyPress(var Key: Char);
                   3015: begin
                   3016:     if not FScreen.FNoXlat then
                   3017:         Key := FScreen.FXlatOutputTable^[ord(Key)];
                   3018: 
                   3019:     inherited KeyPress(Key);
                   3020:     if FLocalEcho then begin
                   3021:         WriteChar(Key);
                   3022:         if not FAutoRepaint then
                   3023:             UpdateScreen;
                   3024:     end;
                   3025: end;
                   3026: 
                   3027: 
                   3028: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3029: procedure TCustomEmulVT.WMSetFocus(var Message: TWMSetFocus);
                   3030: begin
                   3031: {    inherited; }
                   3032:     FScreen.Focused := TRUE;
                   3033: {    SetupFont; }
                   3034: 
                   3035:     if not FCursorVisible then
                   3036:         Exit;
                   3037: 
                   3038:     CreateCaret(Handle, 0, 2, FLineHeight);
                   3039:     FCaretCreated := TRUE;
                   3040:     SetCaret;
                   3041:     if not FScreen.FCursorOff then begin
                   3042:         ShowCaret(Handle);
                   3043:         FCaretShown := TRUE;
                   3044:     end;
                   3045: 
                   3046:     FAppOnMessage := Application.OnMessage;
                   3047:     Application.OnMessage := AppMessageHandler;
                   3048: end;
                   3049: 
                   3050: 
                   3051: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3052: procedure TCustomEmulVT.WMKillFocus(var Message: TWMKillFocus);
                   3053: begin
                   3054: {    inherited; }
                   3055:     FScreen.Focused := FALSE;
                   3056: 
                   3057:     if not FCursorVisible then
                   3058:         Exit;
                   3059: 
                   3060:     if FCaretShown then begin
                   3061:         HideCaret(Handle);
                   3062:         FCaretShown := FALSE;
                   3063:     end;
                   3064: 
                   3065:     if FCaretCreated then begin
                   3066:         DestroyCaret;
                   3067:         FCaretCreated := FALSE;
                   3068:     end;
                   3069: 
                   3070:     Application.OnMessage := FAppOnMessage;
                   3071: end;
                   3072: 
                   3073: 
                   3074: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3075: procedure TCustomEmulVT.MouseToCell(X, Y: Integer; var ACol, ARow: Longint);
                   3076: begin
                   3077: {$IFDEF CHAR_ZOOM}
                   3078:     aRow := FScreen.FRowCount - 1;
                   3079:     while (Y - TopMargin) <= FLinePos[aRow] do
                   3080:         Dec(aRow);
                   3081: {$ELSE}
                   3082:     aRow := (Y - TopMargin) div FLineHeight;
                   3083: {$ENDIF}
                   3084:     if aRow < 0 then
                   3085:         aRow := 0
                   3086:     else if aRow >= FScreen.FRowCount then
                   3087:         aRow := FScreen.FRowCount - 1;
                   3088: 
                   3089: {$IFDEF CHAR_ZOOM}
                   3090:     aCol := FScreen.FColCount - 1;
                   3091:     while (X - LeftMargin) <= FCharPos[aCol] do
                   3092:         Dec(aCol);
                   3093: {$ELSE}
                   3094:     aCol := (X - LeftMargin) div FCharWidth;
                   3095: {$ENDIF}
                   3096:     if aCol < 0 then
                   3097:         aCol := 0
                   3098:     else if aCol >= FScreen.FColCount then
                   3099:         aCol := FScreen.FColCount - 1;
                   3100: end;
                   3101: 
                   3102: 
                   3103: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3104: procedure TCustomEmulVT.ShowCursor;
                   3105: begin
                   3106:     SetCaret;
                   3107: end;
                   3108: 
                   3109: 
                   3110: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3111: procedure TCustomEmulVT.WMPaletteChanged(var Message : TMessage);
                   3112: {var
                   3113:     HandleDC : HDC;}
                   3114: begin
                   3115: {        if Message.wParam <> Handle then begin
                   3116:             HandleDC := GetDC(Handle);
                   3117:             SelectPalette(HandleDC, FPal, FALSE);
                   3118:             if RealizePalette(HandleDC) <> 0 then begin
                   3119:                 InvalidateRect(Handle, nil, TRUE);
                   3120:                 MessageBeep(0);
                   3121:             end;
                   3122:             ReleaseDC(Handle, HandleDC);
                   3123:         end;
                   3124: }
                   3125: end;
                   3126: 
                   3127: 
                   3128: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3129: procedure TCustomEmulVT.UpdateScreen;
                   3130: var
                   3131:     rc : TRect;
                   3132: begin
                   3133:     if FScreen.FAllInvalid then
                   3134:         InvalidateRect(Handle, nil, FALSE)
                   3135:     else begin
                   3136: {$Q-}
                   3137:             with FScreen.FInvRect do begin
                   3138: {$IFDEF CHAR_ZOOM}
                   3139:                 if Left = 9999 then begin
                   3140:                     rc.Top    := 0;
                   3141:                     rc.Bottom := 0;
                   3142:                     rc.Left   := 0;
                   3143:                     rc.Right  := 0;
                   3144:                 end
                   3145:                 else begin
                   3146:                     rc.Top    := TopMargin  + FLinePos[Top - FTopLine] + FInternalLeading;
                   3147:                     rc.Bottom := TopMargin  + FLinePos[Bottom + 1 - FTopLine] + FInternalLeading;
                   3148:                     rc.Left   := LeftMargin + FCharPos[Left];
                   3149:                     rc.Right  := LeftMargin + FCharPos[Right + 1];
                   3150:                 end;
                   3151: {$ELSE}
                   3152:                 rc.Top    := TopMargin  + FLineHeight * (Top - FTopLine) + FInternalLeading;
                   3153:                 rc.Bottom := TopMargin  + FLineHeight * (Bottom + 1 - FTopLine) + FInternalLeading;
                   3154:                 rc.Left   := LeftMargin + FCharWidth * Left;
                   3155:                 rc.Right  := LeftMargin + FCharWidth * (Right + 1);
                   3156: {$ENDIF}
                   3157:             end;
                   3158:             InvalidateRect(Handle, @rc, FALSE);
                   3159: {$Q+}
                   3160:     end;
                   3161: 
                   3162:     { Invalidate the region where the caret is. I should'nt do that, but }
                   3163:     { if I do'nt, the caret remains where it is ! Bug ?                  }
                   3164: {$IFDEF CHAR_ZOOM}
                   3165:     rc.Top    := FLinePos[FScreen.FRow - FTopLine] + TopMargin;
                   3166:     rc.Bottom := FLinePos[FScreen.FRow - FTopLine + 1] + TopMargin;
                   3167:     rc.Left   := LeftMargin + FCharPos[FScreen.FCol];
                   3168:     rc.Right  := LeftMargin + FCharPos[FScreen.FCol + 1];
                   3169: {$ELSE}
                   3170:     rc.Top    := TopMargin  + FLineHeight * (FScreen.FRow - FTopLine);
                   3171:     rc.Bottom := rc.Top + FLineHeight;
                   3172:     rc.Left   := LeftMargin + FCharWidth * FScreen.FCol;
                   3173:     rc.Right  := rc.Left + FCharWidth;
                   3174: {$ENDIF}
                   3175:     InvalidateRect(Handle, @rc, FALSE);
                   3176: 
                   3177:     FScreen.InvClear;
                   3178: 
                   3179:     if FCaretCreated then begin
                   3180:         ShowCaret(Handle);
                   3181:         FCaretShown := TRUE;
                   3182:     end;
                   3183:     SetCaret;
                   3184: end;
                   3185: 
                   3186: 
                   3187: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3188: function TCustomEmulVT.SnapPixelToRow(Y : Integer) : Integer;
                   3189: var
                   3190:     nRow : Integer;
                   3191: begin
                   3192:     nRow := PixelToRow(Y);
                   3193: {$IFDEF CHAR_ZOOM}
                   3194:     Result := TopMargin + FLinePos[nRow];
                   3195: {$ELSE}
                   3196:     Result := TopMargin + nRow * FLineHeight;
                   3197: {$ENDIF}
                   3198: end;
                   3199: 
                   3200: 
                   3201: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3202: function TCustomEmulVT.SnapPixelToCol(X : Integer) : Integer;
                   3203: var
                   3204:     nCol : Integer;
                   3205: begin
                   3206:     nCol := PixelToCol(X);
                   3207: {$IFDEF CHAR_ZOOM}
                   3208:     Result := LeftMargin + FCharPos[nCol];
                   3209: {$ELSE}
                   3210:     Result := LeftMargin + nCol * FCharWidth;
                   3211: {$ENDIF}
                   3212: end;
                   3213: 
                   3214: 
                   3215: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3216: function TCustomEmulVT.PixelToRow(Y : Integer) : Integer;
                   3217: var
                   3218:     nRow : Integer;
                   3219: begin
                   3220: {$IFDEF CHAR_ZOOM}
                   3221:     nRow := FScreen.FRowCount - 1;
                   3222:     while (nRow > 0) and ((Y - TopMargin) < FLinePos[nRow]) do
                   3223:         Dec(nRow);
                   3224: {$ELSE}
                   3225:     nRow := (Y - TopMargin) div FLineHeight;
                   3226: {$ENDIF}
                   3227:     if nRow < 0 then
                   3228:         nRow := 0;
                   3229:     Result := nRow;
                   3230: end;
                   3231: 
                   3232: 
                   3233: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3234: function TCustomEmulVT.PixelToCol(X : Integer) : Integer;
                   3235: var
                   3236:     nCol : Integer;
                   3237: begin
                   3238: {$IFDEF CHAR_ZOOM}
                   3239:     nCol := FScreen.FColCount - 1;
                   3240:     while (X - LeftMargin) < FCharPos[nCol] do
                   3241:         Dec(nCol);
                   3242: {$ELSE}
                   3243:     nCol := (X - LeftMargin) div FCharWidth;
                   3244: {$ENDIF}
                   3245:     if nCol < 0 then
                   3246:         nCol := 0;
                   3247:     Result := nCol;
                   3248: end;
                   3249: 
                   3250: 
                   3251: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3252: { This procedure will paint graphic char from the OEM charset (lines,       }
                   3253: { corners, T and other like) using GDI functions. This will result in       }
                   3254: { autosized characters, necessary for example to draw a frame when zoom     }
                   3255: { affect character and line spacing.                                        }
                   3256: procedure TCustomEmulVT.PaintGraphicChar(
                   3257:     DC   : HDC;
                   3258:     X, Y : Integer;
                   3259:     rc   : PRect;
                   3260:     ch   : Char);
                   3261: const
                   3262:     OneSpace : Char = ' ';
                   3263: var
                   3264:     X1, X2, X3 : Integer;
                   3265:     Y1, Y2, Y3 : Integer;
                   3266:     Co         : TColor;
                   3267: begin
                   3268:     ExtTextOut(DC,
                   3269:                X, Y,
                   3270:                ETO_OPAQUE or ETO_CLIPPED, rc,
                   3271:                @OneSpace, 1, nil);
                   3272:     X1 := X;
                   3273:     X3 := rc^.Right;
                   3274:     X2 := (X1 + X3) div 2;
                   3275:     Y1 := rc^.Top;
                   3276:     Y3 := rc^.Bottom;
                   3277:     Y2 := (Y1 + Y3) div 2;
                   3278:     case Ch of
                   3279:     #$C4: begin       { Horizontal single line }
                   3280:               Canvas.MoveTo(X1, Y2);
                   3281:               Canvas.LineTo(X3, Y2);
                   3282:           end;
                   3283:     #$B3: begin       { Vertical single line }
                   3284:               Canvas.MoveTo(X2, Y1);
                   3285:               Canvas.LineTo(X2, Y3);
                   3286:           end;
                   3287:     #$DA: begin       { Upper Left Single Corner }
                   3288:               Canvas.MoveTo(X3, Y2);
                   3289:               Canvas.LineTo(X2, Y2);
                   3290:               Canvas.LineTo(X2, Y3);
                   3291:           end;
                   3292:     #$C0: begin       { Bottom Left Single Corner }
                   3293:               Canvas.MoveTo(X2, Y1);
                   3294:               Canvas.LineTo(X2, Y2);
                   3295:               Canvas.LineTo(X3, Y2);
                   3296:           end;
                   3297:     #$C1: begin       { Reverse T }
                   3298:               Canvas.MoveTo(X2, Y1);
                   3299:               Canvas.LineTo(X2, Y2);
                   3300:               Canvas.MoveTo(X1, Y2);
                   3301:               Canvas.LineTo(X3, Y2);
                   3302:           end;
                   3303:     #$C2: begin       { T }
                   3304:               Canvas.MoveTo(X2, Y3);
                   3305:               Canvas.LineTo(X2, Y2);
                   3306:               Canvas.MoveTo(X1, Y2);
                   3307:               Canvas.LineTo(X3, Y2);
                   3308:           end;
                   3309:     #$C3: begin       { Left T }
                   3310:               Canvas.MoveTo(X2, Y1);
                   3311:               Canvas.LineTo(X2, Y3);
                   3312:               Canvas.MoveTo(X2, Y2);
                   3313:               Canvas.LineTo(X3, Y2);
                   3314:           end;
                   3315:     #$B4: begin       { Right T }
                   3316:               Canvas.MoveTo(X2,     Y1);
                   3317:               Canvas.LineTo(X2,     Y3);
                   3318:               Canvas.MoveTo(X2,     Y2);
                   3319:               Canvas.LineTo(X1 - 1, Y2);
                   3320:           end;
                   3321:     #$BF: begin       { Top Right Single Corner }
                   3322:               Canvas.MoveTo(X1, Y2);
                   3323:               Canvas.LineTo(X2, Y2);
                   3324:               Canvas.LineTo(X2, Y3);
                   3325:           end;
                   3326:     #$D9: begin       { Bottom Right Single Corner }
                   3327:               Canvas.MoveTo(X1, Y2);
                   3328:               Canvas.LineTo(X2, Y2);
                   3329:               Canvas.LineTo(X2, Y1 - 1);
                   3330:           end;
                   3331:     #$D6: begin       { Upper Left Single/Double Corner }
                   3332:               Canvas.MoveTo(X3, Y2);
                   3333:               Canvas.LineTo(X2 - 1, Y2);
                   3334:               Canvas.LineTo(X2 - 1, Y3);
                   3335:               Canvas.MoveTo(X2 + 1, Y2);
                   3336:               Canvas.LineTo(X2 + 1, Y3);
                   3337:           end;
                   3338:     #$D3: begin       { Bottom Left Single/Double Corner }
                   3339:               Canvas.MoveTo(X2 - 1, Y1);
                   3340:               Canvas.LineTo(X2 - 1, Y2);
                   3341:               Canvas.LineTo(X3, Y2);
                   3342:               Canvas.MoveTo(X2 + 1, Y1);
                   3343:               Canvas.LineTo(X2 + 1, Y2);
                   3344:           end;
                   3345:     #$B7: begin       { Top Right Single/Double Corner }
                   3346:               Canvas.MoveTo(X1, Y2);
                   3347:               Canvas.LineTo(X2 + 1, Y2);
                   3348:               Canvas.LineTo(X2 + 1, Y3);
                   3349:               Canvas.MoveTo(X2 - 1, Y2);
                   3350:               Canvas.LineTo(X2 - 1, Y3);
                   3351:           end;
                   3352:     #$BD: begin       { Bottom Right Single/Double Corner }
                   3353:               Canvas.MoveTo(X2 + 1, Y1);
                   3354:               Canvas.LineTo(X2 + 1, Y2);
                   3355:               Canvas.LineTo(X1 - 1, Y2);
                   3356:               Canvas.MoveTo(X2 - 1, Y1);
                   3357:               Canvas.LineTo(X2 - 1, Y2);
                   3358:           end;
                   3359:     #$D5: begin       { Upper Left Double/Single Corner }
                   3360:               Canvas.MoveTo(X3, Y2 - 1);
                   3361:               Canvas.LineTo(X2, Y2 - 1);
                   3362:               Canvas.LineTo(X2, Y3);
                   3363:               Canvas.MoveTo(X3, Y2 + 1);
                   3364:               Canvas.LineTo(X2, Y2 + 1);
                   3365:           end;
                   3366:     #$D4: begin       { Bottom Left Double/Single Corner }
                   3367:               Canvas.MoveTo(X2, Y1);
                   3368:               Canvas.LineTo(X2, Y2 + 1);
                   3369:               Canvas.LineTo(X3, Y2 + 1);
                   3370:               Canvas.MoveTo(X2, Y2 - 1);
                   3371:               Canvas.LineTo(X3, Y2 - 1);
                   3372:           end;
                   3373:     #$B8: begin       { Top Right Double/Single Corner }
                   3374:               Canvas.MoveTo(X1, Y2 - 1);
                   3375:               Canvas.LineTo(X2, Y2 - 1);
                   3376:               Canvas.LineTo(X2, Y3);
                   3377:               Canvas.MoveTo(X1, Y2 + 1);
                   3378:               Canvas.LineTo(X2, Y2 + 1);
                   3379:           end;
                   3380:     #$BE: begin       { Bottom Right Double/Single Corner }
                   3381:               Canvas.MoveTo(X2,     Y1);
                   3382:               Canvas.LineTo(X2,     Y2 + 1);
                   3383:               Canvas.LineTo(X1 - 1, Y2 + 1);
                   3384:               Canvas.MoveTo(X1,     Y2 - 1);
                   3385:               Canvas.LineTo(X2,     Y2 - 1);
                   3386:           end;
                   3387:     #$CD: begin       { Horizontal Double line }
                   3388:               Canvas.MoveTo(X1, Y2 + 1);
                   3389:               Canvas.LineTo(X3, Y2 + 1);
                   3390:               Canvas.MoveTo(X1, Y2 - 1);
                   3391:               Canvas.LineTo(X3, Y2 - 1);
                   3392:           end;
                   3393:     #$BA: begin       { Vertical Double line }
                   3394:               Canvas.MoveTo(X2 + 1, Y1);
                   3395:               Canvas.LineTo(X2 + 1, Y3);
                   3396:               Canvas.MoveTo(X2 - 1, Y1);
                   3397:               Canvas.LineTo(X2 - 1, Y3);
                   3398:           end;
                   3399:     #$D1: begin       { T Top Horizontal Double line }
                   3400:               Canvas.MoveTo(X1, Y2 + 1);
                   3401:               Canvas.LineTo(X3, Y2 + 1);
                   3402:               Canvas.MoveTo(X1, Y2 - 1);
                   3403:               Canvas.LineTo(X3, Y2 - 1);
                   3404:               Canvas.MoveTo(X2, Y2 + 1);
                   3405:               Canvas.LineTo(X2, Y3);
                   3406:           end;
                   3407:     #$CF: begin       { T Bottom Horizontal Double line }
                   3408:               Canvas.MoveTo(X1, Y2 + 1);
                   3409:               Canvas.LineTo(X3, Y2 + 1);
                   3410:               Canvas.MoveTo(X1, Y2 - 1);
                   3411:               Canvas.LineTo(X3, Y2 - 1);
                   3412:               Canvas.MoveTo(X2, Y2 - 1);
                   3413:               Canvas.LineTo(X2, Y1);
                   3414:           end;
                   3415:     #$C6: begin       { T Left Horizontal Double line }
                   3416:               Canvas.MoveTo(X2, Y2 + 1);
                   3417:               Canvas.LineTo(X3, Y2 + 1);
                   3418:               Canvas.MoveTo(X2, Y2 - 1);
                   3419:               Canvas.LineTo(X3, Y2 - 1);
                   3420:               Canvas.MoveTo(X2, Y1);
                   3421:               Canvas.LineTo(X2, Y3);
                   3422:           end;
                   3423:     #$B5: begin       { T Right Horizontal Double line }
                   3424:               Canvas.MoveTo(X1, Y2 + 1);
                   3425:               Canvas.LineTo(X2, Y2 + 1);
                   3426:               Canvas.MoveTo(X1, Y2 - 1);
                   3427:               Canvas.LineTo(X2, Y2 - 1);
                   3428:               Canvas.MoveTo(X2, Y1);
                   3429:               Canvas.LineTo(X2, Y3);
                   3430:           end;
                   3431:     #$C9: begin       { Upper Left Double Corner }
                   3432:               Canvas.MoveTo(X3,     Y2 - 1);
                   3433:               Canvas.LineTo(X2 - 1, Y2 - 1);
                   3434:               Canvas.LineTo(X2 - 1, Y3);
                   3435:               Canvas.MoveTo(X3,     Y2 + 1);
                   3436:               Canvas.LineTo(X2 + 1, Y2 + 1);
                   3437:               Canvas.LineTo(X2 + 1, Y3);
                   3438:           end;
                   3439:     #$C8: begin       { Bottom Left Double Corner }
                   3440:               Canvas.MoveTo(X2 - 1, Y1);
                   3441:               Canvas.LineTo(X2 - 1, Y2 + 1);
                   3442:               Canvas.LineTo(X3,     Y2 + 1);
                   3443:               Canvas.MoveTo(X2 + 1, Y1);
                   3444:               Canvas.LineTo(X2 + 1, Y2 - 1);
                   3445:               Canvas.LineTo(X3,     Y2 - 1);
                   3446:           end;
                   3447:     #$BB: begin       { Top Right Double Corner }
                   3448:               Canvas.MoveTo(X1,     Y2 - 1);
                   3449:               Canvas.LineTo(X2 + 1, Y2 - 1);
                   3450:               Canvas.LineTo(X2 + 1, Y3);
                   3451:               Canvas.MoveTo(X1,     Y2 + 1);
                   3452:               Canvas.LineTo(X2 - 1, Y2 + 1);
                   3453:               Canvas.LineTo(X2 - 1, Y3);
                   3454:           end;
                   3455:     #$BC: begin       { Bottom Right Double Corner }
                   3456:               Canvas.MoveTo(X2 - 1, Y1);
                   3457:               Canvas.LineTo(X2 - 1, Y2 - 1);
                   3458:               Canvas.LineTo(X1 - 1, Y2 - 1);
                   3459:               Canvas.MoveTo(X2 + 1, Y1);
                   3460:               Canvas.LineTo(X2 + 1, Y2 + 1);
                   3461:               Canvas.LineTo(X1 - 1, Y2 + 1);
                   3462:           end;
                   3463:     #$CC: begin       { Double left T }
                   3464:               Canvas.MoveTo(X2 - 1, Y1);
                   3465:               Canvas.LineTo(X2 - 1, Y3);
                   3466:               Canvas.MoveTo(X2 + 1, Y1);
                   3467:               Canvas.LineTo(X2 + 1, Y2 - 1);
                   3468:               Canvas.LineTo(X3,     Y2 - 1);
                   3469:               Canvas.MoveTo(X3,     Y2 + 1);
                   3470:               Canvas.LineTo(X2 + 1, Y2 + 1);
                   3471:               Canvas.LineTo(X2 + 1, Y3);
                   3472:           end;
                   3473:     #$B9: begin       { Double Right T }
                   3474:               Canvas.MoveTo(X2 + 1, Y1);
                   3475:               Canvas.LineTo(X2 + 1, Y3);
                   3476:               Canvas.MoveTo(X2 - 1, Y1);
                   3477:               Canvas.LineTo(X2 - 1, Y2 - 1);
                   3478:               Canvas.LineTo(X1 - 1, Y2 - 1);
                   3479:               Canvas.MoveTo(X1,     Y2 + 1);
                   3480:               Canvas.LineTo(X2 - 1, Y2 + 1);
                   3481:               Canvas.LineTo(X2 - 1, Y3);
                   3482:           end;
                   3483:     #$C7: begin       { Double T Single Left }
                   3484:               Canvas.MoveTo(X2 + 1, Y1);
                   3485:               Canvas.LineTo(X2 + 1, Y3);
                   3486:               Canvas.MoveTo(X2 - 1, Y1);
                   3487:               Canvas.LineTo(X2 - 1, Y3);
                   3488:               Canvas.MoveTo(X2 + 1, Y2);
                   3489:               Canvas.LineTo(X3,     Y2);
                   3490:           end;
                   3491:     #$B6: begin       { Double T Single Right }
                   3492:               Canvas.MoveTo(X2 + 1, Y1);
                   3493:               Canvas.LineTo(X2 + 1, Y3);
                   3494:               Canvas.MoveTo(X2 - 1, Y1);
                   3495:               Canvas.LineTo(X2 - 1, Y3);
                   3496:               Canvas.MoveTo(X2 - 1, Y2);
                   3497:               Canvas.LineTo(X1 - 1, Y2);
                   3498:           end;
                   3499:     #$D2: begin       { Single T Double Top }
                   3500:               Canvas.MoveTo(X1, Y2);
                   3501:               Canvas.LineTo(X3, Y2);
                   3502:               Canvas.MoveTo(X2 - 1, Y2);
                   3503:               Canvas.LineTo(X2 - 1, Y3);
                   3504:               Canvas.MoveTo(X2 + 1, Y2);
                   3505:               Canvas.LineTo(X2 + 1, Y3);
                   3506:           end;
                   3507:     #$D0: begin       { Single T Double Bottom }
                   3508:               Canvas.MoveTo(X1, Y2);
                   3509:               Canvas.LineTo(X3, Y2);
                   3510:               Canvas.MoveTo(X2 - 1, Y2);
                   3511:               Canvas.LineTo(X2 - 1, Y1);
                   3512:               Canvas.MoveTo(X2 + 1, Y2);
                   3513:               Canvas.LineTo(X2 + 1, Y1);
                   3514:           end;
                   3515:     #$DB: begin       { Full Block }
                   3516:               Canvas.Rectangle(X1, Y1, X3, Y3);
                   3517:           end;
                   3518:     #$DC: begin       { Half Bottom Block }
                   3519:               Canvas.Rectangle(X1, Y2, X3, Y3);
                   3520:           end;
                   3521:     #$DD: begin       { Half Left Block }
                   3522:               Canvas.Rectangle(X1, Y1, X2, Y3);
                   3523:           end;
                   3524:     #$DE: begin       { Half Right Block }
                   3525:               Canvas.Rectangle(X2, Y1, X3, Y3);
                   3526:           end;
                   3527:     #$DF: begin       { Half Top Block }
                   3528:               Canvas.Rectangle(X1, Y1, X2, Y2);
                   3529:           end;
                   3530:     #$C5: begin       { Single Cross }
                   3531:               Canvas.MoveTo(X1, Y2);
                   3532:               Canvas.LineTo(X3, Y2);
                   3533:               Canvas.MoveTo(X2, Y1);
                   3534:               Canvas.LineTo(X2, Y3);
                   3535:           end;
                   3536:     #$CE: begin       { Double Cross }
                   3537:               Canvas.MoveTo(X1,     Y2 - 1);
                   3538:               Canvas.LineTo(X2 - 1, Y2 - 1);
                   3539:               Canvas.LineTo(X2 - 1, Y1);
                   3540:               Canvas.MoveTo(X1,     Y2 + 1);
                   3541:               Canvas.LineTo(X2 - 1, Y2 + 1);
                   3542:               Canvas.LineTo(X2 - 1, Y3);
                   3543:               Canvas.MoveTo(X2 + 1, Y1);
                   3544:               Canvas.LineTo(X2 + 1, Y2 - 1);
                   3545:               Canvas.LineTo(X3,     Y2 - 1);
                   3546:               Canvas.MoveTo(X2 + 1, Y3);
                   3547:               Canvas.LineTo(X2 + 1, Y2 + 1);
                   3548:               Canvas.LineTo(X3,     Y2 + 1);
                   3549:           end;
                   3550:     #$D8: begin      { Cross Double Horizontal Single vertical }
                   3551:               Canvas.MoveTo(X1, Y2 + 1);
                   3552:               Canvas.LineTo(X3, Y2 + 1);
                   3553:               Canvas.MoveTo(X1, Y2 - 1);
                   3554:               Canvas.LineTo(X3, Y2 - 1);
                   3555:               Canvas.MoveTo(X2, Y1);
                   3556:               Canvas.LineTo(X2, Y3);
                   3557:           end;
                   3558:     #$D7: begin      { Cross Single Horizontal Double Vertical }
                   3559:               Canvas.MoveTo(X2 + 1, Y1);
                   3560:               Canvas.LineTo(X2 + 1, Y3);
                   3561:               Canvas.MoveTo(X2 - 1, Y1);
                   3562:               Canvas.LineTo(X2 - 1, Y3);
                   3563:               Canvas.MoveTo(X1,     Y2);
                   3564:               Canvas.LineTo(X3,     Y2);
                   3565:           end;
                   3566:     #$CA: begin      { Double T bottom }
                   3567:               Canvas.MoveTo(X1,     Y2 - 1);
                   3568:               Canvas.LineTo(X2 - 1, Y2 - 1);
                   3569:               Canvas.LineTo(X2 - 1, Y1);
                   3570:               Canvas.MoveTo(X2 + 1, Y1);
                   3571:               Canvas.LineTo(X2 + 1, Y2 - 1);
                   3572:               Canvas.LineTo(X3,     Y2 - 1);
                   3573:               Canvas.MoveTo(X1,     Y2 + 1);
                   3574:               Canvas.LineTo(X3,     Y2 + 1);
                   3575:           end;
                   3576:     #$CB: begin      { Double T  }
                   3577:               Canvas.MoveTo(X1,     Y2 + 1);
                   3578:               Canvas.LineTo(X2 - 1, Y2 + 1);
                   3579:               Canvas.LineTo(X2 - 1, Y3);
                   3580:               Canvas.MoveTo(X2 + 1, Y3);
                   3581:               Canvas.LineTo(X2 + 1, Y2 + 1);
                   3582:               Canvas.LineTo(X3,     Y2 + 1);
                   3583:               Canvas.MoveTo(X1,     Y2 - 1);
                   3584:               Canvas.LineTo(X3,     Y2 - 1);
                   3585:           end;
                   3586:     #$B0: begin
                   3587:               Co := Canvas.Pen.Color;
                   3588:               for Y := Y1 to Y3 do begin
                   3589:                   X := X1 + (Y mod 3);
                   3590:                   while X < X3 do begin
                   3591:                       Canvas.Pixels[X, Y] := Co;
                   3592:                       X := X + 3;
                   3593:                   end;
                   3594:               end;
                   3595:           end;
                   3596:     #$B1: begin
                   3597:               Co := Canvas.Pen.Color;
                   3598:               for Y := Y1 to Y3 do begin
                   3599:                   X := X1 + (Y and 1);
                   3600:                   while X < X3 do begin
                   3601:                       Canvas.Pixels[X, Y] := Co;
                   3602:                       X := X + 2;
                   3603:                   end;
                   3604:               end;
                   3605:           end;
                   3606:     #$B2: begin
                   3607:               Co := Canvas.Pen.Color;
                   3608:               for Y := Y1 to Y3 do begin
                   3609:                   X := X1 + (Y mod 3);
                   3610:                   while X < X3 do begin
                   3611:                       Canvas.Pixels[X, Y] := Co;
                   3612:                       Inc(X);
                   3613:                       if X < X3 then
                   3614:                           Canvas.Pixels[X, Y] := Co;
                   3615:                       Inc(X);
                   3616:                       Inc(X);
                   3617:                   end;
                   3618:               end;
                   3619:           end;
                   3620:     end;
                   3621: end;
                   3622: 
                   3623: 
                   3624: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3625: procedure TCustomEmulVT.PaintOneLine(
                   3626:     DC         : HDC;
                   3627:     Y, Y1      : Integer;
                   3628:     const Line : TLine;
                   3629:     nColFrom   : Integer;
                   3630:     nColTo     : Integer);
                   3631: var
                   3632:     rc       : TRect;
                   3633:     nCnt     : Integer;
                   3634:     nAtt     : Byte;
                   3635:     X        : Integer;
                   3636:     nChr     : Integer;
                   3637:     Ch       : Char;
                   3638: begin
                   3639:     nAtt := Line.Att[nColFrom];
                   3640: 
                   3641: {    if nAtt = $0B then
                   3642:         X := 0; }
                   3643: {
                   3644:     SetBkColor(DC, PALETTEINDEX(nAtt div $0F));
                   3645:     SetTextColor(DC, PALETTEINDEX(nAtt and $0F));
                   3646: }
                   3647:     if not FMonoChrome then begin
                   3648:         with FPaletteEntries[(nAtt shr 4) and $0F] do
                   3649:             SetBkColor(DC, PALETTERGB(peRed, peGreen, peBlue));
                   3650:         with FPaletteEntries[nAtt and $0F] do begin
                   3651:             SetTextColor(DC, PALETTERGB(peRed, peGreen, peBlue));
                   3652:             Canvas.Pen.Color   := PALETTERGB(peRed, peGreen, peBlue);
                   3653:             Canvas.Brush.Color := PALETTERGB(peRed, peGreen, peBlue);
                   3654:         end;
                   3655:     end
                   3656:     else begin
                   3657:         if (nAtt div $0F) <> 0 then
                   3658:             SetBkColor(DC, RGB(127, 127, 127))
                   3659:         else
                   3660:             SetBkColor(DC, RGB(255, 255, 255));
                   3661: 
                   3662:         if (nAtt and $0F) <> 0 then
                   3663:             SetTextColor(DC, RGB(0, 0, 0))
                   3664:         else
                   3665:             SetTextColor(DC, RGB(255, 255, 255));
                   3666:     end;
                   3667: 
                   3668:     nCnt      := nColTo - nColFrom;
                   3669:     nChr      := 0;
                   3670: {$IFDEF SINGLE_CHAR_PAINT}
                   3671:     while nChr < nCnt do begin
                   3672: {$IFDEF CHAR_ZOOM}
                   3673:         X         := LeftMargin + FCharPos[nColFrom + nChr];
                   3674:         rc.Top    := Y  + FInternalLeading;
                   3675:         rc.Bottom := Y1 + FInternalLeading;
                   3676:         rc.Left   := X;
                   3677:         rc.Right  := LeftMargin + FCharPos[nColFrom + nChr + 1];
                   3678: {$ELSE}
                   3679:         X         := LeftMargin + (nColFrom + nChr) * FCharWidth;
                   3680:         rc.Top    := Y  + FInternalLeading;
                   3681:         rc.Bottom := Y1 + FInternalLeading;
                   3682:         rc.Left   := X;
                   3683:         rc.Right  := rc.Left + FCharWidth;
                   3684: {$ENDIF}
                   3685:         if (nColFrom + nChr) = 0 then
                   3686:            rc.Left := rc.Left - LeftMargin;
                   3687:         if (nColFrom + nChr) >= FScreen.FColCount then
                   3688:            rc.Right := rc.Right + RightMargin;
                   3689:         Ch := Line.Txt[nColFrom + nChr];
                   3690:         if FGraphicDraw and
                   3691:            (FScreen.FXlatOutputTable = @ibm_iso8859_1_G0) and
                   3692:            (Ch >= #$B0) and (Ch <= #$DF) and
                   3693:            (Ch in [#$B3, #$C4, #$DA, #$C0, #$C1, #$C2, #$C3, #$B4, #$BF, #$D9,
                   3694:                    #$DB, #$DC, #$DD, #$DE, #$DF,
                   3695:                    #$BA, #$CD, #$C9, #$C8, #$BB, #$BC,
                   3696:                    #$CC, #$B9, #$C7, #$B6, #$D2, #$D0,
                   3697:                    #$D5, #$D4, #$B8, #$BE,
                   3698:                    #$C6, #$D1, #$B5, #$CF,
                   3699:                    #$D6, #$B7, #$D3, #$BD,
                   3700:                    #$C5, #$CE, #$D8, #$D7, #$CA, #$CB,
                   3701:                    #$B0, #$B1, #$B2]) then
                   3702:             PaintGraphicChar(DC, X, Y, @rc, Ch)
                   3703:         else
                   3704:             ExtTextOut(DC, X, Y, ETO_OPAQUE or ETO_CLIPPED, @rc, @Ch, 1, nil);
                   3705:         Inc(nChr);
                   3706:     end;
                   3707: {$ELSE}
                   3708: {$IFDEF CHAR_ZOOM}
                   3709:     X         := LeftMargin + FCharPos[nColFrom];
                   3710:     rc.Top    := Y  + FInternalLeading;
                   3711:     rc.Bottom := Y1 + FInternalLeading;
                   3712:     rc.Left   := X;
                   3713:     rc.Right  := LeftMargin + FCharPos[nColFrom + nCnt];
                   3714: {$ELSE}
                   3715:     X         := LeftMargin + nColFrom * FCharWidth;
                   3716:     rc.Top    := Y  + FInternalLeading;
                   3717:     rc.Bottom := Y1 + FInternalLeading;
                   3718:     rc.Left   := X;
                   3719:     rc.Right  := rc.Left + nCnt * FCharWidth;
                   3720: {$ENDIF}
                   3721:     if nColFrom = 0 then
                   3722:        rc.Left := rc.Left - LeftMargin;
                   3723:     if nColTo >= FScreen.FColCount then
                   3724:        rc.Right := rc.Right + RightMargin;
                   3725:     ExtTextOut(DC,
                   3726:                X, Y,
                   3727:                ETO_OPAQUE or ETO_CLIPPED, @rc,
                   3728:                @Line.Txt[nColFrom], nCnt, nil);
                   3729: {$ENDIF}
                   3730: end;
                   3731: 
                   3732: 
                   3733: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3734: procedure TCustomEmulVT.WMPaint(var Message: TWMPaint);
                   3735: var
                   3736:     DC        : HDC;
                   3737:     PS        : TPaintStruct;
                   3738:     Y, Y1     : Integer;
                   3739:     rc        : TRect;
                   3740:     OldPen    : THandle;
                   3741:     OldBrush  : THandle;
                   3742:     OldFont   : THandle;
                   3743:     rcPaint   : TRect;
                   3744:     DrawRct   : TRect;
                   3745:     nRow      : Integer;
                   3746:     nCol      : Integer;
                   3747:     nColFrom  : Integer;
                   3748:     Line      : TLine;
                   3749:     BackBrush : HBrush;
                   3750: begin
                   3751:     { This may be a bit of overkill but we have to keep the scrollbar tracking
                   3752:       with the number of lines visible on the screen.  The calling program can
                   3753:       change the Height of the screen and we don't have a good way to know that.
                   3754:       This routine will get called whenever the screen gets updated so it is a
                   3755:       good time to update the scrollbar. }
                   3756:     AdjustScrollBar;
                   3757: 
                   3758:     if not GetUpdateRect(WindowHandle, rc, FALSE) then
                   3759:         Exit;
                   3760: 
                   3761:     BackBrush := 0;
                   3762:     OldBrush  := 0;
                   3763: 
                   3764:     DC := Message.DC;
                   3765:     if DC = 0 then
                   3766:         DC := BeginPaint(WindowHandle, PS);
                   3767:     try
                   3768:         if not FMonoChrome then begin
                   3769:             SelectPalette(DC, FPal, FALSE);
                   3770:             RealizePalette(DC);
                   3771:             with FPaletteEntries[FScreen.FAttribute div $0F] do
                   3772:                 BackBrush := CreateSolidBrush(PALETTERGB(peRed, peGreen, peBlue));
                   3773:             OldBrush := SelectObject(DC, BackBrush);
                   3774:         end;
                   3775: 
                   3776:         WinProcs.GetClientRect(WindowHandle, DrawRct);
                   3777:         rcPaint  := PS.rcPaint;
                   3778:         rc.Left  := 2;
                   3779:         rc.Right := DrawRct.Right - 2;
                   3780:         nRow     := PixelToRow(rcPaint.top);
                   3781:         nRow := nRow - 1;
                   3782:         if nRow < 0 then
                   3783:             nRow := 0;
                   3784: 
                   3785: {$IFDEF CHAR_ZOOM}
                   3786:         Y  := TopMargin + FLinePos[nRow];
                   3787:         Y1 := TopMargin + FLinePos[nRow + 1];
                   3788: {$ELSE}
                   3789:         Y  := TopMargin + nRow * FLineHeight;
                   3790:         Y1 := Y + FLineHeight;
                   3791: {$ENDIF}
                   3792: 
                   3793:         if rcPaint.Top <= TopMargin then begin
                   3794:             OldPen := SelectObject(DC, GetStockObject(NULL_PEN));
                   3795:             WinProcs.Rectangle(DC, rcPaint.left, rcPaint.Top,
                   3796:                                rcPaint.Right + 1,
                   3797:                                TopMargin + FInternalLeading + 1);
                   3798:             SelectObject(DC, OldPen);
                   3799:         end;
                   3800: 
                   3801:         if (nRow = 0) and (FInternalLeading > 0) then begin
                   3802:             OldPen := SelectObject(DC, GetStockObject(NULL_PEN));
                   3803:             WinProcs.Rectangle(DC, rcPaint.left, rcPaint.Top,
                   3804:                                rcPaint.Right + 1,
                   3805:                                Y + FInternalLeading + 1);
                   3806:             SelectObject(DC, OldPen);
                   3807:         end;
                   3808: 
                   3809:         OldFont := SelectObject(DC, FFont.Handle);
                   3810:         nRow    := nRow + FTopLine;
                   3811:         while nRow < FScreen.FRowCount do begin
                   3812:             rc.Top    := Y;
                   3813:             rc.Bottom := Y + FLineHeight;
                   3814:             if rc.Bottom > (DrawRct.Bottom - BottomMargin) then begin
                   3815:                 OldPen := SelectObject(DC, GetStockObject(NULL_PEN));
                   3816:                 WinProcs.Rectangle(DC, rc.Left - 2, rc.Top, rc.Right + 1,
                   3817:                                    DrawRct.Bottom - 1);
                   3818:                 SelectObject(DC, OldPen);
                   3819:                 Break;
                   3820:             end;
                   3821:             Line := FScreen.Lines[nRow];
                   3822: 
                   3823:             nCol     := 0;
                   3824:             nColFrom := 0;
                   3825:             while nCol < FScreen.FColCount do begin
                   3826:                 while (nCol < FScreen.FColCount) and
                   3827:                       (Line.Att[nCol] = Line.Att[nColFrom]) do
                   3828:                     Inc(nCol);
                   3829: 
                   3830:                 PaintOneLine(DC, Y, Y1, Line, nColFrom, nCol);
                   3831:                 nColFrom := nCol;
                   3832:             end;
                   3833: 
                   3834:             nRow := nRow + 1;
                   3835: {$IFDEF CHAR_ZOOM}
                   3836:             Y    := TopMargin + FLinePos[nRow - FTopLine];
                   3837:             Y1   := TopMargin + FLinePos[nRow + 1 - FTopLine];
                   3838: {$ELSE}
                   3839:             Y    := Y + FLineHeight;
                   3840:             Y1   := Y + FLineHeight;
                   3841: {$ENDIF}
                   3842:             if Y > rcPaint.Bottom then
                   3843:                 Break;
                   3844:         end;
                   3845: 
                   3846:         { Fill region between last text line and bottom of the window }
                   3847:         OldPen := SelectObject(DC, GetStockObject(NULL_PEN));
                   3848:         if (FScreen.FRowCount - FTopLine) <= MAX_ROW then { WM + SE 09/08/00 }
                   3849:            WinProcs.Rectangle(DC, rc.Left - 2,
                   3850:                               TopMargin + FLinePos[FScreen.FRowCount - FTopLine] + 1,
                   3851:                               rc.Right + 1, DrawRct.Bottom + 1);
                   3852:         SelectObject(DC, OldPen);
                   3853: 
                   3854: {$IFDEF CHAR_ZOOM}
                   3855:         if (LeftMargin + FCharPos[FScreen.FColCount]) < rc.Right then begin
                   3856:             OldPen := SelectObject(DC, GetStockObject(NULL_PEN));
                   3857:             WinProcs.Rectangle(DC, LeftMargin + FCharPos[FScreen.FColCount],
                   3858:                                TopMargin,   { 09/03/99 }
                   3859:                                rcPaint.Right + 1, DrawRct.Bottom + 1);
                   3860:             SelectObject(DC, OldPen);
                   3861:         end;
                   3862: {$ELSE}
                   3863:         if (LeftMargin + FScreen.FColCount * FCharWidth) < rc.Right then begin
                   3864:             OldPen := SelectObject(DC, GetStockObject(NULL_PEN));
                   3865:             WinProcs.Rectangle(DC, LeftMargin + FScreen.FColCount * FCharWidth,
                   3866:                                TopMargin, rc.Right + 1, DrawRct.Bottom - 1);
                   3867:             SelectObject(DC, OldPen);
                   3868:         end;
                   3869: {$ENDIF}
                   3870: 
                   3871:         if FSelectRect.Top <> -1 then begin
                   3872:             SelectObject(DC, GetStockObject(NULL_BRUSH));
                   3873:             SelectObject(DC, GetStockObject(BLACK_PEN));
                   3874:             WinProcs.Rectangle(DC, FSelectRect.Left,
                   3875:                                    FSelectRect.Top,
                   3876:                                    FSelectRect.Right + 1,
                   3877:                                    FSelectRect.Bottom - 1);
                   3878:             SelectObject(DC, GetStockObject(WHITE_PEN));
                   3879:             WinProcs.Rectangle(DC, FSelectRect.Left - 1,
                   3880:                                    FSelectRect.Top - 1,
                   3881:                                    FSelectRect.Right + 2,
                   3882:                                    FSelectRect.Bottom);
                   3883:         end;
                   3884: 
                   3885:         SelectObject(DC, OldFont);
                   3886:         if OldBrush <> 0 then
                   3887:             SelectObject(DC, OldBrush);
                   3888:         if BackBrush <> 0 then
                   3889:             DeleteObject(BackBrush);
                   3890:     finally
                   3891:         if Message.DC = 0 then
                   3892:             EndPaint(WindowHandle, PS);
                   3893:     end;
                   3894: end;
                   3895: 
                   3896: 
                   3897: {* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
                   3898: 
                   3899: end.
                   3900: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.