|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.