Parcourir la source

+ Initial import

michael il y a 25 ans
Parent
commit
aad6d9f198
77 fichiers modifiés avec 20119 ajouts et 63 suppressions
  1. 1299 0
      fv/app.pas
  2. 3214 0
      fv/dialogs.pas
  3. 2624 0
      fv/drivers.pas
  4. 623 0
      fv/fileio.pas
  5. 225 0
      fv/gadgets.pas
  6. 302 0
      fv/gfvgraph.pas
  7. 379 0
      fv/histlist.pas
  8. 826 0
      fv/memory.pas
  9. 1667 0
      fv/menus.pas
  10. 262 0
      fv/msgbox.pas
  11. 342 0
      fv/platform.inc
  12. 422 0
      fv/time.pas
  13. 1056 0
      fv/validate.pas
  14. 6626 0
      fv/views.pas
  15. 4 1
      ide/fake/compiler/browcol.pas
  16. 4 1
      ide/fake/compiler/comphook.pas
  17. 4 1
      ide/fake/compiler/compiler.pas
  18. 4 1
      ide/fake/compiler/globtype.pas
  19. 4 1
      ide/fake/compiler/systems.pas
  20. 4 1
      ide/fake/compiler/tokens.pas
  21. 4 1
      ide/fake/compiler/version.pas
  22. 4 1
      ide/fake/gdb/gdbcon.pas
  23. 4 1
      ide/fake/gdb/gdbint.pas
  24. 4 1
      ide/text/fp.pas
  25. 4 1
      ide/text/fpcalc.pas
  26. 4 1
      ide/text/fpcatch.pas
  27. 4 1
      ide/text/fpcompil.pas
  28. 4 1
      ide/text/fpconst.pas
  29. 4 1
      ide/text/fpdebug.pas
  30. 4 1
      ide/text/fpdesk.pas
  31. 4 1
      ide/text/fphelp.pas
  32. 4 1
      ide/text/fpide.pas
  33. 4 1
      ide/text/fpini.pas
  34. 4 1
      ide/text/fpintf.pas
  35. 4 1
      ide/text/fpmcomp.inc
  36. 4 1
      ide/text/fpmdebug.inc
  37. 4 1
      ide/text/fpmedit.inc
  38. 4 1
      ide/text/fpmfile.inc
  39. 4 1
      ide/text/fpmhelp.inc
  40. 4 1
      ide/text/fpmopts.inc
  41. 4 1
      ide/text/fpmrun.inc
  42. 4 1
      ide/text/fpmsrch.inc
  43. 4 1
      ide/text/fpmtools.inc
  44. 4 1
      ide/text/fpmwnd.inc
  45. 4 1
      ide/text/fpredir.pas
  46. 4 1
      ide/text/fpstre.inc
  47. 4 1
      ide/text/fpstrh.inc
  48. 4 1
      ide/text/fpstring.pas
  49. 4 1
      ide/text/fpswitch.pas
  50. 4 1
      ide/text/fpsymbol.pas
  51. 4 1
      ide/text/fptemplt.pas
  52. 4 1
      ide/text/fptools.pas
  53. 4 1
      ide/text/fpusrscr.pas
  54. 4 1
      ide/text/fputils.pas
  55. 4 1
      ide/text/fpvars.pas
  56. 4 1
      ide/text/fpviews.pas
  57. 4 1
      ide/text/gplprog.pt
  58. 4 1
      ide/text/gplunit.pt
  59. 4 1
      ide/text/pmode.pas
  60. 4 1
      ide/text/vesa.pas
  61. 4 1
      ide/text/wconsts.pas
  62. 4 1
      ide/text/wconstse.inc
  63. 4 1
      ide/text/wconstsh.inc
  64. 4 1
      ide/text/weditor.pas
  65. 4 1
      ide/text/whelp.pas
  66. 4 1
      ide/text/whlpview.pas
  67. 4 1
      ide/text/whtml.pas
  68. 4 1
      ide/text/whtmlhlp.pas
  69. 4 1
      ide/text/whtmlscn.pas
  70. 4 1
      ide/text/winclip.pas
  71. 4 1
      ide/text/wini.pas
  72. 4 1
      ide/text/wnghelp.pas
  73. 4 1
      ide/text/wresourc.pas
  74. 4 1
      ide/text/wtphwrit.pas
  75. 4 1
      ide/text/wutils.pas
  76. 4 1
      ide/text/wviews.pas
  77. 4 1
      ide/text/wwinhelp.pas

+ 1299 - 0
fv/app.pas

@@ -0,0 +1,1299 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{   System independent GRAPHICAL clone of APP.PAS          }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail addr           }
+{   [email protected] - backup e-mail addr            }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     12 Dec 96   First multi platform release       }
+{  1.10     12 Sep 97   FPK pascal 0.92 conversion added.  }
+{  1.20     29 Aug 97   Platform.inc sort added.           }
+{  1.30     05 May 98   Virtual pascal 2.0 code added.     }
+{  1.40     22 Oct 99   Object registration added.         }
+{  1.50     22 Oct 99   Complete recheck preformed         }
+{  1.51     03 Nov 99   FPC Windows support added          }
+{  1.60     26 Nov 99   Graphics stuff moved to GFVGraph   }
+{**********************************************************}
+
+UNIT App;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F-} { Near calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     {$IFNDEF PPC_SPEED}                              { NON SPEED COMPILER }
+       {$IFDEF PPC_FPC}                               { FPC WINDOWS COMPILER }
+       Windows,                                       { Standard units }
+       {$ELSE}                                        { OTHER COMPILERS }
+       WinTypes,WinProcs,                             { Standard units }
+       {$ENDIF}
+       {$IFNDEF PPC_DELPHI}                           { NON DELPHI1 COMPILER }
+         {$IFDEF BIT_16} Win31, {$ENDIF}              { 16 BIT WIN 3.1 UNIT }
+       {$ENDIF}
+     {$ELSE}                                          { SPEEDSOFT COMPILER }
+       WinBase, WinDef,                               { Standard units }
+     {$ENDIF}
+     {$IFDEF PPC_DELPHI}                              { DELPHI COMPILERS }
+       Messages,                                      { Standard unit }
+     {$ENDIF}
+   {$ENDIF}
+
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+     Os2Def, Os2Base, OS2PmApi,                       { Standard units }
+   {$ENDIF}
+
+   Common, Memory, GFVGraph,                          { GFV standard units }
+   Objects, Drivers, Views, Menus, HistList, Dialogs; { GFV standard units }
+
+{***************************************************************************}
+{                              PUBLIC CONSTANTS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                  STANDARD APPLICATION COMMAND CONSTANTS                   }
+{---------------------------------------------------------------------------}
+CONST
+   cmNew       = 30;                                  { Open new file }
+   cmOpen      = 31;                                  { Open a file }
+   cmSave      = 32;                                  { Save current }
+   cmSaveAs    = 33;                                  { Save current as }
+   cmSaveAll   = 34;                                  { Save all files }
+   cmChangeDir = 35;                                  { Change directories }
+   cmDosShell  = 36;                                  { Dos shell }
+   cmCloseAll  = 37;                                  { Close all windows }
+
+{---------------------------------------------------------------------------}
+{                       TApplication PALETTE ENTRIES                        }
+{---------------------------------------------------------------------------}
+CONST
+   apColor      = 0;                                  { Coloured app }
+   apBlackWhite = 1;                                  { B&W application }
+   apMonochrome = 2;                                  { Monochrome app }
+
+{---------------------------------------------------------------------------}
+{                           TBackGround PALETTES                            }
+{---------------------------------------------------------------------------}
+CONST
+   CBackground = #1;                                  { Background colour }
+
+{---------------------------------------------------------------------------}
+{                           TApplication PALETTES                           }
+{---------------------------------------------------------------------------}
+CONST
+  { Turbo Vision 1.0 Color Palettes }
+   CColor =
+         #$81#$70#$78#$74#$20#$28#$24#$17#$1F#$1A#$31#$31#$1E#$71#$1F +
+     #$37#$3F#$3A#$13#$13#$3E#$21#$3F#$70#$7F#$7A#$13#$13#$70#$7F#$7E +
+     #$70#$7F#$7A#$13#$13#$70#$70#$7F#$7E#$20#$2B#$2F#$78#$2E#$70#$30 +
+     #$3F#$3E#$1F#$2F#$1A#$20#$72#$31#$31#$30#$2F#$3E#$31#$13#$38#$00;
+
+   CBlackWhite =
+         #$70#$70#$78#$7F#$07#$07#$0F#$07#$0F#$07#$70#$70#$07#$70#$0F +
+     #$07#$0F#$07#$70#$70#$07#$70#$0F#$70#$7F#$7F#$70#$07#$70#$07#$0F +
+     #$70#$7F#$7F#$70#$07#$70#$70#$7F#$7F#$07#$0F#$0F#$78#$0F#$78#$07 +
+     #$0F#$0F#$0F#$70#$0F#$07#$70#$70#$70#$07#$70#$0F#$07#$07#$78#$00;
+
+   CMonochrome =
+         #$70#$07#$07#$0F#$70#$70#$70#$07#$0F#$07#$70#$70#$07#$70#$00 +
+     #$07#$0F#$07#$70#$70#$07#$70#$00#$70#$70#$70#$07#$07#$70#$07#$00 +
+     #$70#$70#$70#$07#$07#$70#$70#$70#$0F#$07#$07#$0F#$70#$0F#$70#$07 +
+     #$0F#$0F#$07#$70#$07#$07#$70#$07#$07#$07#$70#$0F#$07#$07#$70#$00;
+
+   { Turbo Vision 2.0 Color Palettes }
+
+   CAppColor =
+         #$81#$70#$78#$74#$20#$28#$24#$17#$1F#$1A#$31#$31#$1E#$71#$1F +
+     #$37#$3F#$3A#$13#$13#$3E#$21#$3F#$70#$7F#$7A#$13#$13#$70#$7F#$7E +
+     #$70#$7F#$7A#$13#$13#$70#$70#$7F#$7E#$20#$2B#$2F#$78#$2E#$70#$30 +
+     #$3F#$3E#$1F#$2F#$1A#$20#$72#$31#$31#$30#$2F#$3E#$31#$13#$38#$00 +
+     #$17#$1F#$1A#$71#$71#$1E#$17#$1F#$1E#$20#$2B#$2F#$78#$2E#$10#$30 +
+     #$3F#$3E#$70#$2F#$7A#$20#$12#$31#$31#$30#$2F#$3E#$31#$13#$38#$00 +
+     #$37#$3F#$3A#$13#$13#$3E#$30#$3F#$3E#$20#$2B#$2F#$78#$2E#$30#$70 +
+     #$7F#$7E#$1F#$2F#$1A#$20#$32#$31#$71#$70#$2F#$7E#$71#$13#$38#$00;
+
+   CAppBlackWhite =
+         #$70#$70#$78#$7F#$07#$07#$0F#$07#$0F#$07#$70#$70#$07#$70#$0F +
+     #$07#$0F#$07#$70#$70#$07#$70#$0F#$70#$7F#$7F#$70#$07#$70#$07#$0F +
+     #$70#$7F#$7F#$70#$07#$70#$70#$7F#$7F#$07#$0F#$0F#$78#$0F#$78#$07 +
+     #$0F#$0F#$0F#$70#$0F#$07#$70#$70#$70#$07#$70#$0F#$07#$07#$78#$00 +
+     #$07#$0F#$0F#$07#$70#$07#$07#$0F#$0F#$70#$78#$7F#$08#$7F#$08#$70 +
+     #$7F#$7F#$7F#$0F#$70#$70#$07#$70#$70#$70#$07#$7F#$70#$07#$78#$00 +
+     #$70#$7F#$7F#$70#$07#$70#$70#$7F#$7F#$07#$0F#$0F#$78#$0F#$78#$07 +
+     #$0F#$0F#$0F#$70#$0F#$07#$70#$70#$70#$07#$70#$0F#$07#$07#$78#$00;
+
+   CAppMonochrome =
+         #$70#$07#$07#$0F#$70#$70#$70#$07#$0F#$07#$70#$70#$07#$70#$00 +
+     #$07#$0F#$07#$70#$70#$07#$70#$00#$70#$70#$70#$07#$07#$70#$07#$00 +
+     #$70#$70#$70#$07#$07#$70#$70#$70#$0F#$07#$07#$0F#$70#$0F#$70#$07 +
+     #$0F#$0F#$07#$70#$07#$07#$70#$07#$07#$07#$70#$0F#$07#$07#$70#$00 +
+     #$70#$70#$70#$07#$07#$70#$70#$70#$0F#$07#$07#$0F#$70#$0F#$70#$07 +
+     #$0F#$0F#$07#$70#$07#$07#$70#$07#$07#$07#$70#$0F#$07#$07#$70#$00 +
+     #$70#$70#$70#$07#$07#$70#$70#$70#$0F#$07#$07#$0F#$70#$0F#$70#$07 +
+     #$0F#$0F#$07#$70#$07#$07#$70#$07#$07#$07#$70#$0F#$07#$07#$70#$00;
+
+{---------------------------------------------------------------------------}
+{                     STANDRARD HELP CONTEXT CONSTANTS                      }
+{---------------------------------------------------------------------------}
+CONST
+{ Note: range $FF00 - $FFFF of help contexts are reserved by Borland }
+   hcNew       = $FF01;                               { New file help }
+   hcOpen      = $FF02;                               { Open file help }
+   hcSave      = $FF03;                               { Save file help }
+   hcSaveAs    = $FF04;                               { Save file as help }
+   hcSaveAll   = $FF05;                               { Save all files help }
+   hcChangeDir = $FF06;                               { Change dir help }
+   hcDosShell  = $FF07;                               { Dos shell help }
+   hcExit      = $FF08;                               { Exit program help }
+
+   hcUndo      = $FF10;                               { Clipboard undo help }
+   hcCut       = $FF11;                               { Clipboard cut help }
+   hcCopy      = $FF12;                               { Clipboard copy help }
+   hcPaste     = $FF13;                               { Clipboard paste help }
+   hcClear     = $FF14;                               { Clipboard clear help }
+
+   hcTile      = $FF20;                               { Desktop tile help }
+   hcCascade   = $FF21;                               { Desktop cascade help }
+   hcCloseAll  = $FF22;                               { Desktop close all }
+   hcResize    = $FF23;                               { Window resize help }
+   hcZoom      = $FF24;                               { Window zoom help }
+   hcNext      = $FF25;                               { Window next help }
+   hcPrev      = $FF26;                               { Window previous help }
+   hcClose     = $FF27;                               { Window close help }
+
+{***************************************************************************}
+{                        PUBLIC OBJECT DEFINITIONS                          }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                  TBackGround OBJECT - BACKGROUND OBJECT                   }
+{---------------------------------------------------------------------------}
+TYPE
+   TBackGround = OBJECT (TView)
+         Pattern: Char;                               { Background pattern }
+      CONSTRUCTOR Init (Var Bounds: TRect; APattern: Char);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION GetPalette: PPalette; Virtual;
+      PROCEDURE DrawBackGround; Virtual;
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PBackGround = ^TBackGround;
+
+{---------------------------------------------------------------------------}
+{                     TDeskTop OBJECT - DESKTOP OBJECT                      }
+{---------------------------------------------------------------------------}
+TYPE
+   TDeskTop = OBJECT (TGroup)
+         Background      : PBackground;               { Background view }
+         TileColumnsFirst: Boolean;                   { Tile direction }
+      CONSTRUCTOR Init (Var Bounds: TRect);
+      CONSTRUCTOR Load (Var S: TStream);
+      PROCEDURE TileError; Virtual;
+      PROCEDURE InitBackGround; Virtual;
+      PROCEDURE Tile (Var R: TRect);
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE Cascade (Var R: TRect);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+   END;
+   PDeskTop = ^TDeskTop;
+
+{---------------------------------------------------------------------------}
+{                  TProgram OBJECT - PROGRAM ANCESTOR OBJECT                }
+{---------------------------------------------------------------------------}
+TYPE
+   TProgram = OBJECT (TGroup)
+      CONSTRUCTOR Init;
+      DESTRUCTOR Done; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION CanMoveFocus: Boolean;
+      FUNCTION ValidView (P: PView): PView;
+      FUNCTION InsertWindow (P: PWindow): PWindow;
+      FUNCTION ExecuteDialog (P: PDialog; Data: Pointer): Word;
+      PROCEDURE Run; Virtual;
+      PROCEDURE Idle; Virtual;
+      PROCEDURE InitScreen; Virtual;
+      PROCEDURE InitDeskTop; Virtual;
+      PROCEDURE OutOfMemory; Virtual;
+      PROCEDURE InitMenuBar; Virtual;
+      PROCEDURE InitStatusLine; Virtual;
+      PROCEDURE SetScreenMode (Mode: Word);
+      PROCEDURE PutEvent (Var Event: TEvent); Virtual;
+      PROCEDURE GetEvent (Var Event: TEvent); Virtual;
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      {$IFNDEF OS_DOS}                                { WIN/NT/OS2 CODE }
+      FUNCTION GetClassName: String; Virtual;
+      FUNCTION GetClassText: String; Virtual;
+      FUNCTION GetClassAttr: LongInt; Virtual;
+      FUNCTION GetMsgHandler: Pointer; Virtual;
+      {$ENDIF}
+   END;
+   PProgram = ^TProgram;
+
+{---------------------------------------------------------------------------}
+{                  TApplication OBJECT - APPLICATION OBJECT                 }
+{---------------------------------------------------------------------------}
+TYPE
+   TApplication = OBJECT (TProgram)
+      CONSTRUCTOR Init;
+      DESTRUCTOR Done; Virtual;
+      PROCEDURE Tile;
+      PROCEDURE Cascade;
+      PROCEDURE DosShell;
+      PROCEDURE GetTileRect (Var R: TRect); Virtual;
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+   END;
+   PApplication = ^TApplication;                      { Application ptr }
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                STANDARD MENU AND STATUS LINES ROUTINES                    }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-StdStatusKeys------------------------------------------------------
+Returns a pointer to a linked list of commonly used status line keys.
+The default status line for TApplication uses StdStatusKeys as its
+complete list of status keys.
+22Oct99 LdB
+---------------------------------------------------------------------}
+FUNCTION StdStatusKeys (Next: PStatusItem): PStatusItem;
+
+{-StdFileMenuItems---------------------------------------------------
+Returns a pointer to a list of menu items for a standard File menu.
+The standard File menu items are New, Open, Save, Save As, Save All,
+Change Dir, OS Shell, and Exit.
+22Oct99 LdB
+---------------------------------------------------------------------}
+FUNCTION StdFileMenuItems (Next: PMenuItem): PMenuItem;
+
+{-StdEditMenuItems---------------------------------------------------
+Returns a pointer to a list of menu items for a standard Edit menu.
+The standard Edit menu items are Undo, Cut, Copy, Paste, and Clear.
+22Oct99 LdB
+---------------------------------------------------------------------}
+FUNCTION StdEditMenuItems (Next: PMenuItem): PMenuItem;
+
+{-StdWindowMenuItems-------------------------------------------------
+Returns a pointer to a list of menu items for a standard Window menu.
+The standard Window menu items are Tile, Cascade, Close All,
+Size/Move, Zoom, Next, Previous, and Close.
+22Oct99 LdB
+---------------------------------------------------------------------}
+FUNCTION StdWindowMenuItems (Next: PMenuItem): PMenuItem;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           OBJECT REGISTER ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{-RegisterApp--------------------------------------------------------
+Calls RegisterType for each of the object types defined in this unit.
+22oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE RegisterApp;
+
+{***************************************************************************}
+{                           OBJECT REGISTRATION                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                      TBackGround STREAM REGISTRATION                      }
+{---------------------------------------------------------------------------}
+CONST
+  RBackGround: TStreamRec = (
+     ObjType: 30;                                     { Register id = 30 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TBackGround)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TBackGround);
+     {$ENDIF}
+     Load:    @TBackGround.Load;                      { Object load method }
+     Store:   @TBackGround.Store                      { Object store method }
+  );
+
+{---------------------------------------------------------------------------}
+{                       TDeskTop STREAM REGISTRATION                        }
+{---------------------------------------------------------------------------}
+CONST
+  RDeskTop: TStreamRec = (
+     ObjType: 31;                                     { Register id = 31 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TDeskTop)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TDeskTop);
+     {$ENDIF}
+     Load:    @TDeskTop.Load;                         { Object load method }
+     Store:   @TDeskTop.Store                         { Object store method }
+  );
+
+{***************************************************************************}
+{                        INITIALIZED PUBLIC VARIABLES                       }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                       INITIALIZED PUBLIC VARIABLES                        }
+{---------------------------------------------------------------------------}
+CONST
+   AppPalette: Integer = apColor;                     { Application colour }
+   Desktop: PDeskTop = Nil;                           { Desktop object }
+   MenuBar: PMenuView = Nil;                          { Application menu }
+   StatusLine: PStatusLine = Nil;                     { App status line }
+   Application : PApplication = Nil;                  { Application object }
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{***************************************************************************}
+{                        PRIVATE DEFINED CONSTANTS                          }
+{***************************************************************************}
+
+{***************************************************************************}
+{                      PRIVATE INITIALIZED VARIABLES                        }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                      INITIALIZED PRIVATE VARIABLES                        }
+{---------------------------------------------------------------------------}
+CONST Pending: TEvent = (What: evNothing);            { Pending event }
+
+{***************************************************************************}
+{                        PRIVATE INTERNAL ROUTINES                          }
+{***************************************************************************}
+{$IFDEF OS_WINDOWS}
+{---------------------------------------------------------------------------}
+{  AppMsgHandler -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 13May98 LdB     }
+{---------------------------------------------------------------------------}
+FUNCTION TvAppMsgHandler (Wnd: hWnd; iMessage, wParam: Sw_Word;
+lParam: LongInt): LongInt; {$IFDEF BIT_16} EXPORT; {$ELSE} STDCALL; {$ENDIF}
+VAR Li: LongInt; Min, MAx: TPoint; Event: TEvent; P: PView; Wp: ^TWindowPos;
+    Mm: ^TMinMaxInfo;
+BEGIN
+   {$IFDEF BIT_16}                                    { 16 BIT CODE }
+   PtrRec(P).Seg := GetProp(Wnd, ViewSeg);            { Fetch seg property }
+   PtrRec(P).Ofs := GetProp(Wnd, ViewOfs);            { Fetch ofs property }
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT CODE }
+   LongInt(P) := GetProp(Wnd, ViewPtr);               { Fetch view property }
+   {$ENDIF}
+   TvAppMsgHandler := 0;                              { Preset zero return }
+   Event.What := evNothing;                           { Preset no event }
+   Case iMessage Of
+     WM_Destroy:;                                     { Destroy window }
+     WM_Close: Begin
+       Event.What := evCommand;                       { Command event }
+       Event.Command := cmQuit;                       { Quit command }
+       Event.InfoPtr := Nil;                          { Clear info ptr }
+     End;
+     WM_GetMinMaxInfo: Begin                          { Get minmax info }
+       TvAppMsgHandler := DefWindowProc(Wnd,
+         iMessage, wParam, lParam);                   { Default handler }
+       Mm := Pointer(lParam);                         { Create pointer }
+       Mm^.ptMaxSize.X := SysScreenWidth;             { Max x size }
+       Mm^.ptMaxSize.Y := SysScreenHeight;            { Max y size }
+       Mm^.ptMinTrackSize.X := MinWinSize.X *
+         SysFontWidth;                                { Drag min x size }
+       Mm^.ptMinTrackSize.Y := MinWinSize.Y *
+         SysFontHeight;                               { Drag min y size }
+       Mm^.ptMaxTrackSize.X := SysScreenWidth;        { Drag max x size }
+       Mm^.ptMaxTrackSize.Y := SysScreenHeight;       { Drag max y size }
+     End;
+     Else Begin                                       { Unhandled message }
+       TvAppMsgHandler := DefWindowProc(Wnd,
+         iMessage, wParam, lParam);                   { Default handler }
+       Exit;                                          { Now exit }
+     End;
+   End;
+   If (Event.What <> evNothing) Then                  { Check any FV event }
+     PutEventInQueue(Event);                          { Put event in queue }
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+FUNCTION TvAppMsgHandler(Wnd: HWnd; Msg: ULong; Mp1, Mp2: MParam): MResult; CDECL;
+VAR Event: TEvent; P: PView;
+BEGIN
+   Event.What := evNothing;                           { Preset no event }
+   TvAppMsgHandler := 0;                              { Preset zero return }
+   Case Msg Of
+     WM_Destroy:;                                     { Destroy window }
+     WM_Close: Begin
+       Event.What := evCommand;                       { Command event }
+       Event.Command := cmQuit;                       { Quit command }
+       Event.InfoPtr := Nil;                          { Clear info ptr }
+     End;
+     Else Begin                                       { Unhandled message }
+       TvAppMsgHandler := WinDefWindowProc(Wnd,
+         Msg, Mp1, Mp2);                              { Call std handler }
+       Exit;                                          { Now exit }
+     End;
+   End;
+   If (Event.What <> evNothing) Then                  { Check any FV event }
+     PutEventInQueue(Event);                          { Put event in queue }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  Tileable -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION Tileable (P: PView): Boolean;
+BEGIN
+   Tileable := (P^.Options AND ofTileable <> 0) AND   { View is tileable }
+     (P^.State AND sfVisible <> 0);                   { View is visible }
+END;
+
+{---------------------------------------------------------------------------}
+{  ISqr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION ISqr (X: Sw_Integer): Sw_Integer;
+VAR I: Sw_Integer;
+BEGIN
+   I := 0;                                            { Set value to zero }
+   Repeat
+     Inc(I);                                          { Inc value }
+   Until (I * I > X);                                 { Repeat till Sqr > X }
+   ISqr := I - 1;                                     { Return result }
+END;
+
+{---------------------------------------------------------------------------}
+{  MostEqualDivisors -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB }
+{---------------------------------------------------------------------------}
+PROCEDURE MostEqualDivisors (N: Integer; Var X, Y: Integer; FavorY: Boolean);
+VAR I: Integer;
+BEGIN
+   I := ISqr(N);                                      { Int square of N }
+   If ((N MOD I) <> 0) Then                           { Initial guess }
+     If ((N MOD (I+1)) = 0) Then Inc(I);              { Add one row/column }
+   If (I < (N DIV I)) Then I := N DIV I;              { In first page }
+   If FavorY Then Begin                               { Horz preferred }
+     X := N DIV I;                                    { Calc x position }
+     Y := I;                                          { Set y position  }
+   End Else Begin                                     { Vert preferred }
+     Y := N DIV I;                                    { Calc y position }
+     X := I;                                          { Set x position }
+   End;
+END;
+
+{***************************************************************************}
+{                               OBJECT METHODS                              }
+{***************************************************************************}
+
+{--TBackGround--------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TBackGround.Init (Var Bounds: TRect; APattern: Char);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   GrowMode := gfGrowHiX + gfGrowHiY;                 { Set grow modes }
+   Pattern := APattern;                               { Hold pattern }
+END;
+
+{--TBackGround--------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TBackGround.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(Pattern, SizeOf(Pattern));                  { Read pattern data }
+END;
+
+{--TBackGround--------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TBackGround.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CBackGround;                        { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CBackGround)] = CbackGround;   { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+procedure TBackground.DrawbackGround;
+var
+  B: TDrawBuffer;
+begin
+  MoveChar(B, Pattern, GetColor($01), Size.X);
+  WriteLine(0, 0, Size.X, Size.Y, B);
+end;
+
+{--TBackGround--------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TBackGround.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { TView store called }
+   S.Write(Pattern, SizeOf(Pattern));                 { Write pattern data }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TDesktop OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TDesktop-----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TDesktop.Init (Var Bounds: Objects.TRect);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   GrowMode := gfGrowHiX + gfGrowHiY;                 { Set growmode }
+   {GOptions := GOptions AND NOT goNoDrawView;}         { This group draws }
+   InitBackground;                                    { Create background }
+   If (Background <> Nil) Then Insert(Background);    { Insert background }
+END;
+
+{--TDesktop-----------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TDesktop.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   GetSubViewPtr(S, Background);                      { Load background }
+   S.Read(TileColumnsFirst, SizeOf(TileColumnsFirst));{ Read data }
+END;
+
+{--TDesktop-----------------------------------------------------------------}
+{  TileError -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TDeskTop.TileError;
+BEGIN                                                 { Abstract method }
+END;
+
+{--TDesktop-----------------------------------------------------------------}
+{  InitBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TDesktop.InitBackground;
+{$IFNDEF OS_WINDOWS} CONST Ch: Char = #176; {$ELSE} CONST Ch: Char = #167; {$ENDIF}
+VAR R: TRect;
+BEGIN                                                 { Compatability only }
+   getExtent(R);
+   BackGround := New(PbackGround, Init(R, Ch));
+END;
+
+{--TDesktop-----------------------------------------------------------------}
+{  Tile -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TDeskTop.Tile (Var R: TRect);
+VAR NumCols, NumRows, NumTileable, LeftOver, TileNum: Integer;
+
+   FUNCTION DividerLoc (Lo, Hi, Num, Pos: Integer): Integer;
+   BEGIN
+     DividerLoc := LongInt( LongInt(Hi - Lo) * Pos)
+       DIV Num + Lo;                                  { Calc position }
+   END;
+
+   PROCEDURE DoCountTileable (P: PView); FAR;
+   BEGIN
+     If Tileable(P) Then Inc(NumTileable);            { Count tileable views }
+   END;
+
+   PROCEDURE CalcTileRect (Pos: Integer; Var NR: TRect);
+   VAR X, Y, D: Integer;
+   BEGIN
+     D := (NumCols - LeftOver) * NumRows;             { Calc d value }
+     If (Pos<D) Then Begin
+       X := Pos DIV NumRows; Y := Pos MOD NumRows;    { Calc positions }
+     End Else Begin
+       X := (Pos - D) div (NumRows + 1) +
+         (NumCols - LeftOver);                        { Calc x position }
+       Y := (Pos - D) mod (NumRows + 1);              { Calc y position }
+     End;
+     NR.A.X := DividerLoc(R.A.X, R.B.X, NumCols, X);  { Top left x position }
+     NR.B.X := DividerLoc(R.A.X, R.B.X, NumCols, X+1);{ Right x position }
+     If (Pos >= D) Then Begin
+       NR.A.Y := DividerLoc(R.A.Y, R.B.Y,NumRows+1,Y);{ Top y position }
+       NR.B.Y := DividerLoc(R.A.Y, R.B.Y, NumRows+1,
+        Y+1);                                         { Bottom y position }
+     End Else Begin
+       NR.A.Y := DividerLoc(R.A.Y, R.B.Y,NumRows,Y);  { Top y position }
+       NR.B.Y := DividerLoc(R.A.Y, R.B.Y, NumRows,
+        Y+1);                                         { Bottom y position }
+     End;
+   END;
+
+   PROCEDURE DoTile(P: PView); FAR;
+   VAR PState: Word; R: TRect;
+   BEGIN
+     If Tileable(P) Then Begin
+       CalcTileRect(TileNum, R);                      { Calc tileable area }
+       PState := P^.State;                            { Hold view state }
+       P^.State := P^.State AND NOT sfVisible;        { Temp not visible }
+       P^.Locate(R);                                  { Locate view }
+       P^.State := PState;                            { Restore view state }
+       Dec(TileNum);                                  { One less to tile }
+     End;
+   END;
+
+BEGIN
+   NumTileable := 0;                                  { Zero tileable count }
+   ForEach(@DoCountTileable);                         { Count tileable views }
+   If (NumTileable>0) Then Begin
+     MostEqualDivisors(NumTileable, NumCols, NumRows,
+     NOT TileColumnsFirst);                           { Do pre calcs }
+     If ((R.B.X - R.A.X) DIV NumCols = 0) OR
+     ((R.B.Y - R.A.Y) DIV NumRows = 0) Then TileError { Can't tile }
+     Else Begin
+       LeftOver := NumTileable MOD NumCols;           { Left over count }
+       TileNum := NumTileable-1;                      { Tileable views }
+       ForEach(@DoTile);                              { Tile each view }
+       DrawView;                                      { Now redraw }
+     End;
+   End;
+END;
+
+{--TDesktop-----------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TDesktop.Store (Var S: TStream);
+BEGIN
+   TGroup.Store(S);                                   { Call group store }
+   PutSubViewPtr(S, Background);                      { Store background }
+   S.Write(TileColumnsFirst,SizeOf(TileColumnsFirst));{ Write data }
+END;
+
+{--TDesktop-----------------------------------------------------------------}
+{  Cascade -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TDeskTop.Cascade (Var R: TRect);
+VAR CascadeNum: Integer; LastView: PView; Min, Max: TPoint;
+
+   PROCEDURE DoCount (P: PView); FAR;
+   BEGIN
+     If Tileable(P) Then Begin
+       Inc(CascadeNum); LastView := P;                { Count cascadable }
+     End;
+   END;
+
+   PROCEDURE DoCascade (P: PView); FAR;
+   VAR PState: Word; NR: TRect;
+   BEGIN
+     If Tileable(P) AND (CascadeNum >= 0) Then Begin  { View cascadable }
+       NR.Copy(R);                                    { Copy rect area }
+       Inc(NR.A.X, CascadeNum);                       { Inc x position }
+       Inc(NR.A.Y, CascadeNum);                       { Inc y position }
+       PState := P^.State;                            { Hold view state }
+       P^.State := P^.State AND NOT sfVisible;        { Temp stop draw }
+       P^.Locate(NR);                                 { Locate the view }
+       P^.State := PState;                            { Now allow draws }
+       Dec(CascadeNum);                               { Dec count }
+     End;
+   END;
+
+BEGIN
+   CascadeNum := 0;                                   { Zero cascade count }
+   ForEach(@DoCount);                                 { Count cascadable }
+   If (CascadeNum>0) Then Begin
+     LastView^.SizeLimits(Min, Max);                  { Check size limits }
+     If (Min.X > R.B.X - R.A.X - CascadeNum) OR
+     (Min.Y > R.B.Y - R.A.Y - CascadeNum) Then
+     TileError Else Begin                             { Check for error }
+       Dec(CascadeNum);                               { One less view }
+       ForEach(@DoCascade);                           { Cascade view }
+       DrawView;                                      { Redraw now }
+     End;
+   End;
+END;
+
+{--TDesktop-----------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TDesktop.HandleEvent (Var Event: TEvent);
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   If (Event.What = evCommand) Then Begin
+     Case Event.Command of                            { Command event }
+       cmNext: FocusNext(False);                      { Focus next view }
+       cmPrev: If (BackGround <> Nil) Then Begin
+         If Valid(cmReleasedFocus) Then
+          Current^.PutInFrontOf(Background);          { Focus last view }
+       End Else FocusNext(True);                      { Focus prior view }
+       Else Exit;
+     End;
+     ClearEvent(Event);                               { Clear the event }
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TProgram OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+CONST TvProgramClassName = 'TVPROGRAM'+#0;            { TV program class }
+
+{--TProgram-----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TProgram.Init;
+VAR I: Integer; R: TRect; {$IFDEF OS_WINDOWS} ODc: HDc; {$ENDIF}
+BEGIN
+   Application := @Self;                              { Set application ptr }
+   InitScreen;                                        { Initialize screen }
+  { R.Assign(0, 0, ScreenWidth, ScreenHeight); }        { Full screen area }
+   R.A.X := 0;
+   R.A.Y := 0;
+   R.B.X := -(SysScreenWidth);
+   R.B.Y := -(SysScreenHeight);
+   Inherited Init(R);                                 { Call ancestor }
+   State := sfVisible + sfSelected + sfFocused +
+      sfModal + sfExposed;                            { Deafult states }
+   Options := 0;                                      { No options set }
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   ODc := GetDc(GetDeskTopWindow);                    { Get desktop context }
+   For I := 0 To 15 Do Begin
+     ColBrush[I] := CreateSolidBrush(GetNearestColor(
+       ODc, ColRef[I]));                              { Create brushes }
+     ColPen[I] := CreatePen(ps_Solid, 1,
+       GetNearestColor(ODc, ColRef[I]));              { Create pens }
+   End;
+   ReleaseDC(GetDeskTopWindow, ODc);                  { Release context }
+   CreateWindowNow(sw_ShowNormal);                    { Create app window }
+   {$ENDIF}
+   {$IFDEF OS_OS2}
+   CreateWindowNow(swp_Show);                         { Create app window }
+   {$ENDIF}
+   {$IFNDEF OS_DOS}                                   { WIN/NT/OS2 CODE }
+   AppWindow := HWindow;
+   Size.X := ScreenWidth;
+   Size.Y := ScreenHeight;
+   RawSize.X := ScreenWidth * SysFontWidth;
+   RawSize.Y := ScreenHeight * SysFontHeight - 1;
+   {$ENDIF}
+   InitStatusLine;                                    { Init status line }
+   If (StatusLine <> Nil) Then Insert(StatusLine);    { Insert status line }
+   InitMenuBar;                                       { Create a bar menu }
+   If (MenuBar <> Nil) Then Insert(MenuBar);          { Insert menu bar }
+   InitDesktop;                                       { Create desktop }
+   If (Desktop <> Nil) Then Insert(Desktop);          { Insert desktop }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TProgram.Done;
+VAR I: Integer;
+BEGIN
+   If (Desktop <> Nil) Then Dispose(Desktop, Done);   { Destroy desktop }
+   If (MenuBar <> Nil) Then Dispose(MenuBar, Done);   { Destroy menu bar }
+   If (StatusLine <> Nil) Then
+     Dispose(StatusLine, Done);                       { Destroy status line }
+   Application := Nil;                                { Clear application }
+   Inherited Done;                                    { Call ancestor }
+  {$IFDEF OS_WINDOWS}                                 { WIN/NT CODE }
+   For I := 0 To 15 Do DeleteObject(ColBrush[I]);     { Delete brushes }
+   For I := 0 To 15 Do DeleteObject(ColPen[I]);       { Delete pens }
+   AppWindow := 0;                                    { Zero app window }
+   {$ENDIF}
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.GetPalette: PPalette;
+CONST P: Array[apColor..apMonochrome] Of String = (CAppColor, CAppBlackWhite,
+  CAppMonochrome);
+BEGIN
+   GetPalette := @P[AppPalette];                      { Return palette }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  CanMoveFocus -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23Sep97 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.CanMoveFocus: Boolean;
+BEGIN
+   If (Desktop <> Nil) Then                           { Valid desktop view }
+     CanMovefocus := DeskTop^.Valid(cmReleasedFocus)  { Check focus move }
+     Else CanMoveFocus := True;                       { No desktop who cares! }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  ValidView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.ValidView (P: PView): PView;
+BEGIN
+   ValidView := Nil;                                  { Preset failure }
+   If (P <> Nil) Then Begin
+     If LowMemory Then Begin                          { Check memroy }
+       Dispose(P, Done);                              { Dispose view }
+       OutOfMemory;                                   { Call out of memory }
+       Exit;                                          { Now exit }
+     End;
+     If NOT P^.Valid(cmValid) Then Begin              { Check view valid }
+       Dispose(P, Done);                              { Dipose view }
+       Exit;                                          { Now exit }
+     End;
+     ValidView := P;                                  { Return view }
+   End;
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  InsertWindow -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.InsertWindow (P: PWindow): PWindow;
+BEGIN
+   InsertWindow := Nil;                               { Preset failure }
+   If (ValidView(P) <> Nil) Then                      { Check view valid }
+     If (CanMoveFocus) AND (Desktop <> Nil)           { Can we move focus }
+     Then Begin
+       Desktop^.Insert(P);                            { Insert window }
+       InsertWindow := P;                             { Return view ptr }
+     End Else Dispose(P, Done);                       { Dispose view }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  ExecuteDialog -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB     }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.ExecuteDialog (P: PDialog; Data: Pointer): Word;
+VAR ExecResult: Word;
+BEGIN
+   ExecuteDialog := cmCancel;                         { Preset cancel }
+   If (ValidView(P) <> Nil) Then Begin                { Check view valid }
+     If (Data <> Nil) Then P^.SetData(Data^);         { Set data }
+     If (P <> Nil) Then P^.SelectDefaultView;         { Select default }
+     ExecResult := Desktop^.ExecView(P);              { Execute view }
+     If (ExecResult <> cmCancel) AND (Data <> Nil)
+       Then P^.GetData(Data^);                        { Get data back }
+     Dispose(P, Done);                                { Dispose of dialog }
+     ExecuteDialog := ExecResult;                     { Return result }
+   End;
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  Run -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB               }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.Run;
+BEGIN
+   Execute;                                           { Call execute }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  Idle -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Oct99 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.Idle;
+BEGIN
+   If (StatusLine <> Nil) Then StatusLine^.Update;    { Update statusline }
+   If CommandSetChanged Then Begin                    { Check command change }
+     Message(@Self, evBroadcast, cmCommandSetChanged,
+       Nil);                                          { Send message }
+     CommandSetChanged := False;                      { Clear flag }
+   End;
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  InitScreen -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.InitScreen;
+BEGIN
+   If (Lo(ScreenMode) <> smMono) Then Begin           { Coloured mode }
+     If (ScreenMode AND smFont8x8 <> 0) Then
+       ShadowSize.X := 1 Else                         { Single bit shadow }
+       ShadowSize.X := 2;                             { Double size }
+     ShadowSize.Y := 1; ShowMarkers := False;         { Set variables }
+     If (Lo(ScreenMode) = smBW80) Then
+       AppPalette := apBlackWhite Else                { B & W palette }
+       AppPalette := apColor;                         { Coloured palette }
+   End Else Begin
+     ShadowSize.X := 0;                               { No x shadow size }
+     ShadowSize.Y := 0;                               { No y shadow size }
+     ShowMarkers := True;                             { Show markers }
+     AppPalette := apMonochrome;                      { Mono palette }
+   End;
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  InitDeskTop -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.InitDesktop;
+VAR R: TRect;
+BEGIN
+   GetExtent(R);                                      { Get view extent }
+   If (MenuBar <> Nil) Then Inc(R.A.Y);               { Adjust top down }
+   If (StatusLine <> Nil) Then Dec(R.B.Y);            { Adjust bottom up }
+   DeskTop := New(PDesktop, Init(R));                 { Create desktop }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  OutOfMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.OutOfMemory;
+BEGIN                                                 { Abstract method }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  InitMenuBar -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.InitMenuBar;
+VAR R: TRect;
+BEGIN
+   GetExtent(R);                                      { Get view extents }
+   R.B.Y := R.A.Y + 1;                                { One line high  }
+   MenuBar := New(PMenuBar, Init(R, Nil));            { Create menu bar }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  InitStatusLine -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.InitStatusLine;
+VAR R: TRect;
+BEGIN
+   GetExtent(R);                                      { Get view extents }
+   R.A.Y := R.B.Y - 1;                                { One line high }
+   New(StatusLine, Init(R,
+     NewStatusDef(0, $FFFF,
+       NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,
+       StdStatusKeys(Nil)), Nil)));                   { Default status line }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  SetScreenMode -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Oct99 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.SetScreenMode (Mode: Word);
+BEGIN                                                 { Compatability only }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  PutEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.PutEvent (Var Event: TEvent);
+BEGIN
+   Pending := Event;                                  { Set pending event }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  GetEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10May98 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.GetEvent (Var Event: TEvent);
+BEGIN
+   Event.What := evNothing;
+   If (Event.What = evNothing) Then Begin
+     If (Pending.What <> evNothing) Then Begin        { Pending event }
+       Event := Pending;                              { Load pending event }
+       Pending.What := evNothing;                     { Clear pending event }
+     End Else Begin
+       NextQueuedEvent(Event);                        { Next queued event }
+       If (Event.What = evNothing) Then Begin
+         GetKeyEvent(Event);                          { Fetch key event }
+         If (Event.What = evNothing) Then Begin       { No mouse event }
+           GetMouseEvent(Event);                      { Load mouse event }
+           If (Event.What = evNothing) Then Idle;     { Idle if no event }
+         End;
+       End;
+     End;
+   End;
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TProgram.HandleEvent (Var Event: TEvent);
+VAR I: Word; C: Char;
+BEGIN
+   If (Event.What = evKeyDown) Then Begin             { Key press event }
+     C := GetAltChar(Event.KeyCode);                  { Get alt char code }
+     If (C >= '1') AND (C <= '9') Then
+       If (Message(Desktop, evBroadCast, cmSelectWindowNum,
+         Pointer(Byte(C) - $30)) <> Nil)              { Select window }
+         Then ClearEvent(Event);                      { Clear event }
+   End;
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   If (Event.What = evCommand) AND                    { Command event }
+   (Event.Command = cmQuit) Then Begin                { Quit command }
+      EndModal(cmQuit);                               { Endmodal operation }
+      ClearEvent(Event);                              { Clear event }
+   End;
+END;
+
+{$IFNDEF OS_DOS}
+{***************************************************************************}
+{                  TProgram OBJECT WIN/NT/OS2 ONLY METHODS                  }
+{***************************************************************************}
+
+{--TProgram-----------------------------------------------------------------}
+{  GetClassText -> Platforms WIN/NT/OS2 - Checked 18Mar98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.GetClassText: String;
+VAR S: String; {$IFDEF OS_OS2} I: Integer; {$ENDIF}
+BEGIN
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     {$IFDEF PPC_DELPHI3}                             { DELPHI3+ CODE }
+     SetLength(S, 255);                               { Make string not empty }
+     SetLength(S, GetModuleFilename( 0, PChar(S),
+       Length(S) ) );                                 { Fetch module name }
+     {$ELSE}                                          { OTHER COMPILERS }
+     S[0] := Chr(GetModuleFileName(HInstance, @S[1],
+       255));                                         { Fetch module name }
+     {$ENDIF}
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   WinQuerySessionTitle(Anchor, 0, @S[1], 255);       { Fetch session name }
+   I := 1;                                            { Start on first }
+   While (S[I] <> #0) AND (I<255) Do Inc(I);          { Find pchar end }
+   S[0] := Chr(I);                                    { Set string length }
+   {$ENDIF}
+   GetClassText := S;                                 { Return the string }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  GetClassName -> Platforms WIN/NT/OS2 - Updated 13May98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.GetClassName: String;
+BEGIN
+   GetClassName := TvProgramClassName;                { Program class name }
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  GetClassAttr -> Platforms WIN/NT/OS2 - Checked 17Mar98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.GetClassAttr: LongInt;
+VAr Li: LongInt;
+BEGIN
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   Li := Inherited GetClassAttr;                      { Call ancestor }
+   Li := Li AND NOT ws_Child;                         { Not child view }
+   GetClassAttr := Li OR ws_OverlappedWindow;         { Overlapping window }
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   GetClassAttr := fcf_TitleBar OR fcf_SysMenu OR
+     fcf_SizeBorder OR fcf_MinMax OR fcf_TaskList OR
+     fcf_NoByteAlign;                                 { Window defaults }
+   {$ENDIF}
+END;
+
+{--TProgram-----------------------------------------------------------------}
+{  GetMsghandler -> Platforms WIN/NT/OS2 - Updated 13May98 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION TProgram.GetMsgHandler: Pointer;
+BEGIN
+   GetMsgHandler := @TvAppMsgHandler;                 { Application handler }
+END;
+
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TApplication OBJECT METHODS                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TApplication-------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TApplication.Init;
+BEGIN
+   InitMemory;                                        { Start memory up }
+   InitVideo;                                         { Start video up }
+   InitEvents;                                        { Start event drive }
+   InitSysError;                                      { Start system error }
+   InitHistory;                                       { Start history up }
+   Inherited Init;                                    { Call ancestor }
+END;
+
+{--TApplication-------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TApplication.Done;
+BEGIN
+   Inherited Done;                                    { Call ancestor }
+   DoneHistory;                                       { Close history }
+   DoneSysError;                                      { Close system error }
+   DoneEvents;                                        { Close event drive }
+   DoneVideo;                                         { Close video }
+   DoneMemory;                                        { Close memory }
+END;
+
+{--TApplication-------------------------------------------------------------}
+{  Tile -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TApplication.Tile;
+VAR R: TRect;
+BEGIN
+   GetTileRect(R);                                    { Tileable area }
+   If (Desktop <> Nil) Then Desktop^.Tile(R);         { Tile desktop }
+END;
+
+{--TApplication-------------------------------------------------------------}
+{  Cascade -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TApplication.Cascade;
+VAR R: TRect;
+BEGIN
+   GetTileRect(R);                                    { Cascade area }
+   If (Desktop <> Nil) Then Desktop^.Cascade(R);      { Cascade desktop }
+END;
+
+{--TApplication-------------------------------------------------------------}
+{  DosShell -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Oct99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TApplication.DosShell;
+BEGIN                                                 { Compatability only }
+END;
+
+{--TApplication-------------------------------------------------------------}
+{  GetTileRect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TApplication.GetTileRect (Var R: TRect);
+BEGIN
+   If (DeskTop <> Nil) Then Desktop^.GetExtent(R)     { Desktop extents }
+     Else GetExtent(R);                               { Our extents }
+END;
+
+{--TApplication-------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TApplication.HandleEvent (Var Event: TEvent);
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   If (Event.What = evCommand) Then Begin
+     Case Event.Command Of
+       cmTile: Tile;                                  { Tile request }
+       cmCascade: Cascade;                            { Cascade request }
+       cmDosShell: DosShell;                          { DOS shell request }
+       Else Exit;                                     { Unhandled exit }
+     End;
+     ClearEvent(Event);                               { Clear the event }
+   End;
+END;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                STANDARD MENU AND STATUS LINES ROUTINES                    }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  StdStatusKeys -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB     }
+{---------------------------------------------------------------------------}
+FUNCTION StdStatusKeys (Next: PStatusItem): PStatusItem;
+BEGIN
+   StdStatusKeys :=
+     NewStatusKey('', kbAltX, cmQuit,
+     NewStatusKey('', kbF10, cmMenu,
+     NewStatusKey('', kbAltF3, cmClose,
+     NewStatusKey('', kbF5, cmZoom,
+     NewStatusKey('', kbCtrlF5, cmResize,
+     NewStatusKey('', kbF6, cmNext,
+     NewStatusKey('', kbShiftF6, cmPrev,
+     Next)))))));
+END;
+
+{---------------------------------------------------------------------------}
+{  StdFileMenuItems -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB  }
+{---------------------------------------------------------------------------}
+FUNCTION StdFileMenuItems (Next: PMenuItem): PMenuItem;
+BEGIN
+   StdFileMenuItems :=
+     NewItem('~N~ew', '', kbNoKey, cmNew, hcNew,
+     NewItem('~O~pen...', 'F3', kbF3, cmOpen, hcOpen,
+     NewItem('~S~ave', 'F2', kbF2, cmSave, hcSave,
+     NewItem('S~a~ve as...', '', kbNoKey, cmSaveAs, hcSaveAs,
+     NewItem('Save a~l~l', '', kbNoKey, cmSaveAll, hcSaveAll,
+     NewLine(
+     NewItem('~C~hange dir...', '', kbNoKey, cmChangeDir, hcChangeDir,
+     NewItem('OS shell', '', kbNoKey, cmDosShell, hcDosShell,
+     NewItem('E~x~it', 'Alt+X', kbAltX, cmQuit, hcExit,
+     Next)))))))));
+END;
+
+{---------------------------------------------------------------------------}
+{  StdEditMenuItems -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB  }
+{---------------------------------------------------------------------------}
+FUNCTION StdEditMenuItems (Next: PMenuItem): PMenuItem;
+BEGIN
+   StdEditMenuItems :=
+     NewItem('~U~ndo', '', kbAltBack, cmUndo, hcUndo,
+     NewLine(
+     NewItem('Cu~t~', 'Shift+Del', kbShiftDel, cmCut, hcCut,
+     NewItem('~C~opy', 'Ctrl+Ins', kbCtrlIns, cmCopy, hcCopy,
+     NewItem('~P~aste', 'Shift+Ins', kbShiftIns, cmPaste, hcPaste,
+     NewItem('C~l~ear', 'Ctrl+Del', kbCtrlDel, cmClear, hcClear,
+     Next))))));
+END;
+
+{---------------------------------------------------------------------------}
+{ StdWindowMenuItems -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB }
+{---------------------------------------------------------------------------}
+FUNCTION StdWindowMenuItems (Next: PMenuItem): PMenuItem;
+BEGIN
+   StdWindowMenuItems :=
+     NewItem('~T~ile', '', kbNoKey, cmTile, hcTile,
+     NewItem('C~a~scade', '', kbNoKey, cmCascade, hcCascade,
+     NewItem('Cl~o~se all', '', kbNoKey, cmCloseAll, hcCloseAll,
+     NewLine(
+     NewItem('~S~ize/Move','Ctrl+F5', kbCtrlF5, cmResize, hcResize,
+     NewItem('~Z~oom', 'F5', kbF5, cmZoom, hcZoom,
+     NewItem('~N~ext', 'F6', kbF6, cmNext, hcNext,
+     NewItem('~P~revious', 'Shift+F6', kbShiftF6, cmPrev, hcPrev,
+     NewItem('~C~lose', 'Alt+F3', kbAltF3, cmClose, hcClose,
+     Next)))))))));
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           OBJECT REGISTER ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  RegisterApp -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE RegisterApp;
+BEGIN
+   RegisterType(RBackground);                         { Register background }
+   RegisterType(RDesktop);                            { Register desktop }
+END;
+
+END.
+
+
+

+ 3214 - 0
fv/dialogs.pas

@@ -0,0 +1,3214 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{   System independent GRAPHICAL clone of DIALOGS.PAS      }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail addr           }
+{   [email protected] - backup e-mail addr            }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     11 Nov 96   First DOS/DPMI platform release.   }
+{  1.10     13 Jul 97   Windows platform code added.       }
+{  1.20     29 Aug 97   Platform.inc sort added.           }
+{  1.30     13 Oct 97   Delphi 2 32 bit code added.        }
+{  1.40     05 May 98   Virtual pascal 2.0 code added.     }
+{  1.50     27 Oct 99   All objects completed and checked  }
+{  1.51     03 Nov 99   FPC windows support added          }
+{  1.60     26 Nov 99   Graphics stuff moved to GFVGraph   }
+{**********************************************************}
+
+UNIT Dialogs;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F-} { Short calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     {$IFNDEF PPC_SPEED}                              { NON SPEED COMPILER }
+       {$IFDEF PPC_FPC}                               { FPC WINDOWS COMPILER }
+       Windows,                                       { Standard units }
+       {$ELSE}                                        { OTHER COMPILERS }
+       WinTypes,WinProcs,                             { Standard units }
+       {$ENDIF}
+     {$ELSE}                                          { SPEEDSOFT COMPILER }
+       WinBase, WinDef, WinUser, WinGDI,              { Standard units }
+     {$ENDIF}
+     {$IFDEF PPC_DELPHI}                              { DELPHI COMPILERS }
+     Messages,                                        { Standard unit }
+     {$ENDIF}
+   {$ENDIF}
+
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+     OS2Def, OS2Base, OS2PMAPI,                       { Standard units }
+   {$ENDIF}
+
+   Common, GFVGraph, Objects, Drivers, Views, Validate; { Standard GFV units }
+
+{***************************************************************************}
+{                              PUBLIC CONSTANTS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                        COLOUR PALETTE DEFINITIONS                         }
+{---------------------------------------------------------------------------}
+CONST
+   CGrayDialog    = #32#33#34#35#36#37#38#39#40#41#42#43#44#45#46#47 +
+                    #48#49#50#51#52#53#54#55#56#57#58#59#60#61#62#63;
+   CBlueDialog    = #64#65#66#67#68#69#70#71#72#73#74#75#76#77#78#79 +
+                    #80#81#82#83#84#85#86#87#88#89#90#91#92#92#94#95;
+   CCyanDialog    = #96#97#98#99#100#101#102#103#104#105#106#107#108 +
+                    #109#110#111#112#113#114#115#116#117#118#119#120 +
+                    #121#122#123#124#125#126#127;
+   CStaticText    = #6#7#8#9;
+   CLabel         = #7#8#9#9;
+   CButton        = #10#11#12#13#14#14#14#15;
+   CCluster       = #16#17#18#18#31#6;
+   CInputLine     = #19#19#20#21#14;
+   CHistory       = #22#23;
+   CHistoryWindow = #19#19#21#24#25#19#20;
+   CHistoryViewer = #6#6#7#6#6;
+
+   CDialog = CGrayDialog;                             { Default palette }
+
+
+{$IFNDEF OS_DOS}                                      { WIN/NT/OS2 CODE }
+{---------------------------------------------------------------------------}
+{                        NEW WIN/NT/OS2 COMMAND CODES                       }
+{---------------------------------------------------------------------------}
+CONST
+   cmTvClusterButton = $2001;                         { Cluster button cmd id }
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                     TDialog PALETTE COLOUR CONSTANTS                      }
+{---------------------------------------------------------------------------}
+CONST
+   dpBlueDialog = 0;                                  { Blue dialog colour }
+   dpCyanDialog = 1;                                  { Cyan dialog colour }
+   dpGrayDialog = 2;                                  { Gray dialog colour }
+
+{---------------------------------------------------------------------------}
+{                           TButton FLAGS MASKS                             }
+{---------------------------------------------------------------------------}
+CONST
+   bfNormal    = $00;                                 { Normal displayed }
+   bfDefault   = $01;                                 { Default command }
+   bfLeftJust  = $02;                                 { Left just text }
+   bfBroadcast = $04;                                 { Broadcast command }
+   bfGrabFocus = $08;                                 { Grab focus }
+
+{---------------------------------------------------------------------------}
+{          TMultiCheckBoxes FLAGS - (HiByte = Bits LoByte = Mask)           }
+{---------------------------------------------------------------------------}
+CONST
+   cfOneBit    = $0101;                               { One bit masks }
+   cfTwoBits   = $0203;                               { Two bit masks }
+   cfFourBits  = $040F;                               { Four bit masks }
+   cfEightBits = $08FF;                               { Eight bit masks }
+
+{---------------------------------------------------------------------------}
+{                        DIALOG BROADCAST COMMANDS                          }
+{---------------------------------------------------------------------------}
+CONST
+   cmRecordHistory = 60;                              { Record history cmd }
+
+{***************************************************************************}
+{                            RECORD DEFINITIONS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                          ITEM RECORD DEFINITION                           }
+{---------------------------------------------------------------------------}
+TYPE
+   PSItem = ^TSItem;
+   TSItem = RECORD
+     Value: PString;                                  { Item string }
+     Next: PSItem;                                    { Next item }
+   END;
+
+{***************************************************************************}
+{                            OBJECT DEFINITIONS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                      TDialog OBJECT - DIALOG OBJECT                       }
+{---------------------------------------------------------------------------}
+TYPE
+   TDialog = OBJECT (TWindow)
+      CONSTRUCTOR Init (Var Bounds: TRect; ATitle: TTitleStr);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION Valid (Command: Word): Boolean; Virtual;
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+   END;
+   PDialog = ^TDialog;
+
+{---------------------------------------------------------------------------}
+{                   TInputLine OBJECT - INPUT LINE OBJECT                   }
+{---------------------------------------------------------------------------}
+TYPE
+   TInputLine = OBJECT (TView)
+         MaxLen: Integer;                             { Max input length }
+         CurPos: Integer;                             { Cursor position }
+         FirstPos: Integer;                           { First position }
+         SelStart: Integer;                           { Selected start }
+         SelEnd: Integer;                             { Selected end }
+         Data: PString;                               { Input line data }
+         Validator: PValidator;                       { Validator of view }
+      CONSTRUCTOR Init (Var Bounds: TRect; AMaxLen: Integer);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION DataSize: Word; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION Valid (Command: Word): Boolean; Virtual;
+      PROCEDURE Draw; Virtual;
+      PROCEDURE DrawCursor; Virtual;
+      PROCEDURE DrawbackGround; Virtual;
+      PROCEDURE SelectAll (Enable: Boolean);
+      PROCEDURE SetValidator (AValid: PValidator);
+      PROCEDURE SetState (AState: Word; Enable: Boolean); Virtual;
+      PROCEDURE GetData (Var Rec); Virtual;
+      PROCEDURE SetData (Var Rec); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PRIVATE
+      FUNCTION CanScroll (Delta: Integer): Boolean;
+   END;
+   PInputLine = ^TInputLine;
+
+{---------------------------------------------------------------------------}
+{                  TButton OBJECT - BUTTON ANCESTOR OBJECT                  }
+{---------------------------------------------------------------------------}
+TYPE
+   TButton = OBJECT (TView)
+         AmDefault: Boolean;                          { If default button }
+         Flags    : Byte;                             { Button flags }
+         Command  : Word;                             { Button command }
+         Title    : PString;                          { Button title }
+      CONSTRUCTOR Init (Var Bounds: TRect; ATitle: TTitleStr; ACommand: Word;
+        AFlags: Word);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      PROCEDURE Press; Virtual;
+      PROCEDURE DrawFocus; Virtual;
+      PROCEDURE DrawState (Down: Boolean);
+      PROCEDURE MakeDefault (Enable: Boolean);
+      PROCEDURE SetState (AState: Word; Enable: Boolean); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PRIVATE
+      DownFlag: Boolean;
+   END;
+   PButton = ^TButton;
+
+{---------------------------------------------------------------------------}
+{                 TCluster OBJECT - CLUSTER ANCESTOR OBJECT                 }
+{---------------------------------------------------------------------------}
+TYPE
+   {$IFNDEF OS_DOS}                                   { WIN/NT/OS2 CODE }
+   TWndArray = Array [0..32000] Of HWnd;              { Window handle array }
+   PWndArray = ^TWndArray;                            { Ptr to handle array }
+   {$ENDIF}
+
+   TCluster = OBJECT (TView)
+         Id        : Integer;                         { New communicate id }
+         Sel       : Integer;                         { Selected item }
+         Value     : LongInt;                         { Bit value }
+         EnableMask: LongInt;                         { Mask enable bits }
+         Strings   : TStringCollection;               { String collection }
+         {$IFNDEF OS_DOS}                             { WIN/NT/OS2 DATA }
+         WndHandles: PWndArray;                       { Window handle array }
+         {$ENDIF}
+      CONSTRUCTOR Init (Var Bounds: TRect; AStrings: PSItem);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION DataSize: Word; Virtual;
+      FUNCTION GetHelpCtx: Word; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION Mark (Item: Integer): Boolean; Virtual;
+      FUNCTION MultiMark (Item: Integer): Byte; Virtual;
+      FUNCTION ButtonState (Item: Integer): Boolean;
+      PROCEDURE DrawFocus;                                           Virtual;
+      PROCEDURE Press (Item: Integer); Virtual;
+      PROCEDURE MovedTo (Item: Integer); Virtual;
+      PROCEDURE SetState (AState: Word; Enable: Boolean); Virtual;
+      PROCEDURE DrawMultiBox (Const Icon, Marker: String);
+      PROCEDURE DrawBox (Const Icon: String; Marker: Char);
+      PROCEDURE SetButtonState (AMask: Longint; Enable: Boolean);
+      PROCEDURE GetData (Var Rec); Virtual;
+      PROCEDURE SetData (Var Rec); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent);                     Virtual;
+      {$IFNDEF OS_DOS}                                { WIN/NT/OS2 CODE }
+      FUNCTION GetClassName: String; Virtual;
+      FUNCTION SubClassAttr: LongInt; Virtual;
+      FUNCTION GetMsgHandler: Pointer; Virtual;
+      PROCEDURE CreateWindowNow (CmdShow: Integer);                  Virtual;
+      {$ENDIF}
+      PRIVATE
+      FUNCTION FindSel (P: TPoint): Integer;
+      FUNCTION Row (Item: Integer): Integer;
+      FUNCTION Column (Item: Integer): Integer;
+   END;
+   PCluster = ^TCluster;
+
+{---------------------------------------------------------------------------}
+{                TRadioButtons OBJECT - RADIO BUTTON OBJECT                 }
+{---------------------------------------------------------------------------}
+TYPE
+   TRadioButtons = OBJECT (TCluster)
+      FUNCTION Mark (Item: Integer): Boolean; Virtual;
+      PROCEDURE DrawFocus; Virtual;
+      PROCEDURE Press (Item: Integer); Virtual;
+      PROCEDURE MovedTo(Item: Integer); Virtual;
+      PROCEDURE SetData (Var Rec); Virtual;
+      {$IFNDEF OS_DOS}                                { WIN/NT CODE }
+      FUNCTION SubClassAttr: LongInt; Virtual;
+      {$ENDIF}
+   END;
+   PRadioButtons = ^TRadioButtons;
+
+{---------------------------------------------------------------------------}
+{                  TCheckBoxes OBJECT - CHECK BOXES OBJECT                  }
+{---------------------------------------------------------------------------}
+TYPE
+   TCheckBoxes = OBJECT (TCluster)
+      FUNCTION Mark (Item: Integer): Boolean; Virtual;
+      PROCEDURE DrawFocus; Virtual;
+      PROCEDURE Press (Item: Integer); Virtual;
+      {$IFNDEF OS_DOS}                                { WIN/NT CODE }
+      FUNCTION SubClassAttr: LongInt; Virtual;
+      {$ENDIF}
+   END;
+   PCheckBoxes = ^TCheckBoxes;
+
+{---------------------------------------------------------------------------}
+{               TMultiCheckBoxes OBJECT - CHECK BOXES OBJECT                }
+{---------------------------------------------------------------------------}
+TYPE
+   TMultiCheckBoxes = OBJECT (TCluster)
+         SelRange: Byte;                              { Select item range }
+         Flags   : Word;                              { Select flags }
+         States  : PString;                           { Strings }
+      CONSTRUCTOR Init (Var Bounds: TRect; AStrings: PSItem;
+        ASelRange: Byte; AFlags: Word; Const AStates: String);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION DataSize: Word; Virtual;
+      FUNCTION MultiMark (Item: Integer): Byte; Virtual;
+      PROCEDURE DrawFocus; Virtual;
+      PROCEDURE Press (Item: Integer); Virtual;
+      PROCEDURE GetData (Var Rec); Virtual;
+      PROCEDURE SetData (Var Rec); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      {$IFNDEF OS_DOS}                                { WIN/NT CODE }
+      FUNCTION SubClassAttr: LongInt; Virtual;
+      {$ENDIF}
+   END;
+   PMultiCheckBoxes = ^TMultiCheckBoxes;
+
+{---------------------------------------------------------------------------}
+{                     TListBox OBJECT - LIST BOX OBJECT                     }
+{---------------------------------------------------------------------------}
+TYPE
+   TListBox = OBJECT (TListViewer)
+         List: PCollection;                           { List of strings }
+      CONSTRUCTOR Init (Var Bounds: TRect; ANumCols: Word;
+        AScrollBar: PScrollBar);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION DataSize: Word; Virtual;
+      FUNCTION GetText (Item: Integer; MaxLen: Integer): String; Virtual;
+      PROCEDURE NewList(AList: PCollection); Virtual;
+      PROCEDURE GetData (Var Rec); Virtual;
+      PROCEDURE SetData (Var Rec); Virtual;
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PListBox = ^TListBox;
+
+{---------------------------------------------------------------------------}
+{                TStaticText OBJECT - STATIC TEXT OBJECT                    }
+{---------------------------------------------------------------------------}
+TYPE
+   TStaticText = OBJECT (TView)
+         Text: PString;                               { Text string ptr }
+      CONSTRUCTOR Init (Var Bounds: TRect; Const AText: String);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      PROCEDURE DrawBackGround;                                      Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE GetText (Var S: String); Virtual;
+   END;
+   PStaticText = ^TStaticText;
+
+{---------------------------------------------------------------------------}
+{              TParamText OBJECT - PARMETER STATIC TEXT OBJECT              }
+{---------------------------------------------------------------------------}
+TYPE
+   TParamText = OBJECT (TStaticText)
+         ParamCount: Integer;                         { Parameter count }
+         ParamList : Pointer;                         { Parameter list }
+      CONSTRUCTOR Init (Var Bounds: TRect; Const AText: String;
+        AParamCount: Integer);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION DataSize: Word; Virtual;
+      PROCEDURE GetData (Var Rec); Virtual;
+      PROCEDURE SetData (Var Rec); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE GetText (Var S: String); Virtual;
+   END;
+   PParamText = ^TParamText;
+
+{---------------------------------------------------------------------------}
+{                        TLabel OBJECT - LABEL OBJECT                       }
+{---------------------------------------------------------------------------}
+TYPE
+   TLabel = OBJECT (TStaticText)
+         Light: Boolean;
+         Link: PView;                                 { Linked view }
+      CONSTRUCTOR Init (Var Bounds: TRect; CONST AText: String; ALink: PView);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION GetPalette: PPalette; Virtual;
+      PROCEDURE DrawBackGround; Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+   END;
+   PLabel = ^TLabel;
+
+{---------------------------------------------------------------------------}
+{             THistoryViewer OBJECT - HISTORY VIEWER OBJECT                 }
+{---------------------------------------------------------------------------}
+TYPE
+   THistoryViewer = OBJECT (TListViewer)
+         HistoryId: Word;                             { History id }
+      CONSTRUCTOR Init(Var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar;
+        AHistoryId: Word);
+      FUNCTION HistoryWidth: Integer;
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION GetText (Item: Integer; MaxLen: Integer): String; Virtual;
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+   END;
+   PHistoryViewer = ^THistoryViewer;
+
+{---------------------------------------------------------------------------}
+{             THistoryWindow OBJECT - HISTORY WINDOW OBJECT                 }
+{---------------------------------------------------------------------------}
+TYPE
+  THistoryWindow = OBJECT (TWindow)
+         Viewer: PListViewer;                         { List viewer object }
+      CONSTRUCTOR Init (Var Bounds: TRect; HistoryId: Word);
+      FUNCTION GetSelection: String; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      PROCEDURE InitViewer (HistoryId: Word); Virtual;
+   END;
+   PHistoryWindow = ^THistoryWindow;
+
+{---------------------------------------------------------------------------}
+{                   THistory OBJECT - HISTORY OBJECT                        }
+{---------------------------------------------------------------------------}
+TYPE
+   THistory = OBJECT (TView)
+         HistoryId: Word;
+         Link: PInputLine;
+      CONSTRUCTOR Init (Var Bounds: TRect; ALink: PInputLine; AHistoryId: Word);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION InitHistoryWindow (Var Bounds: TRect): PHistoryWindow; Virtual;
+      PROCEDURE Draw; Virtual;
+      PROCEDURE RecordHistory (CONST S: String); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+   END;
+   PHistory = ^THistory;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           ITEM STRING ROUTINES                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-NewSItem-----------------------------------------------------------
+Allocates memory for a new TSItem record and sets the text field
+and chains to the next TSItem. This allows easy construction of
+singly-linked lists of strings, to end a chain the next TSItem
+should be nil.
+28Apr98 LdB
+---------------------------------------------------------------------}
+FUNCTION NewSItem (Const Str: String; ANext: PSItem): PSItem;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                   DIALOG OBJECT REGISTRATION PROCEDURE                    }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-RegisterDialogs----------------------------------------------------
+This registers all the view type objects used in this unit.
+30Sep99 LdB
+---------------------------------------------------------------------}
+PROCEDURE RegisterDialogs;
+
+{***************************************************************************}
+{                        STREAM REGISTRATION RECORDS                        }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                        TDialog STREAM REGISTRATION                        }
+{---------------------------------------------------------------------------}
+CONST
+   RDialog: TStreamRec = (
+     ObjType: 10;                                     { Register id = 10 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TDialog)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TDialog);
+     {$ENDIF}
+     Load:  @TDialog.Load;                            { Object load method }
+     Store: @TDialog.Store                            { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                      TInputLine STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RInputLine: TStreamRec = (
+     ObjType: 11;                                     { Register id = 11 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TInputLine)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TInputLine);
+     {$ENDIF}
+     Load:  @TInputLine.Load;                         { Object load method }
+     Store: @TInputLine.Store                         { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                        TButton STREAM REGISTRATION                        }
+{---------------------------------------------------------------------------}
+CONST
+   RButton: TStreamRec = (
+     ObjType: 12;                                     { Register id = 12 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TButton)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TButton);
+     {$ENDIF}
+     Load:  @TButton.Load;                            { Object load method }
+     Store: @TButton.Store                            { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                       TCluster STREAM REGISTRATION                        }
+{---------------------------------------------------------------------------}
+CONST
+   RCluster: TStreamRec = (
+     ObjType: 13;                                     { Register id = 13 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TCluster)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TCluster);
+     {$ENDIF}
+     Load:  @TCluster.Load;                           { Object load method }
+     Store: @TCluster.Store                           { Objects store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                    TRadioButtons STREAM REGISTRATION                      }
+{---------------------------------------------------------------------------}
+CONST
+   RRadioButtons: TStreamRec = (
+     ObjType: 14;                                     { Register id = 14 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TRadioButtons)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TRadioButtons);
+     {$ENDIF}
+     Load:  @TRadioButtons.Load;                      { Object load method }
+     Store: @TRadioButtons.Store                      { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                     TCheckBoxes STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RCheckBoxes: TStreamRec = (
+     ObjType: 15;                                     { Register id = 15 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TCheckBoxes)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TCheckBoxes);
+     {$ENDIF}
+     Load:  @TCheckBoxes.Load;                        { Object load method }
+     Store: @TCheckBoxes.Store                        { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                   TMultiCheckBoxes STREAM REGISTRATION                    }
+{---------------------------------------------------------------------------}
+CONST
+   RMultiCheckBoxes: TStreamRec = (
+     ObjType: 27;                                     { Register id = 27 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TMultiCheckBoxes)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TMultiCheckBoxes);
+     {$ENDIF}
+     Load:  @TMultiCheckBoxes.Load;                   { Object load method }
+     Store: @TMultiCheckBoxes.Store                   { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                        TListBox STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RListBox: TStreamRec = (
+     ObjType: 16;                                     { Register id = 16 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TListBox)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TListBox);
+     {$ENDIF}
+     Load:  @TListBox.Load;                           { Object load method }
+     Store: @TListBox.Store                           { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                      TStaticText STREAM REGISTRATION                      }
+{---------------------------------------------------------------------------}
+CONST
+   RStaticText: TStreamRec = (
+     ObjType: 17;                                     { Register id = 17 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TStaticText)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TStaticText);
+     {$ENDIF}
+     Load:  @TStaticText.Load;                        { Object load method }
+     Store: @TStaticText.Store                        { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                        TLabel STREAM REGISTRATION                         }
+{---------------------------------------------------------------------------}
+CONST
+   RLabel: TStreamRec = (
+     ObjType: 18;                                     { Register id = 18 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TLabel)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TLabel);
+     {$ENDIF}
+     Load:  @TLabel.Load;                             { Object load method }
+     Store: @TLabel.Store                             { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                        THistory STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RHistory: TStreamRec = (
+     ObjType: 19;                                     { Register id = 19 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(THistory)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(THistory);
+     {$ENDIF}
+     Load:  @THistory.Load;                           { Object load method }
+     Store: @THistory.Store                           { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                      TParamText STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RParamText: TStreamRec = (
+     ObjType: 20;                                     { Register id = 20 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TParamText)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TParamText);
+     {$ENDIF}
+     Load:  @TParamText.Load;                         { Object load method }
+     Store: @TParamText.Store                         { Object store method }
+   );
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+USES HistList;                                        { Standard GFV unit }
+
+{***************************************************************************}
+{                         PRIVATE DEFINED CONSTANTS                         }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                 LEFT AND RIGHT ARROW CHARACTER CONSTANTS                  }
+{---------------------------------------------------------------------------}
+{$IFDEF OS_DOS} CONST LeftArr = #17; RightArr = #16; {$ENDIF}
+{$IFDEF OS_WINDOWS} CONST LeftArr = #$AB; RightArr = #$BB; {$ENDIF}
+{$IFDEF OS_OS2} CONST LeftArr = #17; RightArr = #16; {$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                               TButton MESSAGES                            }
+{---------------------------------------------------------------------------}
+CONST
+   cmGrabDefault    = 61;                             { Grab default }
+   cmReleaseDefault = 62;                             { Release default }
+
+{***************************************************************************}
+{                          PRIVATE INTERNAL ROUTINES                        }
+{***************************************************************************}
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+{---------------------------------------------------------------------------}
+{  TvClusterMsgHandler -> Platforms WIN/NT - Checked 08Jun98 LdB            }
+{---------------------------------------------------------------------------}
+FUNCTION TvClusterMsgHandler (Wnd: hWnd; iMessage, wParam: sw_Word;
+lParam: LongInt): LongInt; {$IFDEF BIT_32} STDCALL; {$ELSE} EXPORT; {$ENDIF}
+VAR Sel: Integer; W: sw_Word; P: PCluster;
+BEGIN
+   TvClusterMsgHandler := 0;                          { Reset return of zero }
+   Case iMessage Of
+     WM_KeyDown:;                                     { Ignore keypresses }
+     WM_Command: Begin
+       If (wParam AND $FFFF = cmTvClusterButton)      { Command message }
+       Then Begin
+         {$IFDEF BIT_16}                              { 16 BIT CODE }
+         PtrRec(P).Seg := GetProp(Wnd, ViewSeg);      { Fetch cluster seg }
+         PtrRec(P).Ofs := GetProp(Wnd, ViewOfs);      { Fetch cluster ofs }
+         {$ENDIF}
+         {$IFDEF BIT_32}                              { 32 BIT CODE }
+         LongInt(P) := GetProp(Wnd, ViewPtr);         { Fetch cluster ptr }
+         {$ENDIF}
+         If (P <> Nil) AND (P^.WndHandles <> Nil)     { Cluster/handles valid }
+         Then Begin
+           If (P^.State AND sfFocused = 0) Then       { We have not focus }
+             P^.FocusFromTop;                         { Focus up to us }
+           Sel := 0;                                  { Start on first }
+           {$IFDEF BIT_16}                            { 16 BIT CODE }
+           W := LoWord(lParam);                       { Use only low part }
+           {$ENDIF}
+           {$IFDEF BIT_32}                            { 32 BIT CODE }
+           W := lParam;                               { Use full param }
+           {$ENDIF}
+           While (Sel < P^.Strings.Count) AND         { Valid item }
+           (W <> P^.WndHandles^[Sel]) Do Inc(Sel);    { Find handle }
+           If (Sel < P^.Strings.Count) Then Begin     { Handle was found }
+             P^.Press(Sel);                           { Call press }
+             P^.Sel := Sel;                           { Set selection }
+             If (P^.GetState(sfSelected)=False)       { Check not selected }
+             Then P^.Select Else Begin                { Select us then }
+               P^.SetDrawMask(vdFocus OR vdInner);    { Redraw inner }
+               P^.DrawView;                           { Redraw partial view }
+             End;
+           End;
+         End;
+       End Else
+         TvClusterMsgHandler := TvViewMsgHandler(Wnd,
+           iMessage, wParam, lParam);                 { Call TV view handler }
+     End;
+     Else TvClusterMsgHandler := TvViewMsgHandler(Wnd,
+      iMessage, wParam, lParam);                      { Call TV view handler }
+   End;
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+{---------------------------------------------------------------------------}
+{  TvClusterMsgHandler -> Platforms OS2 - Checked ??Sep99 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TvClusterMsgHandler (Wnd: hWnd; iMessage, wParam: sw_Word;
+lParam: LongInt): LongInt; STDCALL;
+VAR Sel: Integer; W: sw_Word; P: PCluster;
+BEGIN
+   TvClusterMsgHandler := 0;                          { Reset return of zero }
+   TvClusterMsgHandler := TvViewMsgHandler(Wnd,
+    iMessage, wParam, lParam);                        { Call TV view handler }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  IsBlank -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jun98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION IsBlank (Ch: Char): Boolean;
+BEGIN
+   IsBlank := (Ch = ' ') OR (Ch = #13) OR (Ch = #10); { Check for characters }
+END;
+
+{---------------------------------------------------------------------------}
+{  HotKey -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jun98 LdB            }
+{---------------------------------------------------------------------------}
+FUNCTION HotKey (Const S: String): Char;
+VAR I: Word;
+BEGIN
+   HotKey := #0;                                      { Preset fail }
+   If (S <> '') Then Begin                            { Valid string }
+     I := Pos('~', S);                                { Search for tilde }
+     If (I <> 0) Then HotKey := UpCase(S[I+1]);       { Return hotkey }
+   End;
+END;
+
+{***************************************************************************}
+{                              OBJECT METHODS                               }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TDialog OBJECT METHODS                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TDialog------------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Apr98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TDialog.Init (Var Bounds: TRect; ATitle: TTitleStr);
+BEGIN
+   Inherited Init(Bounds, ATitle, wnNoNumber);        { Call ancestor }
+   Options := Options OR ofVersion20;                 { Version two dialog }
+   GrowMode := 0;                                     { Clear grow mode }
+   Flags := wfMove + wfClose;                         { Close/moveable flags }
+   Palette := dpGrayDialog;                           { Default gray colours }
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   GOptions := GOptions AND NOT goThickFramed;        { Turn thick frame off }
+   ExStyle := ws_Ex_DlgModalFrame;                    { Set extended style }
+   {$ENDIF}
+END;
+
+{--TDialog------------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Apr98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TDialog.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   If (Options AND ofVersion = ofVersion10) Then Begin
+     Palette := dpGrayDialog;                         { Set gray palette }
+     Options := Options OR ofVersion20;               { Update version flag }
+   End;
+END;
+
+{--TDialog------------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Apr98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TDialog.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: Array[dpBlueDialog..dpGrayDialog] Of String =
+    (CBlueDialog, CCyanDialog, CGrayDialog);          { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: Array[dpBlueDialog..dpGrayDialog] Of String[Length(CBlueDialog)] =
+    (CBlueDialog, CCyanDialog, CGrayDialog);          { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P[Palette];                         { Return palette }
+END;
+
+{--TDialog------------------------------------------------------------------}
+{  Valid -> Platforms DOS/DPMI/WIN/NT/Os2 - Updated 25Apr98 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION TDialog.Valid (Command: Word): Boolean;
+BEGIN
+   If (Command = cmCancel) Then Valid := True         { Cancel returns true }
+     Else Valid := TGroup.Valid(Command);             { Call group ancestor }
+END;
+
+{--TDialog------------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Apr98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TDialog.HandleEvent (Var Event: TEvent);
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   Case Event.What Of
+     evNothing: Exit;                                 { Speed up exit }
+     evKeyDown:                                       { Key down event }
+       Case Event.KeyCode Of
+         kbEsc: Begin                                 { Escape key press }
+             Event.What := evCommand;                 { Command event }
+             Event.Command := cmCancel;               { cancel command }
+             Event.InfoPtr := Nil;                    { Clear info ptr }
+             PutEvent(Event);                         { Put event on queue }
+             ClearEvent(Event);                       { Clear the event }
+           End;
+         kbEnter: Begin                               { Enter key press }
+             Event.What := evBroadcast;               { Broadcast event }
+             Event.Command := cmDefault;              { Default command }
+             Event.InfoPtr := Nil;                    { Clear info ptr }
+             PutEvent(Event);                         { Put event on queue }
+             ClearEvent(Event);                       { Clear the event }
+           End;
+       End;
+     evCommand:                                       { Command event }
+       Case Event.Command Of
+         cmOk, cmCancel, cmYes, cmNo:                 { End dialog cmds }
+           If (State AND sfModal <> 0) Then Begin     { View is modal }
+             EndModal(Event.Command);                 { End modal state }
+             ClearEvent(Event);                       { Clear the event }
+           End;
+       End;
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                       TInputLine OBJECT METHODS                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TInputLine---------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TInputLine.Init (Var Bounds: TRect; AMaxLen: Integer);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   State := State OR sfCursorVis;                     { Cursor visible }
+   Options := Options OR (ofSelectable + ofFirstClick
+     + ofVersion20);                                  { Set options }
+   If (MaxAvail > AMaxLen + 1) Then Begin             { Check enough memory }
+     GetMem(Data, AMaxLen + 1);                       { Allocate memory }
+     Data^ := '';                                     { Data = empty string }
+   End;
+   MaxLen := AMaxLen;                                 { Hold maximum length }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TInputLine.Load (Var S: TStream);
+VAR B: Byte;
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(MaxLen, 2);                                 { Read max length }
+   S.Read(CurPos, 2);                                 { Read cursor position }
+   S.Read(FirstPos, 2);                               { Read first position }
+   S.Read(SelStart, 2);                               { Read selected start }
+   S.Read(SelEnd, 2);                                 { Read selected end }
+   S.Read(B, 1);                                      { Read string length }
+   If (MaxAvail > MaxLen+1) Then Begin                { Check enough memory }
+     GetMem(Data, MaxLen + 1);                        { Allocate memory }
+     S.Read(Data^[1], Length(Data^));                 { Read string data }
+     {$IFDEF PPC_DELPHI3}                             { DELPHI 3+ COMPILER }
+     SetLength(Data^, B);                             { Xfer string length }
+     {$ELSE}                                          { OTHER COMPILERS }
+     Data^[0] := Chr(B);                              { Set string length }
+     {$ENDIF}
+   End Else S.Seek(S.GetPos + B);                     { Move to position }
+   If (Options AND ofVersion >= ofVersion20) Then     { Version 2 or above }
+     Validator := PValidator(S.Get);                  { Get any validator }
+   Options := Options OR ofVersion20;                 { Set version 2 flag }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TInputLine.Done;
+BEGIN
+   If (Data <> Nil) Then FreeMem(Data, MaxLen + 1);    { Release any memory }
+   SetValidator(Nil);                                  { Clear any validator }
+   Inherited Done;                                     { Call ancestor }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  DataSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TInputLine.DataSize: Word;
+VAR DSize: Word;
+BEGIN
+   DSize := 0;                                        { Preset zero datasize }
+   If (Validator <> Nil) AND (Data <> Nil) Then
+     DSize := Validator^.Transfer(Data^, Nil,
+       vtDataSize);                                   { Add validator size }
+   If (DSize <> 0) Then DataSize := DSize             { Use validtor size }
+     Else DataSize := MaxLen + 1;                     { No validator use size }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TInputLine.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CInputLine;                         { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CInputLine)] = CInputLine;     { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  Valid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION TInputLine.Valid (Command: Word): Boolean;
+
+   FUNCTION AppendError (Validator: PValidator): Boolean;
+   BEGIN
+     AppendError := False;                            { Preset false }
+     If (Data <> Nil) Then
+       With Validator^ Do
+         If (Options AND voOnAppend <> 0) AND         { Check options }
+         (CurPos <> Length(Data^)) AND                { Exceeds max length }
+         NOT IsValidInput(Data^, True) Then Begin     { Check data valid }
+           Error;                                     { Call error }
+           AppendError := True;                       { Return true }
+         End;
+   END;
+
+BEGIN
+   Valid := Inherited Valid(Command);                 { Call ancestor }
+   If (Validator <> Nil) AND (Data <> Nil) AND        { Validator present }
+   (State AND sfDisabled = 0) Then                    { Not disabled }
+     If (Command = cmValid) Then                      { Valid command }
+       Valid := Validator^.Status = vsOk              { Validator result }
+       Else If (Command <> cmCancel) Then             { Not cancel command }
+         If AppendError(Validator) OR                 { Append any error }
+         NOT Validator^.Valid(Data^) Then Begin       { Check validator }
+           Select;                                    { Reselect view }
+           Valid := False;                            { Return false }
+         End;
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.Draw;
+VAR Color: Byte; X, L, R: Integer; S, T: String;
+BEGIN
+   If (State AND sfFocused = 0) Then Color := 1       { Not focused colour }
+     Else Color := 2;                                 { Focused colour }
+   If CanScroll(-1) Then WriteStr(0, 0, LeftArr, 4);  { Set left scroll mark }
+   If CanScroll(1) Then WriteStr(-(RawSize.X + 1 -
+     TextWidth(RightArr)), 0, RightArr, 4);           { Set right scroll mark }
+   If (Data <> Nil) Then S := Copy(Data^, FirstPos+1,
+    Length(Data^)-FirstPos) Else S := '';             { Fetch data string }
+   X := TextWidth(LeftArr);                           { left arrow width }
+   While (TextWidth(S) > ((RawSize.X+1)-X-TextWidth(
+     RightArr))) Do Delete(S, Length(S), 1);          { Cut to right length }
+   If (State AND sfFocused <> 0) Then Begin
+     L := SelStart - FirstPos;                        { Selected left end }
+     R := SelEnd - FirstPos;                          { Selected right end }
+     If (L < 0) Then L := 0;                          { Fix any negative }
+     If (R > Length(S)) Then R := Length(S);          { Fix to long case }
+     If (L > 0) Then Begin
+       T := Copy(S, 1, L);                            { Unhighlight bit }
+       WriteStr(-X, 0, T, Color);                     { Write string to screen }
+       X := X + TextWidth(T);                         { New x position }
+       Delete(S, 1, L);                               { Reduce string }
+     End;
+     If (L < R) Then Begin
+       T := Copy(S, 1, R-L);                          { Highlight bit }
+       WriteStr(-X, 0, T, 3);                         { Write string to screen }
+       X := X + TextWidth(T);                         { New x position }
+       Delete(S, 1, R-L);                             { Reduce string }
+     End;
+     If (Length(S) > 0) Then
+       WriteStr(-X, 0, S, Color);                     { Write string to screen }
+   End Else WriteStr(-X, 0, S, Color);                { Write string to screen }
+   Cursor.X := CurPos - FirstPos + 1;                 { Update cursor position }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  DrawbackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.DrawBackGround;
+BEGIN
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (HWindow <> 0) Then DestroyCaret;               { Destroy any caret }
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   If (HWindow <> 0) Then WinDestroyCursor(HWindow);  { Destroy any caret }
+   {$ENDIF}
+   Inherited DrawBackGround;                          { Call ancestor }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  DrawCursor -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 05Oct99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.DrawCursor;
+VAR I, X: Integer; S: String;
+BEGIN
+   If (State AND sfFocused <> 0) Then Begin           { Focused window }
+     X := TextWidth(LeftArr);                         { Preset x position }
+     I := 0;                                          { Preset cursor width }
+     If (Data <> Nil) Then Begin                      { Data pointer valid }
+       S := Copy(Data^, FirstPos+1, CurPos-FirstPos); { Copy the string }
+       X := X + TextWidth(S);                         { Calculate position }
+       If (State AND sfCursorIns <> 0) Then           { Check insert mode }
+         If ((CurPos+1) <= Length(Data^)) Then
+           I := TextWidth(Data^[CurPos+1])            { Insert caret width }
+           Else I := FontWidth;                       { At end use fontwidth }
+     End;
+     {$IFDEF OS_DOS}
+     If (State AND sfCursorIns <> 0) Then Begin       { Insert mode }
+       If ((CurPos+1) <= Length(Data^)) Then          { Not beyond end }
+         WriteStr(-X, 0, Data^[CurPos+1], 5)          { Create block cursor }
+         Else ClearArea(X, 0, X+I, FontHeight, Green);{ Line cursor }
+     End Else ClearArea(X, 0, X+I, FontHeight, Green);{ Line cursor }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     If (HWindow <> 0) Then Begin
+       CreateCaret(HWindow, 0, I, FontHeight);        { Create a craet }
+       SetCaretPos(X, 0);                             { Set caret position }
+       If (State AND sfCursorVis <> 0) Then
+         ShowCaret(HWindow);                          { Show the caret }
+     End;
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (HWindow <> 0) Then Begin
+       WinCreateCursor(HWindow, X, 0, 0, FontHeight,
+         CURSOR_FLASH, Nil);                          { Create a craet }
+       If (State AND sfCursorVis <> 0) Then
+         WinShowCursor(HWindow, True);                { Show the caret }
+     End;
+     {$ENDIF}
+   End;
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  SelectAll -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.SelectAll (Enable: Boolean);
+BEGIN
+   CurPos := 0;                                       { Cursor to start }
+   FirstPos := 0;                                     { First pos to start }
+   SelStart := 0;                                     { Selected at start }
+   If Enable AND (Data <> Nil) Then
+     SelEnd := Length(Data^) Else SelEnd := 0;        { Selected which end }
+   DrawView;                                          { Now redraw the view }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  SetValidator -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.SetValidator (AValid: PValidator);
+BEGIN
+   If (Validator <> Nil) Then Validator^.Free;        { Release validator }
+   Validator := AValid;                               { Set new validator }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  SetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.SetState (AState: Word; Enable: Boolean);
+BEGIN
+   Inherited SetState(AState, Enable);                { Call ancestor }
+   If (AState = sfSelected) OR ((AState = sfActive)
+   AND (State and sfSelected <> 0)) Then
+     SelectAll(Enable) Else                           { Call select all }
+     If (AState = sfFocused) Then DrawView;           { Redraw for focus }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  GetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.GetData (Var Rec);
+BEGIN
+   If (Data <> Nil) Then Begin                        { Data ptr valid }
+     If (Validator = Nil) OR (Validator^.Transfer(Data^,
+     @Rec, vtGetData) = 0) Then Begin                 { No validator/data }
+       FillChar(Rec, DataSize, #0);                   { Clear the data area }
+       Move(Data^, Rec, Length(Data^) + 1);           { Transfer our data }
+     End;
+   End Else FillChar(Rec, DataSize, #0);              { Clear the data area }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  SetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.SetData (Var Rec);
+{$IFDEF PPC_DELPHI3} VAR Buf: Array [0..256] Of Char; {$ENDIF}
+BEGIN
+   If (Data <> Nil) Then Begin                        { Data ptr valid }
+     If (Validator = Nil) OR (Validator^.Transfer(
+       Data^, @Rec, vtSetData) = 0) Then              { No validator/data }
+       {$IFDEF PPC_DELPHI3}                           { DELPHI3+ COMPILER }
+       Move(Rec, Buf, DataSize);                      { Fetch our data }
+       Move(Buf[1], Data^[1], Ord(Buf[0]));           { Tranfer string }
+       SetLength(Data^, Ord(Buf[0]));                 { Set string length }
+       {$ELSE}                                        { OTHER COMPILERS }
+       Move(Rec, Data^[0], DataSize);                 { Set our data }
+       {$ENDIF}
+   End;
+   SelectAll(True);                                   { Now select all }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { Implict TView.Store }
+   S.Write(MaxLen, 2);                                { Read max length }
+   S.Write(CurPos, 2);                                { Read cursor position }
+   S.Write(FirstPos, 2);                              { Read first position }
+   S.Write(SelStart, 2);                              { Read selected start }
+   S.Write(SelEnd, 2);                                { Read selected end }
+   S.WriteStr(Data);                                  { Write the data }
+   S.Put(Validator);                                  { Write any validator }
+END;
+
+{--TInputLine---------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TInputLine.HandleEvent (Var Event: TEvent);
+CONST PadKeys = [$47, $4B, $4D, $4F, $73, $74];
+VAR WasAppending: Boolean; ExtendBlock: Boolean; OldData: String;
+Delta, Anchor, OldCurPos, OldFirstPos, OldSelStart, OldSelEnd: Integer;
+
+   FUNCTION MouseDelta: Integer;
+   BEGIN
+     If (Event.Where.X <= RawOrigin.X+TextWidth(LeftArr))
+       Then MouseDelta := -1 Else                     { To left of text area }
+       If ((Event.Where.X-RawOrigin.X) >= RawSize.X -
+       TextWidth(RightArr)) Then MouseDelta := 1      { To right of text area }
+         Else MouseDelta := 0;                        { In area return 0 }
+   END;
+
+   FUNCTION MousePos: Integer;
+   VAR Mp, Tw, Pos: Integer; S: String;
+   BEGIN
+     Mp := Event.Where.X - RawOrigin.X;               { Mouse position }
+     If (Data <> Nil) Then S := Copy(Data^, FirstPos+1,
+       Length(Data^)-FirstPos) Else S := '';          { Text area string }
+     Tw := TextWidth(LeftArr);                        { Text width }
+     Pos := 0;                                        { Zero position }
+     While (Mp > Tw) AND (Pos <= Length(S)) Do Begin  { Still text to right }
+       Tw := Tw + TextWidth(S[Pos+1]);                { Add next character }
+       Inc(Pos);                                      { Next character }
+     End;
+     If (Pos > 0) Then Dec(Pos);
+     MousePos := FirstPos + Pos;                      { Return mouse position }
+   END;
+
+   PROCEDURE DeleteSelect;
+   BEGIN
+     If (SelStart <> SelEnd) Then Begin               { An area selected }
+       If (Data <> Nil) Then
+         Delete(Data^, SelStart+1, SelEnd-SelStart);  { Delete the text }
+       CurPos := SelStart;                            { Set cursor position }
+     End;
+   END;
+
+   PROCEDURE AdjustSelectBlock;
+   BEGIN
+     If (CurPos < Anchor) Then Begin                  { Selection backwards }
+       SelStart := CurPos;                            { Start of select }
+       SelEnd := Anchor;                              { End of select }
+     End Else Begin
+       SelStart := Anchor;                            { Start of select }
+       SelEnd := CurPos;                              { End of select }
+     End;
+   END;
+
+   PROCEDURE SaveState;
+   BEGIN
+     If (Validator <> Nil) Then Begin                 { Check for validator }
+       If (Data <> Nil) Then OldData := Data^;        { Hold data }
+       OldCurPos := CurPos;                           { Hold cursor position }
+       OldFirstPos := FirstPos;                       { Hold first position }
+       OldSelStart := SelStart;                       { Hold select start }
+       OldSelEnd := SelEnd;                           { Hold select end }
+       If (Data = Nil) Then WasAppending := True      { Invalid data ptr }
+         Else WasAppending := Length(Data^) = CurPos; { Hold appending state }
+     End;
+   END;
+
+   PROCEDURE RestoreState;
+   BEGIN
+     If (Validator <> Nil) Then Begin                 { Validator valid }
+       If (Data <> Nil) Then Data^ := OldData;        { Restore data }
+       CurPos := OldCurPos;                           { Restore cursor pos }
+       FirstPos := OldFirstPos;                       { Restore first pos }
+       SelStart := OldSelStart;                       { Restore select start }
+       SelEnd := OldSelEnd;                           { Restore select end }
+     End;
+   END;
+
+   FUNCTION CheckValid (NoAutoFill: Boolean): Boolean;
+   VAR OldLen: Integer; NewData: String;
+   BEGIN
+     If (Validator <> Nil) Then Begin                 { Validator valid }
+       CheckValid := False;                           { Preset false return }
+       If (Data <> Nil) Then OldLen := Length(Data^); { Hold old length }
+       If (Validator^.Options AND voOnAppend = 0) OR
+       (WasAppending AND (CurPos = OldLen)) Then Begin
+         If (Data <> Nil) Then NewData := Data^       { Hold current data }
+           Else NewData := '';                        { Set empty string }
+         If NOT Validator^.IsValidInput(NewData,
+         NoAutoFill) Then RestoreState Else Begin
+           If (Length(NewData) > MaxLen) Then         { Exceeds maximum }
+             {$IFDEF PPC_DELPHI3}                     { DELPHI 3+ COMPILER }
+             SetLength(NewData, MaxLen);              { Set string length }
+             {$ELSE}                                  { OTHER COMPILERS }
+             NewData[0] := Chr(MaxLen);               { Set string length }
+             {$ENDIF}
+           If (Data <> Nil) Then Data^ := NewData;    { Set data value }
+           If (Data <> Nil) AND (CurPos >= OldLen)    { Cursor beyond end }
+           AND (Length(Data^) > OldLen) Then          { Cursor beyond string }
+             CurPos := Length(Data^);                 { Set cursor position }
+           CheckValid := True;                        { Return true result }
+         End;
+       End Else Begin
+         CheckValid := True;                          { Preset true return }
+         If (CurPos = OldLen) AND (Data <> Nil) Then  { Lengths match }
+           If NOT Validator^.IsValidInput(Data^,
+           False) Then Begin                          { Check validator }
+             Validator^.Error;                        { Call error }
+             CheckValid := False;                     { Return false result }
+           End;
+       End;
+     End Else CheckValid := True;                     { No validator }
+   END;
+
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   If (State AND sfSelected <> 0) Then Begin          { View is selected }
+     Case Event.What Of
+       evNothing: Exit;                               { Speed up exit }
+       evMouseDown: Begin                             { Mouse down event }
+         Delta := MouseDelta;                         { Calc scroll value }
+         If CanScroll(Delta) Then Begin               { Can scroll }
+           Repeat
+             If CanScroll(Delta) Then Begin           { Still can scroll }
+               Inc(FirstPos, Delta);                  { Move start position }
+               DrawView;                              { Redraw the view }
+             End;
+           Until NOT MouseEvent(Event, evMouseAuto);  { Until no mouse auto }
+         End Else If Event.Double Then                { Double click }
+           SelectAll(True) Else Begin                 { Select whole text }
+             Anchor := MousePos;                      { Start of selection }
+             Repeat
+               {$IFDEF OS_DOS}                        { DOS/DPMI CODE }
+               If (Event.What = evMouseAuto)          { Mouse auto event }
+               {$ELSE}                                { WIN/NT/OS2 CODE }
+               If (Event.What = evMouseMove)          { Mouse move event }
+               {$ENDIF}
+               Then Begin
+                 Delta := MouseDelta;                 { New position }
+                 If CanScroll(Delta) Then             { If can scroll }
+                   Inc(FirstPos, Delta);
+               End;
+               CurPos := MousePos;                    { Set cursor position }
+               AdjustSelectBlock;                     { Adjust selected }
+               DrawView;                              { Redraw the view }
+             Until NOT MouseEvent(Event, evMouseMove
+               + evMouseAuto);                        { Until mouse released }
+           End;
+         ClearEvent(Event);                           { Clear the event }
+       End;
+       evKeyDown: Begin
+         SaveState;                                   { Save state of view }
+         Event.KeyCode := CtrlToArrow(Event.KeyCode); { Convert keycode }
+         If (Event.ScanCode IN PadKeys) AND
+         (GetShiftState AND $03 <> 0) Then Begin      { Mark selection active }
+           Event.CharCode := #0;                      { Clear char code }
+           If (CurPos = SelEnd) Then                  { Find if at end }
+             Anchor := SelStart Else                  { Anchor from start }
+             Anchor := SelEnd;                        { Anchor from end }
+             ExtendBlock := True;                     { Extended block true }
+         End Else ExtendBlock := False;               { No extended block }
+         Case Event.KeyCode Of
+           kbLeft: If (CurPos > 0) Then Dec(CurPos);  { Move cursor left }
+           kbRight: If (Data <> Nil) AND              { Move right cursor }
+           (CurPos < Length(Data^)) Then Begin        { Check not at end }
+             Inc(CurPos);                             { Move cursor }
+             CheckValid(True);                        { Check if valid }
+           End;
+           kbHome: CurPos := 0;                       { Move to line start }
+           kbEnd: Begin                               { Move to line end }
+             If (Data = Nil) Then CurPos := 0         { Invalid data ptr }
+               Else CurPos := Length(Data^);          { Set cursor position }
+             CheckValid(True);                        { Check if valid }
+           End;
+           kbBack: If (Data <> Nil) AND (CurPos > 0)  { Not at line start }
+           Then Begin
+             Delete(Data^, CurPos, 1);                { Backspace over char }
+             Dec(CurPos);                             { Move cursor back one }
+             If (FirstPos > 0) Then Dec(FirstPos);    { Move first position }
+             CheckValid(True);                        { Check if valid }
+           End;
+           kbDel: If (Data <> Nil) Then Begin         { Delete character }
+             If (SelStart = SelEnd) Then              { Select all on }
+               If (CurPos < Length(Data^)) Then Begin { Cursor not at end }
+                 SelStart := CurPos;                  { Set select start }
+                 SelEnd := CurPos + 1;                { Set select end }
+               End;
+             DeleteSelect;                            { Deselect selection }
+             CheckValid(True);                        { Check if valid }
+           End;
+           kbIns: SetState(sfCursorIns, State AND
+             sfCursorIns = 0);                        { Flip insert state }
+           Else Case Event.CharCode Of
+             ' '..#255: If (Data <> Nil) Then Begin   { Character key }
+               If (State AND sfCursorIns <> 0) Then
+                 Delete(Data^, CurPos + 1, 1) Else    { Overwrite character }
+                 DeleteSelect;                        { Deselect selected }
+               If CheckValid(True) Then Begin         { Check data valid }
+                 If (Length(Data^) < MaxLen) Then     { Must not exceed maxlen }
+                 Begin
+                   If (FirstPos > CurPos) Then
+                     FirstPos := CurPos;              { Advance first position }
+                   Inc(CurPos);                       { Increment cursor }
+                   Insert(Event.CharCode, Data^,
+                     CurPos);                         { Insert the character }
+                 End;
+                 CheckValid(False);                   { Check data valid }
+               End;
+             End;
+             ^Y: If (Data <> Nil) Then Begin          { Clear all data }
+                Data^ := '';                          { Set empty string }
+                CurPos := 0;                          { Cursor to start }
+             End;
+             Else Exit;                               { Unused key }
+           End
+         End;
+         If ExtendBlock Then AdjustSelectBlock        { Extended block }
+         Else Begin
+           SelStart := CurPos;                        { Set select start }
+           SelEnd := CurPos;                          { Set select end }
+         End;
+         If (FirstPos > CurPos) Then
+           FirstPos := CurPos;                        { Advance first pos }
+         If (Data <> Nil) Then OldData := Copy(Data^,
+           FirstPos+1, CurPos-FirstPos)               { Text area string }
+           Else OldData := '';                        { Empty string }
+         {$IFDEF OS_DOS}                              { DOS/DPMI CODE }
+         Delta := FontWidth;                          { Safety = 1 char }
+         {$ELSE}                                      { WIN/NT CODE }
+         Delta := 2*FontWidth;                        { Safety = 2 char }
+         {$ENDIF}
+         While (TextWidth(OldData) > ((RawSize.X+1)-Delta)
+         - TextWidth(LeftArr) - TextWidth(RightArr))  { Check text fits }
+         Do Begin
+           Inc(FirstPos);                             { Advance first pos }
+           OldData := Copy(Data^, FirstPos+1,
+             CurPos-FirstPos)                         { Text area string }
+         End;
+         DrawView;                                    { Redraw the view }
+         ClearEvent(Event);                           { Clear the event }
+       End;
+     End;
+   End;
+END;
+
+{***************************************************************************}
+{                     TInputLine OBJECT PRIVATE METHODS                     }
+{***************************************************************************}
+{--TInputLine---------------------------------------------------------------}
+{  CanScroll -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION TInputLine.CanScroll (Delta: Integer): Boolean;
+VAR S: String;
+BEGIN
+   If (Delta < 0) Then CanScroll := FirstPos > 0      { Check scroll left }
+     Else If (Delta > 0) Then Begin
+       If (Data = Nil) Then S := '' Else              { Data ptr invalid }
+         S := Copy(Data^, FirstPos+1, Length(Data^)
+          - FirstPos);                                { Fetch max string }
+       CanScroll := (TextWidth(S)) > (RawSize.X -
+         TextWidth(LeftArr) - TextWidth(RightArr));   { Check scroll right }
+     End Else CanScroll := False;                     { Zero so no scroll }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           TButton OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TButton------------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Apr98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TButton.Init (Var Bounds: TRect; ATitle: TTitleStr;
+  ACommand: Word; AFlags: Word);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   EventMask := EventMask OR evBroadcast;             { Handle broadcasts }
+   GOptions := GOptions OR goDrawFocus;               { Set new option mask }
+   Options := Options OR (ofSelectable + ofFirstClick
+     + ofPreProcess + ofPostProcess);                 { Set option flags }
+   If NOT CommandEnabled(ACommand) Then
+     State := State OR sfDisabled;                    { Check command state }
+   Flags := AFlags;                                   { Hold flags }
+   If (AFlags AND bfDefault <> 0) Then AmDefault := True
+     Else AmDefault := False;                         { Check if default }
+   Title := NewStr(ATitle);                           { Hold title string }
+   Command := ACommand;                               { Hold button command }
+   TabMask := TabMask OR (tmLeft + tmRight +
+     tmTab + tmShiftTab + tmUp + tmDown);             { Set tab masks }
+END;
+
+{--TButton------------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Apr98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TButton.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   Title := S.ReadStr;                                { Read title }
+   S.Read(Command, 2);                                { Read command }
+   S.Read(Flags, 1);                                  { Read flags }
+   S.Read(AmDefault, 1);                              { Read if default }
+   If NOT CommandEnabled(Command) Then                { Check command state }
+     State := State OR sfDisabled Else                { Command disabled }
+     State := State AND NOT sfDisabled;               { Command enabled }
+END;
+
+{--TButton------------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Apr98 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TButton.Done;
+BEGIN
+   If (Title <> Nil) Then DisposeStr(Title);          { Dispose title }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TButton------------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Apr98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TButton.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CButton;                            { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CButton)] = CButton;           { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Get button palette }
+END;
+
+{--TButton------------------------------------------------------------------}
+{  Press -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 29Apr98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TButton.Press;
+VAR E: TEvent;
+BEGIN
+   Message(Owner, evBroadcast, cmRecordHistory, Nil); { Message for history }
+   If (Flags AND bfBroadcast <> 0) Then               { Broadcasting button }
+     Message(Owner, evBroadcast, Command, @Self)      { Send message }
+     Else Begin
+       E.What := evCommand;                           { Command event }
+       E.Command := Command;                          { Set command value }
+       E.InfoPtr := @Self;                            { Pointer to self }
+       PutEvent(E);                                   { Put event on queue }
+     End;
+END;
+
+{--TButton------------------------------------------------------------------}
+{  DrawFocus -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TButton.DrawFocus;
+VAR B: Byte; I: Integer; Bc: Word; Db: TDrawBuffer;
+BEGIN
+   If DownFlag Then B := 7 Else B := 0;               { Shadow colour }
+   GraphRectangle(0, 0, RawSize.X, RawSize.Y, B);     { Draw backing shadow }
+   GraphRectangle(1, 1, RawSize.X-1, RawSize.Y-1, B); { Draw backing shadow }
+   If DownFlag Then B := 0 Else B := 15;              { Highlight colour }
+   GraphLine(0, RawSize.Y, 0, 0, B);
+   GraphLine(1, RawSize.Y-1, 1, 1, B);                { Left highlights }
+   GraphLine(0, 0, RawSize.X, 0, B);
+   GraphLine(1, 1, RawSize.X-1, 1, B);                { Top highlights }
+   If DownFlag Then B := 8 Else B := 7;               { Select backing }
+   If (State AND sfFocused <> 0) AND
+     (DownFlag = False) Then B := 14;                 { Show as focused }
+   GraphRectangle(2, 2, RawSize.X-2, RawSize.Y-2, B); { Draw first border }
+   GraphRectangle(3, 3, RawSize.X-3, RawSize.Y-3, B); { Draw next border }
+   If (State AND sfDisabled <> 0) Then                { Button disabled }
+     Bc := GetColor($0404) Else Begin                 { Disabled colour }
+       Bc := GetColor($0501);                         { Set normal colour }
+       If (State AND sfActive <> 0) Then              { Button is active }
+         If (State AND sfSelected <> 0) Then
+           Bc := GetColor($0703) Else                 { Set selected colour }
+             If AmDefault Then Bc := GetColor($0602); { Set is default colour }
+     End;
+   If (Title <> Nil) Then Begin                       { We have a title }
+     If (Flags AND bfLeftJust = 0) Then Begin         { Not left set title }
+       I := TextWidth(Title^);                        { Fetch title width }
+       I := (RawSize.X - I) DIV 2;                    { Centre in button }
+     End Else I := FontWidth;                         { Left edge of button }
+     MoveCStr(Db, Title^, Bc);                        { Move title to buffer }
+     GOptions := GOptions OR goGraphView;             { Graphics co-ords mode }
+     WriteLine(I, FontHeight DIV 2, CStrLen(Title^),
+       1, Db);                                        { Write the title }
+     GOptions := GOptions AND NOT goGraphView;        { Return to normal mode }
+   End;
+END;
+
+{--TButton------------------------------------------------------------------}
+{  DrawState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TButton.DrawState (Down: Boolean);
+BEGIN
+   DownFlag := Down;                                  { Set down flag }
+   SetDrawMask(vdFocus);                              { Set focus mask }
+   DrawView;                                          { Redraw the view }
+END;
+
+{--TButton------------------------------------------------------------------}
+{  MakeDefault -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TButton.MakeDefault (Enable: Boolean);
+VAR C: Word;
+BEGIN
+   If (Flags AND bfDefault=0) Then Begin              { Not default }
+     If Enable Then C := cmGrabDefault
+       Else C := cmReleaseDefault;                    { Change default }
+     Message(Owner, evBroadcast, C, @Self);           { Message to owner }
+     AmDefault := Enable;                             { Set default flag }
+     DrawView;                                        { Now redraw button }
+   End;
+END;
+
+{--TButton------------------------------------------------------------------}
+{  SetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Oct99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TButton.SetState (AState: Word; Enable: Boolean);
+BEGIN
+   Inherited SetState(AState, Enable);                { Call ancestor }
+   If (AState AND (sfSelected + sfActive) <> 0)       { Changing select }
+     Then DrawView;                                   { Redraw required }
+   If (AState AND sfFocused <> 0) Then
+     MakeDefault(Enable);                             { Check for default }
+END;
+
+{--TButton------------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TButton.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { Implict TView.Store }
+   S.WriteStr(Title);                                 { Store title string }
+   S.Write(Command, 2);                               { Store command }
+   S.Write(Flags, 1);                                 { Store flags }
+   S.Write(AmDefault, 1);                             { Store default flag }
+END;
+
+{--TButton------------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 05Sep99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TButton.HandleEvent (Var Event: TEvent);
+VAR Down: Boolean; C: Char; ButRect: TRect;
+BEGIN
+   ButRect.A := RawOrigin;                            { Get origin point }
+   ButRect.B.X := RawOrigin.X + RawSize.X;            { Calc right side }
+   ButRect.B.Y := RawOrigin.Y + RawSize.Y;            { Calc bottom }
+   If (Event.What = evMouseDown) Then Begin           { Mouse down event }
+     If NOT MouseInView(Event.Where) Then Begin       { If point not in view }
+       ClearEvent(Event);                             { Clear the event }
+       Exit;                                          { Speed up exit }
+     End;
+   End;
+   If (Flags AND bfGrabFocus <> 0) Then               { Check focus grab }
+     Inherited HandleEvent(Event);                    { Call ancestor }
+   Case Event.What Of
+     evNothing: Exit;                                 { Speed up exit }
+     evMouseDown: Begin
+       If (State AND sfDisabled = 0) Then Begin       { Button not disabled }
+         Down := False;                               { Clear down flag }
+         Repeat
+           If (Down <> ButRect.Contains(Event.Where)) { State has changed }
+           Then Begin
+             Down := NOT Down;                        { Invert down flag }
+             DrawState(Down);                         { Redraw button }
+           End;
+         Until NOT MouseEvent(Event, evMouseMove);    { Wait for mouse move }
+         If Down Then Begin                           { Button is down }
+           Press;                                     { Send out command }
+           DrawState(False);                          { Draw button up }
+         End;
+       End;
+       ClearEvent(Event);                             { Event was handled }
+     End;
+     evKeyDown: Begin
+       If (Title <> Nil) Then C := HotKey(Title^)     { Key title hotkey }
+         Else C := #0;                                { Invalid title }
+       If (Event.KeyCode = GetAltCode(C)) OR          { Alt char }
+       (Owner^.Phase = phPostProcess) AND (C <> #0)
+       AND (Upcase(Event.CharCode) = C) OR            { Matches hotkey }
+       (State AND sfFocused <> 0) AND                 { View focused }
+       ((Event.CharCode = ' ') OR                     { Space bar }
+       (Event.KeyCode=kbEnter)) Then Begin            { Enter key }
+         DrawState(True);                             { Draw button down }
+         Press;                                       { Send out command }
+         ClearEvent(Event);                           { Clear the event }
+         DrawState(False);                            { Draw button up }
+       End;
+     End;
+     evBroadcast:
+       Case Event.Command of
+         cmDefault: If AmDefault AND                  { Default command }
+         (State AND sfDisabled = 0) Then Begin        { Button enabled }
+             Press;                                   { Send out command }
+             ClearEvent(Event);                       { Clear the event }
+         End;
+         cmGrabDefault, cmReleaseDefault:             { Grab and release cmd }
+           If (Flags AND bfDefault <> 0) Then Begin   { Change button state }
+             AmDefault := Event.Command = cmReleaseDefault;
+             DrawView;                                { Redraw the view }
+           End;
+         cmCommandSetChanged: Begin                   { Command set changed }
+           SetState(sfDisabled, NOT
+             CommandEnabled(Command));                { Set button state }
+            DrawView;                                 { Redraw the view }
+         End;
+       End;
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           TCluster OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+CONST TvClusterClassName = 'TVCLUSTER';
+
+{--TCluster-----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TCluster.Init (Var Bounds: TRect; AStrings: PSItem);
+VAR I: Integer; P: PSItem;
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   GOptions := GOptions OR goDrawFocus;               { Draw focus view }
+   Options := Options OR (ofSelectable + ofFirstClick
+     + ofPreProcess + ofPostProcess + ofVersion20);   { Set option masks }
+   I := 0;                                            { Zero string count }
+   P := AStrings;                                     { First item }
+   While (P <> Nil) Do Begin
+     Inc(I);                                          { Count 1 item }
+     P := P^.Next;                                    { Move to next item }
+   End;
+   Strings.Init(I, 0);                                { Create collection }
+   While (AStrings <> Nil) Do Begin
+     P := AStrings;                                   { Transfer item ptr }
+     Strings.AtInsert(Strings.Count, AStrings^.Value);{ Insert string }
+     AStrings := AStrings^.Next;                      { Move to next item }
+     Dispose(P);                                      { Dispose prior item }
+   End;
+   EnableMask := $FFFFFFFF;                           { Enable bit masks }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TCluster.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(Value, 4);                                  { Read value }
+   S.Read(Sel, 2);                                    { Read select item }
+   If ((Options AND ofVersion) >= ofVersion20)        { Version 2 TV view }
+   Then S.Read(EnableMask, 4) Else Begin              { Read enable masks }
+     EnableMask := $FFFFFFFF;                         { Enable all masks }
+     Options := Options OR ofVersion20;               { Set version 2 mask }
+   End;
+   If (Options AND ofGFVModeView <> 0) Then           { GFV mode view check }
+     S.Read(Id, 2);                                   { Read view id }
+   Strings.Load(S);                                   { Load string data }
+   SetButtonState(0, True);                           { Set button state }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TCluster.Done;
+VAR I: Integer;
+BEGIN
+   {$IFNDEF OS_DOS}                                   { WIN/NT/OS2 CODE }
+   If (WndHandles <> Nil) Then Begin                  { Handles valid }
+     For I := 1 To Strings.Count Do                   { For each entry }
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+       DestroyWindow(WndHandles^[I-1]);               { Destroy button views }
+       {$ELSE}                                        { OS2 CODE }
+       WinDestroyWindow(WndHandles^[I-1]);            { Destroy button views }
+       {$ENDIF}
+     FreeMem(WndHandles, Strings.Count*SizeOf(HWnd)); { Release memory }
+   End;
+   {$ENDIF}
+   Strings.Done;                                      { Dispose of strings }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  DataSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.DataSize: Word;
+BEGIN
+   DataSize := SizeOf(Word);                          { Exchanges a word }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  GetHelpCtx -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.GetHelpCtx: Word;
+BEGIN
+   If (HelpCtx = hcNoContext) Then                    { View has no help }
+     GetHelpCtx := hcNoContext Else                   { No help context }
+     GetHelpCtx := HelpCtx + Sel;                     { Help of selected }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CCluster;                           { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CCluster)] = CCluster;         { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Cluster palette }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  Mark -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04May98 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.Mark (Item: Integer): Boolean;
+BEGIN
+   Mark := False;                                     { Default false }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  MultiMark -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04May98 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.MultiMark (Item: Integer): Byte;
+BEGIN
+   MultiMark := Byte(Mark(Item) = True);              { Return multi mark }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  ButtonState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.ButtonState (Item: Integer): Boolean;
+BEGIN
+   If (Item > 31) Then ButtonState := False Else      { Impossible item }
+     ButtonState := ((1 SHL Item) AND EnableMask)<>0; { Return true/false }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  DrawFocus -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Jul99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.DrawFocus;
+BEGIN
+   {$IFNDEF OS_DOS}                                   { WIN/NT/OS2 CODE }
+   If (WndHandles <> Nil) Then                        { Valid window handles }
+     If (State AND sfFocused <> 0) Then Begin         { View is focused }
+       If (Sel >= 0) AND (Sel < Strings.Count) Then
+         {$IFDEF OS_WINDOWS}                          { WIN/NT CODE }
+         SetFocus(WndHandles^[Sel])                   { Focus selected view }
+           Else SetFocus(AppWindow);                  { Focus owner }
+         {$ELSE}                                      { OS2 CODE }
+         WinSetFocus(HWND_DESKTOP, WndHandles^[Sel])  { Focus selected view }
+           Else WinSetFocus(HWND_DESKTOP, HWindow);   { Focus owner }
+         {$ENDIF}
+     End Else
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+       SetFocus(AppWindow);                           { Focus owner }
+       {$ELSE}                                        { OS2 CODE }
+       WinSetFocus(HWND_DESKTOP, AppWindow);          { Focus owner }
+       {$ENDIF}
+   {$ENDIF}
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  Press -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.Press (Item: Integer);
+VAR P: PView;
+BEGIN
+   P := TopView;
+   If (Id <> 0) AND (P <> Nil) Then NewMessage(P,
+     evCommand, cmIdCommunicate, Id, Value, @Self);   { Send new message }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  MovedTo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.MovedTo (Item: Integer);
+BEGIN                                                 { Abstract method }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  SetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.SetState (AState: Word; Enable: Boolean);
+BEGIN
+   Inherited SetState(AState, Enable);                { Call ancestor }
+   If (AState AND sfFocused <> 0) Then Begin
+     SetDrawMask(vdFocus OR vdInner);                 { Set redraw masks }
+     DrawView;                                        { Redraw masked areas }
+   End;
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  DrawMultiBox -> Platforms DOS/DPMI/WIN/NT - Updated 05Jun98 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.DrawMultiBox (Const Icon, Marker: String);
+VAR I, J, K, Cur, Col: Integer; CNorm, CSel, CDis, Color: Word; B: TDrawBuffer;
+    Tb, SCOff: Byte;
+{$IFNDEF OS_DOS} S: String; P: PString; Q: PChar; {$ENDIF}
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+   CNorm := GetColor($0301);                          { Normal colour }
+   CSel := GetColor($0402);                           { Selected colour }
+   CDis := GetColor($0505);                           { Disabled colour }
+   If (Options AND ofFramed <>0) OR                   { Normal frame }
+   (GOptions AND goThickFramed <>0) Then              { Thick frame }
+     K := 1 Else  K := 0;                             { Select offset }
+   For I := 0 To Size.Y-K-K-1 Do Begin                { For each line }
+     MoveChar(B, ' ', Byte(CNorm), Size.X-K-K);       { Fill buffer }
+     For J := 0 To (Strings.Count - 1) DIV Size.Y + 1
+     Do Begin
+       Cur := J*Size.Y + I;                           { Current line }
+       If (Cur < Strings.Count) Then Begin
+         Col := Column(Cur);                          { Calc column }
+         If (Col + CStrLen(PString(Strings.At(Cur))^)+
+         5 < Sizeof(TDrawBuffer) DIV SizeOf(Word))
+         AND (Col < Size.X-K-K) Then Begin            { Text fits in column }
+           If NOT ButtonState(Cur) Then
+             Color := CDis Else If (Cur = Sel) AND    { Disabled colour }
+             (State and sfFocused <> 0) Then
+               Color := CSel Else                     { Selected colour }
+               Color := CNorm;                        { Normal colour }
+           MoveChar(B[Col], ' ', Byte(Color),
+             Size.X-K-K-Col);                         { Set this colour }
+           MoveStr(B[Col], Icon, Byte(Color));        { Transfer icon string }
+           WordRec(B[Col+2]).Lo := Byte(Marker[
+             MultiMark(Cur) + 1]);                    { Transfer marker }
+           MoveCStr(B[Col+5], PString(Strings.At(
+             Cur))^, Color);                          { Transfer item string }
+           If ShowMarkers AND (State AND sfFocused <> 0)
+           AND (Cur = Sel) Then Begin                 { Current is selected }
+             WordRec(B[Col]).Lo := Byte(SpecialChars[0]);
+              WordRec(B[Column(Cur+Size.Y)-1]).Lo
+                := Byte(SpecialChars[1]);             { Set special character }
+           End;
+         End;
+       End;
+     End;
+     WriteBuf(K, K+I, Size.X-K-K, 1, B);              { Write buffer }
+   End;
+   {$ELSE}                                            { WIN/NT/OS2 CODE }
+   If (WndHandles <> Nil) Then Begin                  { Valid window handles }
+     For I := 1 To Strings.Count Do Begin             { For each window }
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+       Tb := GetWindowText(WndHandles^[I-1], @S[1],
+         255);                                        { Get window text }
+       {$ELSE}                                        { OS2 CODE }
+       Tb := WinQueryWindowText(WndHandles^[I-1], 255,
+         @S[1]);                                      { Get window text }
+       {$ENDIF}
+       {$IFDEF PPC_DELPHI3}                           { DELPHI3+ COMPILER }
+       SetLength(S, Tb);                              { Set string length }
+       {$ELSE}                                        { OTHER COMPILERS }
+       S[0] := Chr(Tb);                               { Set string length }
+       {$ENDIF}
+       P := Strings.At(I-1);                          { Cluster strings }
+       If (P <> Nil) AND (P^ <> S) Then Begin         { Something changed }
+         S := P^ + #0;                                { Transfer string }
+         {$IFDEF OS_WINDOWS}                          { WIN/NT CODE }
+         SetWindowText(WndHandles^[I-1], @S[1]);      { Set new window text }
+         {$ELSE}                                      { OS2 CODE }
+         WinSetWindowText(WndHandles^[I-1], @S[1]);   { Set new window text }
+         {$ENDIF}
+       End;
+       If Mark(I-1) Then                              { If item marked }
+         {$IFDEF OS_WINDOWS}                          { WIN/NT CODE }
+         SendMessage(WndHandles^[I-1], bm_SetCheck,
+           1, 0) Else                                 { Check the box }
+         SendMessage(WndHandles^[I-1], bm_SetCheck,
+           0, 0);                                     { Uncheck the box }
+         {$ELSE}                                      { OS2 CODE }
+         WinSendMsg(WndHandles^[I-1], bm_SetCheck,
+           1, 0) Else                                 { Check the box }
+         WinSendMsg(WndHandles^[I-1], bm_SetCheck,
+           0, 0);                                     { Uncheck the box }
+         {$ENDIF}
+     End;
+   End;
+   {$ENDIF}
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  DrawBox -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.DrawBox (Const Icon: String; Marker: Char);
+BEGIN
+   DrawMultiBox(Icon, ' '+Marker);                    { Call draw routine }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  SetButtonState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.SetButtonState (AMask: Longint; Enable: Boolean);
+VAR I: Integer; M: Longint;
+BEGIN
+   If Enable Then EnableMask := EnableMask OR AMask   { Set enable bit mask }
+     Else EnableMask := EnableMask AND NOT AMask;     { Disable bit mask }
+   If (Strings.Count <= 32) Then Begin                { Valid string number }
+     M := 1;                                          { Preset bit masks }
+     For I := 1 To Strings.Count Do Begin             { For each item string }
+       If ((M AND EnableMask) <> 0) Then Begin        { Bit enabled }
+         Options := Options OR ofSelectable;          { Set selectable option }
+         Exit;                                        { Now exit }
+       End;
+       M := M SHL 1;                                  { Create newbit mask }
+     End;
+     Options := Options AND NOT ofSelectable;         { Make not selectable }
+   End;
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  GetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04May98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.GetData (Var Rec);
+BEGIN
+   Word(Rec) := Value;                                { Return current value }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  SetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04May98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.SetData (Var Rec);
+BEGIN
+   Value := Word(Rec);                                { Set current value }
+   SetDrawMask(vdFocus OR vdInner);                   { Set redraw mask }
+   DrawView;                                          { Redraw masked areas }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { TView.Store called }
+   If ((Options AND ofVersion) >= ofVersion20)        { Version 2 TV view }
+   Then Begin
+     S.Write(Value, SizeOf(LongInt));                 { Write value }
+     S.Write(Sel, SizeOf(Sel));                       { Write select item }
+     S.Write(EnableMask, SizeOf(EnableMask));         { Write enable masks }
+   End Else Begin
+     S.Write(Value, SizeOf(Word));                    { Write value }
+     S.Write(Sel, SizeOf(Sel));                       { Write select item }
+   End;
+   If (Options AND ofGFVModeView <> 0) Then           { GFV mode view check }
+     S.Write(Id, SizeOf(Id));                         { Write new id value }
+   Strings.Store(S);                                  { Store strings }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Jun98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.HandleEvent (Var Event: TEvent);
+VAR C: Char; I, J, S, Vh: Integer; Key: Word; Mouse: TPoint; Ts: PString;
+
+   PROCEDURE MoveSel;
+   BEGIN
+     If (I <= Strings.Count) Then Begin
+       Sel := S;                                      { Set selected item }
+       MovedTo(Sel);                                  { Move to selected }
+       SetDrawMask(vdInner OR vdFocus);               { Set draw masks }
+       DrawView;                                      { Now draw changes }
+     End;
+   END;
+
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   If ((Options AND ofSelectable) = 0) Then Exit;     { Check selectable }
+   If (Event.What = evMouseDown) Then Begin           { MOUSE EVENT }
+     MakeLocal(Event.Where, Mouse);                   { Make point local }
+     I := FindSel(Mouse);                             { Find selected item }
+     If (I <> -1) Then                                { Check in view }
+       If ButtonState(I) Then Sel := I;               { If enabled select }
+     SetDrawMask(vdFocus OR vdInner);                 { Set draw mask }
+     DrawView;                                        { Now draw changes }
+     Repeat
+       MakeLocal(Event.Where, Mouse);                 { Make point local }
+     Until NOT MouseEvent(Event, evMouseMove);        { Wait for mouse up }
+     MakeLocal(Event.Where, Mouse);                   { Make point local }
+     If (FindSel(Mouse) = Sel) AND ButtonState(Sel)   { If valid/selected }
+     Then Begin
+       Press(Sel);                                    { Call pressed }
+       SetDrawMask(vdFocus OR vdInner);               { Set draw mask }
+       DrawView;                                      { Now draw changes }
+     End;
+     ClearEvent(Event);                               { Event was handled }
+   End Else If (Event.What = evKeyDown) Then Begin    { KEY EVENT }
+     If (Options AND ofFramed <> 0) OR                { Normal frame }
+     (GOptions AND goThickFramed <> 0) Then           { Thick frame }
+       J := 1 Else J := 0;                            { Adjust value }
+     Vh := Size.Y - J - J;                            { View height }
+     S := Sel;                                        { Hold current item }
+     Key := CtrlToArrow(Event.KeyCode);               { Convert keystroke }
+     Case Key Of
+       kbUp, kbDown, kbRight, kbLeft:
+       If (State AND sfFocused <> 0) Then Begin       { Focused key event }
+         I := 0;                                      { Zero process count }
+         Repeat
+           Inc(I);                                    { Inc process count }
+           Case Key Of
+             kbUp: Dec(S);                            { Next item up }
+             kbDown: Inc(S);                          { Next item down }
+             kbRight: Begin                           { Next column across }
+               Inc(S, Vh);                            { Move to next column }
+               If (S >= Strings.Count) Then           { No next column check }
+                 S := (S+1) MOD Vh;                   { Move to last column }
+             End;
+             kbLeft: Begin                            { Prior column across }
+               Dec(S, Vh);                            { Move to prior column }
+               If (S < 0) Then  S := ((Strings.Count +
+                 Vh - 1) DIV Vh) * Vh + S - 1;        { No prior column check }
+             End;
+           End;
+           If (S >= Strings.Count) Then S := 0;       { Roll up to top }
+           If (S < 0) Then S := Strings.Count - 1;    { Roll down to bottom }
+         Until ButtonState(S) OR (I > Strings.Count); { Repeat until select }
+         MoveSel;                                     { Move to selected }
+         ClearEvent(Event);                           { Event was handled }
+       End;
+       Else Begin                                     { Not an arrow key }
+         For I := 0 To Strings.Count-1 Do Begin       { Scan each item }
+           Ts := Strings.At(I);                       { Fetch string pointer }
+           If (Ts <> Nil) Then C := HotKey(Ts^)       { Check for hotkey }
+             Else C := #0;                            { No valid string }
+           If (GetAltCode(C) = Event.KeyCode) OR      { Hot key for item }
+           (((Owner^.Phase = phPostProcess) OR        { Owner in post process }
+           (State AND sfFocused <> 0)) AND (C <> #0)  { Non zero hotkey }
+           AND (UpCase(Event.CharCode) = C))          { Matches current key }
+           Then Begin
+             If ButtonState(I) Then Begin             { Check mask enabled }
+               If Focus Then Begin                    { Check view focus }
+                 Sel := I;                            { Set selected }
+                 MovedTo(Sel);                        { Move to selected }
+                 Press(Sel);                          { Call pressed }
+                 SetDrawMask(vdFocus OR vdInner);     { Set draw mask }
+                 DrawView;                            { Now draw changes }
+               End;
+               ClearEvent(Event);                     { Event was handled }
+             End;
+             Exit;                                    { Now exit }
+           End;
+         End;
+         {$IFDEF OS_DOS}                              { DOS/DPMI CODE }
+         If (Event.CharCode = ' ') AND                { Spacebar key }
+         (State AND sfFocused <> 0) AND               { Check focused view }
+         ButtonState(Sel) Then Begin                  { Check item enabled }
+           Press(Sel);                                { Call pressed }
+           SetDrawMask(vdFocus OR vdInner);           { Set draw mask }
+           DrawView;                                  { Now draw changes }
+           ClearEvent(Event);                         { Event was handled }
+         End;
+         {$ENDIF}
+       End;
+     End;
+   End;
+END;
+
+{$IFNDEF OS_DOS}                                      { WIN/NT/OS2 CODE }
+{***************************************************************************}
+{                  TCLuster OBJECT WIN/NT/OS2 ONLY METHODS                  }
+{***************************************************************************}
+
+{--TCluster-----------------------------------------------------------------}
+{  GetClassName -> Platforms WIN/NT/OS2 - Updated 03Jun98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.GetClassName: String;
+BEGIN
+   GetClassName := TvClusterClassName;                { Cluster class name }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  SubClassAttr -> Platforms WIN/NT/OS2 - Updated 02Jun98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.SubClassAttr: LongInt;
+VAR Li: LongInt;
+BEGIN
+   If (State AND sfVisible = 0) Then Li := 0          { View not visible }
+     Else Li := ws_Visible;                           { View is visible }
+   If (State AND sfDisabled <> 0) Then                { Check disabled flag }
+     Li := Li OR ws_Disabled;                         { Set disabled flag }
+   Li := Li OR ws_ClipChildren OR ws_ClipSiblings;    { Must have these }
+   SubClassAttr := Li;                                { Return attributes }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  GetMsgHandler -> Platforms WIN/NT/OS2 - Updated 02Jun98 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.GetMsgHandler: Pointer;
+BEGIN
+   GetMsgHandler := @TvClusterMsgHandler;             { Cluster msg handler }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  CreateWindowNow -> Platforms WIN/NT - Updated 28May98 LdB                }
+{---------------------------------------------------------------------------}
+PROCEDURE TCluster.CreateWindowNow (CmdShow: Integer);
+VAR I, J, L: Integer; Li: LongInt; Ct: String; Ts: PString; P: PChar; Wnd: HWnd;
+BEGIN
+   If (HWindow = 0) Then Begin                        { Window not created }
+     Inherited CreateWindowNow (CmdShow);             { Call ancestor }
+     If (HWindow <> 0) Then Begin                     { Window now created }
+       GetMem(WndHandles, Strings.Count*SizeOf(HWnd));{ Allocate memory }
+       For I := 1 To Strings.Count Do Begin
+         L := (I-1) * FontHeight;                     { Height of each line }
+         Ts := Strings.At(I-1);                       { Fetch string pointer }
+         If (Ts <> Nil) Then Ct := Ts^ Else Ct := ''; { Get string text }
+         Ct := Ct + #0;                               { Make asciiz }
+         J := Pos('~', Ct);                           { Check for tilde }
+         If (J <> 0) Then Ct[J] := '&';               { Sub 1st tilde }
+         Repeat
+           J := Pos('~', Ct);                         { Check for tilde }
+           If (J <> 0) Then System.Delete(Ct, J, 1);  { Remove the tilde }
+         Until (J = 0);                               { Remove all tildes }
+         If (Ct <> #0) Then Begin                     { Check for empty }
+           GetMem(P, Length(Ct));                     { Allocate memory }
+           Move(Ct[1], P^, Length(Ct));               { Move string data }
+         End Else P := Nil;                           { Return nil ptr }
+         {$IFDEF OS_WINDOWS}
+         If (Options AND ofFramed <> 0) OR            { Normal frame }
+         (GOptions AND goThickFramed <> 0) Then       { Thick frame }
+           Wnd := CreateWindowEx(0, 'BUTTON', P,
+             SubClassAttr OR ws_Child OR ws_Visible, FontWidth,
+             L+FontHeight, RawSize.X-2*FontWidth+1,
+             FontHeight, HWindow, cmTvClusterButton,
+             HInstance, Nil) Else                     { Create window }
+           Wnd := CreateWindowEx(0, 'BUTTON', P,
+             SubClassAttr OR ws_Child OR ws_Visible, 0, L,
+             RawSize.X+1, FontHeight, HWindow,
+             cmTvClusterButton, HInstance, Nil);      { Create window }
+         If (Wnd <> 0) Then Begin                     { Window created ok }
+           {$IFDEF PPC_FPC}
+           Windows.SendMessage(Wnd, WM_SetFont,
+             DefGFVFont, 1);                          { Set font style }
+           {$ELSE}
+           WinProcs.SendMessage(Wnd, WM_SetFont,
+             DefGFVFont, 1);                          { Set font style }
+           {$ENDIF}
+           Li := LongInt(@Self);                      { Address of  self }
+           {$IFDEF BIT_16}                            { 16 BIT CODE }
+           SetProp(Wnd, ViewSeg,
+             Li AND $FFFF0000 SHR 16);                { Set seg property }
+           SetProp(Wnd, ViewOfs,
+             Li AND $0000FFFF);                       { Set ofs propertry }
+           {$ENDIF}
+           {$IFDEF BIT_32}                            { 32 BIT CODE }
+           SetProp(Wnd, ViewPtr, Li);                 { Set view property }
+           {$ENDIF}
+           If (CmdShow <> 0) Then
+             ShowWindow(Wnd, cmdShow);                { Execute show cmd }
+           UpdateWindow(Wnd);                         { Update the window }
+           BringWindowToTop(Wnd);                     { Bring window to top }
+         End;
+         WndHandles^[I-1] := Wnd;                     { Hold the handle }
+         If  Mark(I-1) Then                           { If item marked }
+           SendMessage(WndHandles^[I-1], bm_SetCheck,
+             1, 0) Else                               { Check the item }
+           SendMessage(WndHandles^[I-1], bm_SetCheck,
+             0, 0);                                   { Uncheck the item }
+         {$ENDIF}
+       End;
+     End;
+   End;
+END;
+{$ENDIF}
+
+{***************************************************************************}
+{                      TCluster OBJECT PRIVATE METHODS                      }
+{***************************************************************************}
+
+{--TCluster-----------------------------------------------------------------}
+{  FindSel -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.FindSel (P: TPoint): Integer;
+VAR I, J, S, Vh: Integer; R: TRect;
+BEGIN
+   GetExtent(R);                                      { Get view extents }
+   If R.Contains(P) Then Begin                        { Point in view }
+     If (Options AND ofFramed <> 0) OR                { Normal frame }
+     (GOptions AND goThickFramed <> 0) Then           { Thick frame }
+       J := 1 Else J := 0;                            { Adjust value }
+     Vh := Size.Y - J - J;                            { View height }
+     I := 0;                                          { Preset zero value }
+     While (P.X >= Column(I+Vh)) Do Inc(I, Vh);       { Inc view size }
+     S := I + P.Y - J;                                { Line to select }
+     If ((S >= 0) AND (S < Strings.Count))            { Valid selection }
+       Then FindSel := S Else FindSel := -1;          { Return selected item }
+   End Else FindSel := -1;                            { Point outside view }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  Row -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.Row (Item: Integer): Integer;
+BEGIN
+   If (Options AND ofFramed <> 0) OR                  { Normal frame }
+  (GOptions AND goThickFramed <> 0) Then              { Thick frame }
+    Row := Item MOD (Size.Y - 2) Else                 { Allow for frames }
+    Row := Item MOD Size.Y;                           { Normal mod value }
+END;
+
+{--TCluster-----------------------------------------------------------------}
+{  Column -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 03Jun98 LdB            }
+{---------------------------------------------------------------------------}
+FUNCTION TCluster.Column (Item: Integer): Integer;
+VAR I, J, Col, Width, L, Vh: Integer; Ts: PString;
+BEGIN
+   If (Options AND ofFramed <> 0) OR                  { Normal frame }
+   (GOptions AND goThickFramed <> 0) Then             { Thick frame }
+     J := 1 Else J := 0;                              { Adjust value }
+   Vh := Size.Y - J - J;                              { Vertical size }
+   If (Item >= Vh) Then Begin                         { Valid selection }
+     Width := 0;                                      { Zero width }
+     Col := -6;                                       { Start column at -6 }
+     For I := 0 To Item Do Begin                      { For each item }
+       If (I MOD Vh = 0) Then Begin                   { Start next column }
+         Inc(Col, Width + 6);                         { Add column width }
+         Width := 0;                                  { Zero width }
+       End;
+       If (I < Strings.Count) Then Begin              { Valid string }
+         Ts := Strings.At(I);                         { Transfer string }
+         If (Ts <> Nil) Then L := CStrLen(Ts^)        { Length of string }
+           Else L := 0;                               { No string }
+       End;
+       If (L > Width) Then Width := L;                { Hold longest string }
+     End;
+     Column := Col;                                   { Return column }
+   End Else Column := 0;                              { Outside select area }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TRadioButtons OBJECT METHODS                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TRadioButtons------------------------------------------------------------}
+{  Mark -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION TRadioButtons.Mark (Item: Integer): Boolean;
+BEGIN
+   Mark := Item = Value;                              { True if item = value }
+END;
+
+{--TRadioButtons------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04May98 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TRadioButtons.DrawFocus;
+CONST Button = ' ( ) ';
+BEGIN
+   Inherited DrawFocus;
+   DrawMultiBox(Button, #32#7);                       { Redraw the text }
+END;
+
+{--TRadioButtons------------------------------------------------------------}
+{  Press -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TRadioButtons.Press (Item: Integer);
+BEGIN
+   Value := Item;                                     { Set value field }
+   Inherited Press(Item);                             { Call ancestor }
+END;
+
+{--TRadioButtons------------------------------------------------------------}
+{  MovedTo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04May98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TRadioButtons.MovedTo (Item: Integer);
+BEGIN
+   Value := Item;                                     { Set value to item }
+   If (Id <> 0) Then NewMessage(Owner, evCommand,
+     cmIdCommunicate, Id, Value, @Self);              { Send new message }
+END;
+
+{--TRadioButtons------------------------------------------------------------}
+{  SetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04May98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TRadioButtons.SetData (Var Rec);
+BEGIN
+   Sel := Integer(Rec);                               { Set selection }
+   Inherited SetData(Rec);                            { Call ancestor }
+END;
+
+{$IFNDEF OS_DOS}                                      { WIN/NT CODE }
+{***************************************************************************}
+{             TRadioButtons OBJECT WIN/NT/OS2 ONLY METHODS                  }
+{***************************************************************************}
+
+{--TRadioButtons------------------------------------------------------------}
+{  SubClassAttr -> Platforms WIN/NT/OS2 - Updated 20May98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TRadioButtons.SubClassAttr: LongInt;
+BEGIN
+   SubClassAttr := Inherited SubClassAttr OR
+     bs_RadioButton;                                  { Radio button }
+END;
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TCheckBoxes OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TCheckBoxes--------------------------------------------------------------}
+{  Mark -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION TCheckBoxes.Mark(Item: Integer): Boolean;
+BEGIN
+   If (Value AND (1 SHL Item) <> 0) Then              { Check if item ticked }
+     Mark := True Else Mark := False;                 { Return result }
+END;
+
+{--TCheckBoxes--------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04May98 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TCheckBoxes.DrawFocus;
+CONST Button = ' [ ] ';
+BEGIN
+   Inherited DrawFocus;
+   DrawMultiBox(Button, ' X');                        { Redraw the text }
+END;
+
+{--TCheckBoxes--------------------------------------------------------------}
+{  Press -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Apr98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TCheckBoxes.Press (Item: Integer);
+BEGIN
+   Value := Value XOR (1 SHL Item);                   { Flip the item mask }
+   Inherited Press(Item);                             { Call ancestor }
+END;
+
+{$IFNDEF OS_DOS}                                      { WIN/NT/OS2 CODE }
+{***************************************************************************}
+{               TCheckBoxes OBJECT WIN/NT/OS2 ONLY METHODS                  }
+{***************************************************************************}
+
+{--TCheckBoxes--------------------------------------------------------------}
+{  SubClassAttr -> Platforms WIN/NT/OS2 - Updated 20May98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TCheckBoxes.SubClassAttr: LongInt;
+BEGIN
+   SubClassAttr := Inherited SubClassAttr OR
+     bs_CheckBox;                                     { Check box buttons }
+END;
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                      TMultiCheckBoxes OBJECT METHODS                      }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 05Jun98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TMultiCheckBoxes.Init (Var Bounds: TRect; AStrings: PSItem;
+ASelRange: Byte; AFlags: Word; Const AStates: String);
+BEGIN
+   Inherited Init(Bounds, AStrings);                  { Call ancestor }
+   SelRange := ASelRange;                             { Hold select range }
+   Flags := AFlags;                                   { Hold flags }
+   States := NewStr(AStates);                         { Hold string }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TMultiCheckBoxes.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(SelRange, SizeOf(SelRange));                { Read select range }
+   S.Read(Flags, SizeOf(Flags));                      { Read flags }
+   States := S.ReadStr;                               { Read strings }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TMultiCheckBoxes.Done;
+BEGIN
+   If (States <> Nil) Then DisposeStr(States);        { Dispose strings }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  DataSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TMultiCheckBoxes.DataSize: Word;
+BEGIN
+   DataSize := SizeOf(LongInt);                       { Size to exchange }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  MultiMark -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION TMultiCheckBoxes.MultiMark (Item: Integer): Byte;
+BEGIN
+   MultiMark := (Value SHR (Word(Item) *
+    WordRec(Flags).Hi)) AND WordRec(Flags).Lo;        { Return mark state }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TMultiCheckBoxes.DrawFocus;
+CONST Button = ' [ ] ';
+BEGIN
+   Inherited DrawFocus;
+   DrawMultiBox(Button, States^);                     { Draw the items }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  Press -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TMultiCheckBoxes.Press (Item: Integer);
+VAR CurState: ShortInt;
+BEGIN
+   CurState := (Value SHR (Word(Item) *
+     WordRec(Flags).Hi)) AND WordRec(Flags).Lo;       { Hold current state }
+   Dec(CurState);                                     { One down }
+   If (CurState >= SelRange) OR (CurState < 0) Then
+     CurState := SelRange - 1;                        { Roll if needed }
+   Value := (Value AND NOT (LongInt(WordRec(Flags).Lo)
+     SHL (Word(Item) * WordRec(Flags).Hi))) OR
+    (LongInt(CurState) SHL (Word(Item) *
+    WordRec(Flags).Hi));                              { Calculate value }
+   Inherited Press(Item);                             { Call ancestor }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  GetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TMultiCheckBoxes.GetData (Var Rec);
+BEGIN
+   Longint(Rec) := Value;                             { Return value }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  SetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TMultiCheckBoxes.SetData (Var Rec);
+BEGIN
+   Value := Longint(Rec);                             { Set value }
+   SetDrawMask(vdFocus OR vdInner);                   { Set redraw mask }
+   DrawView;                                          { Redraw masked areas }
+END;
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TMultiCheckBoxes.Store (Var S: TStream);
+BEGIN
+   TCluster.Store(S);                                 { TCluster store called }
+   S.Write(SelRange, SizeOf(SelRange));               { Write select range }
+   S.Write(Flags, SizeOf(Flags));                     { Write select flags }
+   S.WriteStr(States);                                { Write strings }
+END;
+
+{$IFNDEF OS_DOS}                                      { WIN/NT/OS2 CODE }
+{***************************************************************************}
+{             TMultiCheckBoxes OBJECT WIN/NT/OS2 ONLY METHODS               }
+{***************************************************************************}
+
+{--TMultiCheckBoxes---------------------------------------------------------}
+{  SubClassAttr -> Platforms WIN/NT/OS2 - Updated 06Jun98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TMultiCheckBoxes.SubClassAttr: LongInt;
+BEGIN
+   SubClassAttr := Inherited SubClassAttr OR
+     bs_CheckBox;                                     { Check box buttons }
+END;
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TListBox OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+TYPE
+   TListBoxRec = PACKED RECORD
+     List: PCollection;                               { List collection ptr }
+     Selection: Word;                                 { Selected item }
+   END;
+
+{--TListBox-----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TListBox.Init (Var Bounds: TRect; ANumCols: Word;
+  AScrollBar: PScrollBar);
+BEGIN
+   Inherited Init(Bounds, ANumCols, Nil, AScrollBar); { Call ancestor }
+   SetRange(0);                                       { Set range to zero }
+END;
+
+{--TListBox-----------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TListBox.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   List := PCollection(S.Get);                        { Fetch collection }
+END;
+
+{--TListBox-----------------------------------------------------------------}
+{  DataSize -> Platforms DOS/DPMI/WIN/NT/Os2 - Updated 06Jun98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TListBox.DataSize: Word;
+BEGIN
+   DataSize := SizeOf(TListBoxRec);                   { Xchg data size }
+END;
+
+{--TListBox-----------------------------------------------------------------}
+{  GetText -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TListBox.GetText (Item: Integer; MaxLen: Integer): String;
+VAR P: PString;
+BEGIN
+   GetText := '';                                     { Preset return }
+   If (List <> Nil) Then Begin                        { A list exists }
+     P := PString(List^.At(Item));                    { Get string ptr }
+     If (P <> Nil) Then GetText := P^;                { Return string }
+   End;
+END;
+
+{--TListBox-----------------------------------------------------------------}
+{  NewList -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TListBox.NewList (AList: PCollection);
+{$IFDEF OS_WINDOWS} VAR I: Integer; S: String; P: PString; {$ENDIF}
+BEGIN
+   If (List <> Nil) Then Dispose(List, Done);         { Dispose old list }
+   List := AList;                                     { Hold new list }
+   If (AList <> Nil) Then SetRange(AList^.Count)      { Set new item range }
+     Else SetRange(0);                                { Set zero range }
+   If (Range > 0) Then FocusItem(0);                  { Focus first item }
+   DrawView;                                          { Redraw all view }
+END;
+
+{--TListBox-----------------------------------------------------------------}
+{  GetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TListBox.GetData (Var Rec);
+BEGIN
+   TListBoxRec(Rec).List := List;                     { Return current list }
+   TListBoxRec(Rec).Selection := Focused;             { Return focused item }
+END;
+
+{--TListBox-----------------------------------------------------------------}
+{  SetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TListBox.SetData (Var Rec);
+BEGIN
+   NewList(TListBoxRec(Rec).List);                    { Hold new list }
+   FocusItem(TListBoxRec(Rec).Selection);             { Focus selected item }
+   DrawView;                                          { Redraw all view }
+END;
+
+{--TListBox-----------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TListBox.Store (Var S: TStream);
+BEGIN
+   TListViewer.Store(S);                              { TListViewer store }
+   S.Put(List);                                       { Store list to stream }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TStaticText OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TStaticText--------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TStaticText.Init (Var Bounds: TRect; Const AText: String);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   Text := NewStr(AText);                             { Create string ptr }
+END;
+
+{--TStaticText--------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TStaticText.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   Text := S.ReadStr;                                 { Read text string }
+END;
+
+{--TStaticText--------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TStaticText.Done;
+BEGIN
+   If (Text <> Nil) Then DisposeStr(Text);            { Dispose string }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TStaticText--------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TStaticText.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CStaticText;                        { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CStaticText)] = CStaticText;   { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{--TStaticText--------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TStaticText.DrawBackGround;
+VAR Just: Byte; I, J, P, Y, L: Integer; S, T: String;
+BEGIN
+   Inherited DrawBackGround;                          { Call ancestor }
+   GetText(S);                                        { Fetch text to write }
+   P := 1;                                            { X start position }
+   Y := 0;                                            { Y start position }
+   L := Length(S);                                    { Length of text }
+   While (Y < Size.Y) AND (P <= L) Do Begin
+     Just := 0;                                       { Default left justify }
+     If (S[P] = #2) Then Begin                        { Right justify char }
+       Just := 2;                                     { Set right justify }
+       Inc(P);                                        { Next character }
+     End;
+     If (S[P] = #3) Then Begin                        { Centre justify char }
+       Just := 1;                                     { Set centre justify }
+       Inc(P);                                        { Next character }
+     End;
+     I := P;                                          { Start position }
+     While (P <= L) AND (S[P] <> #13) Do Inc(P);      { Scan for end }
+     T := Copy(S, I, P-I);                            { String to write }
+     Case Just Of
+       0: J := 0;                                     { Left justify }
+       1: J := (RawSize.X - TextWidth(T)) DIV 2;      { Centre justify }
+       2: J := RawSize.X - TextWidth(T);              { Right justify }
+     End;
+     While (J < 0) Do Begin                           { Text to long }
+       J := J + TextWidth(T[1]);                      { Add width to J }
+       Delete(T, 1, 1);                               { Delete the char }
+     End;
+     WriteStr(-J, -(Y*FontHeight), T, 1);             { Write the text }
+     While (P <= L) AND ((S[P] = #13) OR (S[P] = #10))
+       Do Inc(P);                                     { Remove CR/LF }
+     Inc(Y);                                          { Next line }
+   End;
+END;
+
+{--TStaticText--------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TStaticText.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { Call TView store }
+   S.WriteStr(Text);                                  { Write text string }
+END;
+
+{--TStaticText--------------------------------------------------------------}
+{  GetText -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TStaticText.GetText (Var S: String);
+BEGIN
+   If (Text <> Nil) Then S := Text^                   { Copy text string }
+     Else S := '';                                    { Return empty string }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                         TParamText OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TParamText---------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TParamText.Init (Var Bounds: TRect; Const AText: String;
+  AParamCount: Integer);
+BEGIN
+   Inherited Init(Bounds, AText);                     { Call ancestor }
+   ParamCount := AParamCount;                         { Hold param count }
+END;
+
+{--TParamText---------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TParamText.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(ParamCount, 2);                             { Read parameter count }
+END;
+
+{--TParamText---------------------------------------------------------------}
+{  DataSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TParamText.DataSize: Word;
+BEGIN
+   DataSize := ParamCount * SizeOf(Pointer);          { Return data size }
+END;
+
+{--TParamText---------------------------------------------------------------}
+{  GetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TParamText.GetData (Var Rec);
+BEGIN
+   Pointer(Rec) := @ParamList;                        { Return parm ptr }
+END;
+
+{--TParamText---------------------------------------------------------------}
+{  SetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Jun98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TParamText.SetData (Var Rec);
+BEGIN
+   ParamList := @Rec;                                 { Fetch parameter list }
+   DrawView;                                          { Redraw all the view }
+END;
+
+{--TParamText---------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TParamText.Store (Var S: TStream);
+BEGIN
+   TStaticText.Store(S);                              { Statictext store }
+   S.Write(ParamCount, 2);                            { Store param count }
+END;
+
+{--TParamText---------------------------------------------------------------}
+{  GetText -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TParamText.GetText (Var S: String);
+BEGIN
+   If (Text = Nil) Then S := '' Else                  { Return empty string }
+     FormatStr(S, Text^, ParamList^);                 { Return text string }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           TLabel OBJECT METHODS                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TLabel-------------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TLabel.Init (Var Bounds: TRect; CONST AText: String; ALink: PView);
+BEGIN
+   Inherited Init(Bounds, AText);                     { Call ancestor }
+   Link := ALink;                                     { Hold link }
+   Options := Options OR (ofPreProcess+ofPostProcess);{ Set pre/post process }
+   EventMask := EventMask OR evBroadcast;             { Sees broadcast events }
+END;
+
+{--TLabel-------------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TLabel.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   GetPeerViewPtr(S, Link);                           { Load link view }
+END;
+
+{--TLabel-------------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TLabel.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CLabel;                             { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CLabel)] = CLabel;             { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{--TLabel-------------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TLabel.DrawBackGround;
+VAR SCOff: Byte; Color: Word; B: TDrawBuffer;
+BEGIN
+   TView.DrawBackGround;                              { Explict call to TView }
+   If Light Then Begin                                { Light colour select }
+     Color := GetColor($0402);                        { Choose light colour }
+     SCOff := 0;                                      { Zero offset }
+   End Else Begin
+     Color := GetColor($0301);                        { Darker colour }
+     SCOff := 4;                                      { Set offset }
+   End;
+   MoveChar(B[0], ' ', Byte(Color), Size.X);          { Clear the buffer }
+   If (Text <> Nil) Then MoveCStr(B[1], Text^, Color);{ Transfer label text }
+   If ShowMarkers Then WordRec(B[0]).Lo := Byte(
+     SpecialChars[SCOff]);                            { Show marker if req }
+   WriteLine(0, 0, Size.X, 1, B);                     { Write the text }
+END;
+
+{--TLabel-------------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TLabel.Store (Var S: TStream);
+BEGIN
+   TStaticText.Store(S);                              { TStaticText.Store }
+   PutPeerViewPtr(S, Link);                           { Store link view }
+END;
+
+{--TLabel-------------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TLabel.HandleEvent (Var Event: TEvent);
+VAR C: Char;
+
+   PROCEDURE FocusLink;
+   BEGIN
+     If (Link <> Nil) AND (Link^.Options AND
+      ofSelectable <> 0) Then Link^.Focus;            { Focus link view }
+     ClearEvent(Event);                               { Clear the event }
+   END;
+
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   Case Event.What Of
+     evNothing: Exit;                                 { Speed up exit }
+     evMouseDown: FocusLink;                          { Focus link view }
+     evKeyDown: Begin
+       C := HotKey(Text^);                            { Check for hotkey }
+       If (GetAltCode(C) = Event.KeyCode) OR          { Alt plus char }
+       ((C <> #0) AND (Owner^.Phase = phPostProcess)  { Post process phase }
+       AND (UpCase(Event.CharCode) = C)) Then         { Upper case match }
+         FocusLink;                                   { Focus link view }
+     End;
+     evBroadcast: If ((Event.Command = cmReceivedFocus)
+       OR (Event.Command = cmReleasedFocus)) AND      { Focus state change }
+       (Link <> Nil) Then Begin
+         Light := Link^.State AND sfFocused <> 0;     { Change light state }
+         DrawView;                                    { Now redraw change }
+       End;
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                       THistoryViewer OBJECT METHODS                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--THistoryViewer-----------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR THistoryViewer.Init (Var Bounds: TRect; AHScrollBar,
+AVScrollBar: PScrollBar; AHistoryId: Word);
+BEGIN
+   Inherited Init(Bounds, 1, AHScrollBar,
+     AVScrollBar);                                    { Call ancestor }
+   HistoryId := AHistoryId;                           { Hold history id }
+   SetRange(HistoryCount(AHistoryId));                { Set history range }
+   If (Range > 1) Then FocusItem(1);                  { Set to item 1 }
+   If (HScrollBar <> Nil) Then
+     HScrollBar^.SetRange(1, HistoryWidth-Size.X + 3);{ Set scrollbar range }
+END;
+
+{--THistoryViewer-----------------------------------------------------------}
+{  HistoryWidth -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION THistoryViewer.HistoryWidth: Integer;
+VAR Width, T, Count, I: Integer;
+BEGIN
+   Width := 0;                                        { Zero width variable }
+   Count := HistoryCount(HistoryId);                  { Hold count value }
+   For I := 0 To Count-1 Do Begin                     { For each item }
+     T := Length(HistoryStr(HistoryId, I));           { Get width of item }
+     If (T > Width) Then Width := T;                  { Set width to max }
+   End;
+   HistoryWidth := Width;                             { Return max item width }
+END;
+
+{--THistoryViewer-----------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION THistoryViewer.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CHistoryViewer;                     { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CHistoryViewer)] = CHistoryViewer;{ Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{--THistoryViewer-----------------------------------------------------------}
+{  GetText -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION THistoryViewer.GetText (Item: Integer; MaxLen: Integer): String;
+BEGIN
+   GetText := HistoryStr(HistoryId, Item);            { Return history string }
+END;
+
+{--THistoryViewer-----------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE THistoryViewer.HandleEvent (Var Event: TEvent);
+BEGIN
+   If ((Event.What = evMouseDown) AND (Event.Double)) { Double click mouse }
+   OR ((Event.What = evKeyDown) AND
+   (Event.KeyCode = kbEnter)) Then Begin              { Enter key press }
+     EndModal(cmOk);                                  { End with cmOk }
+     ClearEvent(Event);                               { Event was handled }
+   End Else If ((Event.What = evKeyDown) AND
+   (Event.KeyCode = kbEsc)) OR                        { Esc key press }
+   ((Event.What = evCommand) AND
+   (Event.Command = cmCancel)) Then Begin             { Cancel command }
+     EndModal(cmCancel);                              { End with cmCancel }
+     ClearEvent(Event);                               { Event was handled }
+   End Else Inherited HandleEvent(Event);             { Call ancestor }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                       THistoryWindow OBJECT METHODS                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--THistoryWindow-----------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR THistoryWindow.Init (Var Bounds: TRect; HistoryId: Word);
+BEGIN
+   Inherited Init(Bounds, '', wnNoNumber);            { Call ancestor }
+   Flags := wfClose;                                  { Close flag only }
+   InitViewer(HistoryId);                             { Create list view }
+END;
+
+{--THistoryWindow-----------------------------------------------------------}
+{  GetSelection -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION THistoryWindow.GetSelection: String;
+BEGIN
+   If (Viewer = Nil) Then GetSelection := '' Else     { Return empty string }
+     GetSelection := Viewer^.GetText(Viewer^.Focused,
+       255);                                          { Get focused string }
+END;
+
+{--THistoryWindow-----------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION THistoryWindow.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CHistoryWindow;                     { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CHistoryWindow)] = CHistoryWindow;{ Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return the palette }
+END;
+
+{--THistoryWindow-----------------------------------------------------------}
+{  InitViewer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE THistoryWindow.InitViewer(HistoryId: Word);
+VAR R: TRect;
+BEGIN
+   GetExtent(R);                                      { Get extents }
+   R.Grow(-1,-1);                                     { Grow inside }
+   Viewer := New(PHistoryViewer, Init(R,
+     StandardScrollBar(sbHorizontal + sbHandleKeyboard),
+     StandardScrollBar(sbVertical + sbHandleKeyboard),
+     HistoryId));                                     { Create the viewer }
+   If (Viewer <> Nil) Then Insert(Viewer);            { Insert viewer }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          THistory OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--THistory-----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR THistory.Init (Var Bounds: TRect; ALink: PInputLine;
+AHistoryId: Word);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   Options := Options OR ofPostProcess;               { Set post process }
+   EventMask := EventMask OR evBroadcast;             { See broadcast events }
+   Link := ALink;                                     { Hold link view }
+   HistoryId := AHistoryId;                           { Hold history id }
+END;
+
+{--THistory-----------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR THistory.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   GetPeerViewPtr(S, Link);                           { Load link view }
+   S.Read(HistoryId, 2);                              { Read history id }
+END;
+
+{--THistory-----------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION THistory.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CHistory;                           { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CHistory)] = CHistory;         { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return the palette }
+END;
+
+{--THistory-----------------------------------------------------------------}
+{  InitHistoryWindow -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB }
+{---------------------------------------------------------------------------}
+FUNCTION THistory.InitHistoryWindow (Var Bounds: TRect): PHistoryWindow;
+VAR P: PHistoryWindow;
+BEGIN
+   P := New(PHistoryWindow, Init(Bounds, HistoryId)); { Create history window }
+   If (Link <> Nil) Then
+     P^.HelpCtx := Link^.HelpCtx;                     { Set help context }
+   InitHistoryWindow := P;                            { Return history window }
+END;
+
+PROCEDURE THistory.Draw;
+VAR B: TDrawBuffer;
+BEGIN
+   MoveCStr(B, #222'~'#25'~'#221, GetColor($0102));   { Set buffer data }
+   WriteLine(0, 0, Size.X, Size.Y, B);                { Write buffer }
+END;
+
+{--THistory-----------------------------------------------------------------}
+{  RecordHistory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE THistory.RecordHistory (CONST S: String);
+BEGIN
+   HistoryAdd(HistoryId, S);                          { Add to history }
+END;
+
+{--THistory-----------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE THistory.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { TView.Store called }
+   PutPeerViewPtr(S, Link);                           { Store link view }
+   S.Write(HistoryId, 2);                             { Store history id }
+END;
+
+{--THistory-----------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE THistory.HandleEvent (Var Event: TEvent);
+VAR C: Word; Rslt: String; R, P: TRect; HistoryWindow: PHistoryWindow;
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   If (Link = Nil) Then Exit;                         { No link view exits }
+   If (Event.What = evMouseDown) OR                   { Mouse down event }
+   ((Event.What = evKeyDown) AND
+    (CtrlToArrow(Event.KeyCode) = kbDown) AND         { Down arrow key }
+    (Link^.State AND sfFocused <> 0)) Then Begin      { Link view selected }
+      If NOT Link^.Focus Then Begin
+       ClearEvent(Event);                             { Event was handled }
+       Exit;                                          { Now exit }
+      End;
+     RecordHistory(Link^.Data^);                      { Record current data }
+     Link^.GetBounds(R);                              { Get view bounds }
+     Dec(R.A.X);                                      { One char in from us }
+     Inc(R.B.X);                                      { One char short of us }
+     Inc(R.B.Y, 7);                                   { Seven lines down }
+     Dec(R.A.Y,1);                                    { One line below us }
+     Owner^.GetExtent(P);                             { Get owner extents }
+     R.Intersect(P);                                  { Intersect views }
+     Dec(R.B.Y,1);                                    { Shorten length by one }
+     HistoryWindow := InitHistoryWindow(R);           { Create history window }
+     If (HistoryWindow <> Nil) Then Begin             { Window crested okay }
+       C := Owner^.ExecView(HistoryWindow);           { Execute this window }
+       If (C = cmOk) Then Begin                       { Result was okay }
+         Rslt := HistoryWindow^.GetSelection;         { Get history selection }
+         If Length(Rslt) > Link^.MaxLen Then
+           {$IFDEF PPC_DELPHI3}                       { DELPHI 3+ COMPILER }
+            SetLength(Rslt, Link^.MaxLen);            { Hold new length }
+           {$ELSE}
+            Rslt[0] := Char(Link^.MaxLen);            { Hold new length }
+           {$ENDIF}
+         Link^.Data^ := Rslt;                         { Hold new selection }
+         Link^.SelectAll(True);                       { Select all string }
+         Link^.DrawView;                              { Redraw link view }
+       End;
+       Dispose(HistoryWindow, Done);                  { Dispose of window }
+     End;
+     ClearEvent(Event);                               { Event was handled }
+   End Else If (Event.What = evBroadcast) Then        { Broadcast event }
+     If ((Event.Command = cmReleasedFocus) AND
+     (Event.InfoPtr = Link)) OR
+     (Event.Command = cmRecordHistory) Then           { Record command }
+       RecordHistory(Link^.Data^);                    { Record the history }
+END;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           ITEM STRING ROUTINES                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  NewSItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28Apr98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION NewSItem (Const Str: String; ANext: PSItem): PSItem;
+VAR Item: PSItem;
+BEGIN
+   New(Item);                                         { Allocate item }
+   Item^.Value := NewStr(Str);                        { Hold item string }
+   Item^.Next := ANext;                               { Chain the ptr }
+   NewSItem := Item;                                  { Return item }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                    DIALOG OBJECT REGISTRATION ROUTINES                    }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  RegisterDialogs -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB   }
+{---------------------------------------------------------------------------}
+PROCEDURE RegisterDialogs;
+BEGIN
+   RegisterType(RDialog);                             { Register dialog }
+   RegisterType(RInputLine);                          { Register inputline }
+   RegisterType(RButton);                             { Register button }
+   RegisterType(RCluster);                            { Register cluster }
+   RegisterType(RRadioButtons);                       { Register radiobutton }
+   RegisterType(RCheckBoxes);                         { Register check boxes }
+   RegisterType(RMultiCheckBoxes);                    { Register multi boxes }
+   RegisterType(RListBox);                            { Register list box }
+   RegisterType(RStaticText);                         { Register static text }
+   RegisterType(RLabel);                              { Register label }
+   RegisterType(RHistory);                            { Register history }
+   RegisterType(RParamText);                          { Register parm text }
+END;
+
+END.

+ 2624 - 0
fv/drivers.pas

@@ -0,0 +1,2624 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{    System independent clone of DRIVERS.PAS               }
+{                                                          }
+{    Interface Copyright (c) 1992 Borland International    }
+{                                                          }
+{    Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer  }
+{    [email protected]  - primary e-mail addr          }
+{    [email protected] - backup e-mail addr           }
+{                                                          }
+{    Original FormatStr kindly donated by Marco Schmidt    }
+{                                                          }
+{    Mouse callback hook under FPC with kind assistance of }
+{    Pierre Muller, Gertjan Schouten & Florian Klaempfl.   }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                 - Speed Pascal 1.0+       (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     26 Jul 96   First DOS/DPMI platform release    }
+{  1.10     18 Nov 97   Windows conversion added.          }
+{  1.20     29 Aug 97   Platform.inc sort added.           }
+{  1.30     10 Jun 98   Virtual pascal 2.0 code added.     }
+{  1.40     13 Jul 98   Added FormatStr by Marco Schmidt.  }
+{  1.50     14 Jul 98   Fixed width = 0 in FormatStr.      }
+{  1.60     13 Aug 98   Complete rewrite of FormatStr.     }
+{  1.70     10 Sep 98   Added mouse int hook for FPC.      }
+{  1.80     10 Sep 98   Checks run & commenting added.     }
+{  1.90     15 Oct 98   Fixed for FPC version 0.998        }
+{  1.91     18 Feb 99   Added PrintStr functions           }
+{  1.92     18 Feb 99   FormatStr literal '%' fix added    }
+{  1.93     10 Jul 99   Sybil 2.0 code added               }
+{  1.94     15 Jul 99   Fixed for FPC 0.9912 release       }
+{  1.95     26 Jul 99   Windows..Scales to GFV system font }
+{  1.96     30 Jul 99   Fixed Ctrl+F1..F10 in GetKeyEvent  }
+{  1.97     07 Sep 99   InitEvent, DoneEvent fixed for OS2 }
+{  1.98     09 Sep 99   GetMouseEvent fixed for OS2.       }
+{  1.99     03 Nov 99   FPC windows support added.         }
+{  2.00     26 Nov 99   Graphics stuff moved to GFVGraph   }
+{**********************************************************}
+
+UNIT Drivers;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC} { FPC doesn't support these switches }
+  {$F+} { Force far calls - Used because of the ShowMouseProc etc... }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O-} { This unit may >>> NOT <<< be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     {$IFNDEF PPC_SPEED}                              { NON SPEED COMPILER }
+       {$IFDEF PPC_FPC}                               { FPC WINDOWS COMPILER }
+         Windows,                                     { Standard unit }
+       {$ELSE}                                        { OTHER COMPILERS }
+         WinTypes, WinProcs,                          { Standard units }
+       {$ENDIF}
+       {$IFDEF PPC_DELPHI}                            { DELPHI3+ COMPILER }
+       SysUtils, Messages,                            { Standard unit }
+       {$ENDIF}
+     {$ELSE}                                          { SYBIL2+ COMPILER }
+       WinBase, WinDef, WinUser, WinGDI,              { Standard units }
+     {$ENDIF}
+   {$ENDIF}
+
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+     {$IFDEF PPC_Virtual}                             { VIRTUAL PASCAL UNITS }
+       OS2Def, OS2Base, OS2PMAPI,                     { Standard units }
+     {$ENDIF}
+     {$IFDEF PPC_Speed}                               { SPEED PASCAL UNITS }
+       BseDos, Os2Def,                                { Standard units }
+     {$ENDIF}
+   {$ENDIF}
+
+   Common, GFVGraph, Objects;                         { GFV standard units }
+
+{***************************************************************************}
+{                              PUBLIC CONSTANTS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                              EVENT TYPE MASKS                             }
+{---------------------------------------------------------------------------}
+CONST
+   evMouseDown = $0001;                               { Mouse down event }
+   evMouseUp   = $0002;                               { Mouse up event }
+   evMouseMove = $0004;                               { Mouse move event }
+   evMouseAuto = $0008;                               { Mouse auto event }
+   evKeyDown   = $0010;                               { Key down event }
+   evCommand   = $0100;                               { Command event }
+   evBroadcast = $0200;                               { Broadcast event }
+
+{---------------------------------------------------------------------------}
+{                             EVENT CODE MASKS                              }
+{---------------------------------------------------------------------------}
+CONST
+   evNothing   = $0000;                               { Empty event }
+   evMouse     = $000F;                               { Mouse event }
+   evKeyboard  = $0010;                               { Keyboard event }
+   evMessage   = $FF00;                               { Message event }
+
+{---------------------------------------------------------------------------}
+{                             EXTENDED KEY CODES                            }
+{---------------------------------------------------------------------------}
+CONST
+   kbNoKey       = $0000;  kbAltEsc      = $0100;  kbEsc         = $011B;
+   kbAltSpace    = $0200;  kbCtrlIns     = $0400;  kbShiftIns    = $0500;
+   kbCtrlDel     = $0600;  kbShiftDel    = $0700;  kbAltBack     = $0800;
+   kbAltShiftBack= $0900;  kbBack        = $0E08;  kbCtrlBack    = $0E7F;
+   kbShiftTab    = $0F00;  kbTab         = $0F09;  kbAltQ        = $1000;
+   kbCtrlQ       = $1011;  kbAltW        = $1100;  kbCtrlW       = $1117;
+   kbAltE        = $1200;  kbCtrlE       = $1205;  kbAltR        = $1300;
+   kbCtrlR       = $1312;  kbAltT        = $1400;  kbCtrlT       = $1414;
+   kbAltY        = $1500;  kbCtrlY       = $1519;  kbAltU        = $1600;
+   kbCtrlU       = $1615;  kbAltI        = $1700;  kbCtrlI       = $1709;
+   kbAltO        = $1800;  kbCtrlO       = $180F;  kbAltP        = $1900;
+   kbCtrlP       = $1910;  kbAltLftBrack = $1A00;  kbAltRgtBrack = $1B00;
+   kbCtrlEnter   = $1C0A;  kbEnter       = $1C0D;  kbAltA        = $1E00;
+   kbCtrlA       = $1E01;  kbAltS        = $1F00;  kbCtrlS       = $1F13;
+   kbAltD        = $2000;  kbCtrlD       = $2004;  kbAltF        = $2100;
+   kbCtrlF       = $2106;  kbAltG        = $2200;  kbCtrlG       = $2207;
+   kbAltH        = $2300;  kbCtrlH       = $2308;  kbAltJ        = $2400;
+   kbCtrlJ       = $240A;  kbAltK        = $2500;  kbCtrlK       = $250B;
+   kbAltL        = $2600;  kbCtrlL       = $260C;  kbAltSemiCol  = $2700;
+   kbAltQuote    = $2800;  kbAltOpQuote  = $2900;  kbAltBkSlash  = $2B00;
+   kbAltZ        = $2C00;  kbCtrlZ       = $2C1A;  kbAltX        = $2D00;
+   kbCtrlX       = $2D18;  kbAltC        = $2E00;  kbCtrlC       = $2E03;
+   kbAltV        = $2F00;  kbCtrlV       = $2F16;  kbAltB        = $3000;
+   kbCtrlB       = $3002;  kbAltN        = $3100;  kbCtrlN       = $310E;
+   kbAltM        = $3200;  kbCtrlM       = $320D;  kbAltComma    = $3300;
+   kbAltPeriod   = $3400;  kbAltSlash    = $3500;  kbAltGreyAst  = $3700;
+   kbSpaceBar    = $3920;  kbF1          = $3B00;  kbF2          = $3C00;
+   kbF3          = $3D00;  kbF4          = $3E00;  kbF5          = $3F00;
+   kbF6          = $4000;  kbF7          = $4100;  kbF8          = $4200;
+   kbF9          = $4300;  kbF10         = $4400;  kbHome        = $4700;
+   kbUp          = $4800;  kbPgUp        = $4900;  kbGrayMinus   = $4A2D;
+   kbLeft        = $4B00;  kbCenter      = $4C00;  kbRight       = $4D00;
+   kbAltGrayPlus = $4E00;  kbGrayPlus    = $4E2B;  kbEnd         = $4F00;
+   kbDown        = $5000;  kbPgDn        = $5100;  kbIns         = $5200;
+   kbDel         = $5300;  kbShiftF1     = $5400;  kbShiftF2     = $5500;
+   kbShiftF3     = $5600;  kbShiftF4     = $5700;  kbShiftF5     = $5800;
+   kbShiftF6     = $5900;  kbShiftF7     = $5A00;  kbShiftF8     = $5B00;
+   kbShiftF9     = $5C00;  kbShiftF10    = $5D00;  kbCtrlF1      = $5E00;
+   kbCtrlF2      = $5F00;  kbCtrlF3      = $6000;  kbCtrlF4      = $6100;
+   kbCtrlF5      = $6200;  kbCtrlF6      = $6300;  kbCtrlF7      = $6400;
+   kbCtrlF8      = $6500;  kbCtrlF9      = $6600;  kbCtrlF10     = $6700;
+   kbAltF1       = $6800;  kbAltF2       = $6900;  kbAltF3       = $6A00;
+   kbAltF4       = $6B00;  kbAltF5       = $6C00;  kbAltF6       = $6D00;
+   kbAltF7       = $6E00;  kbAltF8       = $6F00;  kbAltF9       = $7000;
+   kbAltF10      = $7100;  kbCtrlPrtSc   = $7200;  kbCtrlLeft    = $7300;
+   kbCtrlRight   = $7400;  kbCtrlEnd     = $7500;  kbCtrlPgDn    = $7600;
+   kbCtrlHome    = $7700;  kbAlt1        = $7800;  kbAlt2        = $7900;
+   kbAlt3        = $7A00;  kbAlt4        = $7B00;  kbAlt5        = $7C00;
+   kbAlt6        = $7D00;  kbAlt7        = $7E00;  kbAlt8        = $7F00;
+   kbAlt9        = $8000;  kbAlt0        = $8100;  kbAltMinus    = $8200;
+   kbAltEqual    = $8300;  kbCtrlPgUp    = $8400;  kbF11         = $8500;
+   kbF12         = $8600;  kbShiftF11    = $8700;  kbShiftF12    = $8800;
+   kbCtrlF11     = $8900;  kbCtrlF12     = $8A00;  kbAltF11      = $8B00;
+   kbAltF12      = $8C00;  kbCtrlUp      = $8D00;  kbCtrlMinus   = $8E00;
+   kbCtrlCenter  = $8F00;  kbCtrlGreyPlus= $9000;  kbCtrlDown    = $9100;
+   kbCtrlTab     = $9400;  kbAltHome     = $9700;  kbAltUp       = $9800;
+   kbAltPgUp     = $9900;  kbAltLeft     = $9B00;  kbAltRight    = $9D00;
+   kbAltEnd      = $9F00;  kbAltDown     = $A000;  kbAltPgDn     = $A100;
+   kbAltIns      = $A200;  kbAltDel      = $A300;  kbAltTab      = $A500;
+
+{ ------------------------------- REMARK ------------------------------ }
+{ New keys not initially defined by Borland in their unit interface.    }
+{ ------------------------------ END REMARK --- Leon de Boer, 15May96 - }
+   kbFullStop    = $342E;  kbComma       = $332C;  kbBackSlash   = $352F;
+   kbApostrophe  = $2827;  kbSemiColon   = $273B;  kbEqual       = $0D3D;
+   kbGreaterThan = $343E;  kbLessThan    = $333C;  kbQuestion    = $353F;
+   kbQuote       = $2822;  kbColon       = $273A;  kbPlus        = $0D2B;
+   kbPipe        = $2B7C;  kbSlash       = $2B5C;  kbExclaim     = $0221;
+   kbAt          = $0340;  kbNumber      = $0423;  kbPercent     = $0625;
+   kbCaret       = $075E;  kbAmpersand   = $0826;  kbAsterix     = $092A;
+   kbLeftBracket = $0A28;  kbRightBracket= $0B29;  kbApprox      = $2960;
+   kbTilde       = $297E;  kbDollar      = $0524;  kbMinus       = $0C2D;
+   kbUnderline   = $0C5F;  kbLeftSqBr    = $1A5B;  kbRightSqBr   = $1B5D;
+   kbLeftCurlyBr = $1A7B;  kbRightCurlyBr= $1B7D;
+
+{---------------------------------------------------------------------------}
+{                      KEYBOARD STATE AND SHIFT MASKS                       }
+{---------------------------------------------------------------------------}
+CONST
+   kbRightShift  = $0001;                             { Right shift key }
+   kbLeftShift   = $0002;                             { Left shift key }
+   kbCtrlShift   = $0004;                             { Control key down }
+   kbAltShift    = $0008;                             { Alt key down }
+   kbScrollState = $0010;                             { Scroll lock on }
+   kbNumState    = $0020;                             { Number lock on }
+   kbCapsState   = $0040;                             { Caps lock on }
+   kbInsState    = $0080;                             { Insert mode on }
+
+   kbBothShifts  = kbRightShift + kbLeftShift;        { Right & Left shifts }
+
+{---------------------------------------------------------------------------}
+{                         MOUSE BUTTON STATE MASKS                          }
+{---------------------------------------------------------------------------}
+CONST
+   mbLeftButton   = $01;                              { Left mouse button }
+   mbRightButton  = $02;                              { Right mouse button }
+   mbMiddleButton = $04;                              { Middle mouse button }
+
+{---------------------------------------------------------------------------}
+{                         SCREEN CRT MODE CONSTANTS                         }
+{---------------------------------------------------------------------------}
+CONST
+   smBW80    = $0002;                                 { Black and white }
+   smCO80    = $0003;                                 { Colour mode }
+   smMono    = $0007;                                 { Monochrome mode }
+   smFont8x8 = $0100;                                 { 8x8 font mode }
+
+{***************************************************************************}
+{                          PUBLIC TYPE DEFINITIONS                          }
+{***************************************************************************}
+
+{ ******************************* REMARK ****************************** }
+{    The TEvent definition is completely compatable with all existing   }
+{  code but adds two new fields ID and Data into the message record     }
+{  which helps with WIN/NT and OS2 message processing.                  }
+{ ****************************** END REMARK *** Leon de Boer, 11Sep97 * }
+
+{---------------------------------------------------------------------------}
+{                          EVENT RECORD DEFINITION                          }
+{---------------------------------------------------------------------------}
+TYPE
+   TEvent = PACKED RECORD
+      What: Word;                                     { Event type }
+      Case Word Of
+        evNothing: ();                                { ** NO EVENT ** }
+        evMouse: (
+          Buttons: Byte;                              { Mouse buttons }
+          Double: Boolean;                            { Double click state }
+          Where: TPoint);                             { Mouse position }
+        evKeyDown: (                                  { ** KEY EVENT ** }
+          Case Integer Of
+            0: (KeyCode: Word);                       { Full key code }
+            1: (CharCode: Char;                       { Char code }
+                ScanCode: Byte));                     { Scan code }
+        evMessage: (                                  { ** MESSAGE EVENT ** }
+          Command: Word;                              { Message command }
+          Id     : Word;                              { Message id }
+          Data   : Real;                              { Message data }
+          Case Word Of
+            0: (InfoPtr: Pointer);                    { Message pointer }
+            1: (InfoLong: Longint);                   { Message longint }
+            2: (InfoWord: Word);                      { Message word }
+            3: (InfoInt: Integer);                    { Message integer }
+            4: (InfoByte: Byte);                      { Message byte }
+            5: (InfoChar: Char));                     { Message character }
+   END;
+   PEvent = ^TEvent;
+
+{---------------------------------------------------------------------------}
+{                    ERROR HANDLER FUNCTION DEFINITION                      }
+{---------------------------------------------------------------------------}
+TYPE
+   TSysErrorFunc = FUNCTION (ErrorCode: Integer; Drive: Byte): Integer;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          BUFFER MOVE ROUTINES                             }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-CStrLen------------------------------------------------------------
+Returns the length of string S, where S is a control string using tilde
+characters ('~') to designate shortcut characters. The tildes are
+excluded from the length of the string, as they will not appear on
+the screen. For example, given the string '~B~roccoli' as its
+parameter, CStrLen returns 8.
+25May96 LdB
+---------------------------------------------------------------------}
+FUNCTION CStrLen (Const S: String): Integer;
+
+{-MoveStr------------------------------------------------------------
+Moves a string into a buffer for use with a view's WriteBuf or WriteLine.
+Dest must be a TDrawBuffer (or an equivalent array of words). The
+characters in Str are moved into the low bytes of corresponding words
+in Dest. The high bytes of the words are set to Attr, or remain
+unchanged if Attr is zero.
+25May96 LdB
+---------------------------------------------------------------------}
+PROCEDURE MoveStr (Var Dest; Const Str: String; Attr: Byte);
+
+{-MoveCStr-----------------------------------------------------------
+The characters in Str are moved into the low bytes of corresponding
+words in Dest. The high bytes of the words are set to Lo(Attr) or
+Hi(Attr). Tilde characters (~) in the string toggle between the two
+attribute bytes passed in the Attr word.
+25May96 LdB
+---------------------------------------------------------------------}
+PROCEDURE MoveCStr (Var Dest; Const Str: String; Attrs: Word);
+
+{-MoveBuf------------------------------------------------------------
+Count bytes are moved from Source into the low bytes of corresponding
+words in Dest. The high bytes of the words in Dest are set to Attr,
+or remain unchanged if Attr is zero.
+25May96 LdB
+---------------------------------------------------------------------}
+PROCEDURE MoveBuf (Var Dest, Source; Attr: Byte; Count: Word);
+
+{-MoveChar------------------------------------------------------------
+Moves characters into a buffer for use with a view's WriteBuf or
+WriteLine. Dest must be a TDrawBuffer (or an equivalent array of words).
+The low bytes of the first Count words of Dest are set to C, or
+remain unchanged if Ord(C) is zero. The high bytes of the words are
+set to Attr, or remain unchanged if Attr is zero.
+25May96 LdB
+---------------------------------------------------------------------}
+PROCEDURE MoveChar (Var Dest; C: Char; Attr: Byte; Count: Word);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        KEYBOARD SUPPORT ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-GetAltCode---------------------------------------------------------
+Returns the scancode corresponding to Alt+Ch key that is given.
+25May96 LdB
+---------------------------------------------------------------------}
+FUNCTION GetAltCode (Ch: Char): Word;
+
+{-GetCtrlCode--------------------------------------------------------
+Returns the scancode corresponding to Alt+Ch key that is given.
+25May96 LdB
+---------------------------------------------------------------------}
+FUNCTION GetCtrlCode (Ch: Char): Word;
+
+{-GetAltChar---------------------------------------------------------
+Returns the ascii character for the Alt+Key scancode that was given.
+25May96 LdB
+---------------------------------------------------------------------}
+FUNCTION GetAltChar (KeyCode: Word): Char;
+
+{-GetCtrlChar--------------------------------------------------------
+Returns the ascii character for the Ctrl+Key scancode that was given.
+25May96 LdB
+---------------------------------------------------------------------}
+FUNCTION GetCtrlChar (KeyCode: Word): Char;
+
+{-CtrlToArrow--------------------------------------------------------
+Converts a WordStar-compatible control key code to the corresponding
+cursor key code.
+25May96 LdB
+---------------------------------------------------------------------}
+FUNCTION CtrlToArrow (KeyCode: Word): Word;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        KEYBOARD CONTROL ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-GetShiftState------------------------------------------------------
+Returns a byte containing the current Shift key state. The return
+value contains a combination of the kbXXXX constants for shift states.
+08Jul96 LdB
+---------------------------------------------------------------------}
+FUNCTION GetShiftState: Byte;
+
+{-GetKeyEvent--------------------------------------------------------
+Checks whether a keyboard event is available. If a key has been pressed,
+Event.What is set to evKeyDown and Event.KeyCode is set to the scan
+code of the key. Otherwise, Event.What is set to evNothing.
+19May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE GetKeyEvent (Var Event: TEvent);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          MOUSE CONTROL ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-ShowMouse----------------------------------------------------------
+Decrements the hide counter and if zero the mouse is shown on screen.
+30Jun98 LdB
+---------------------------------------------------------------------}
+PROCEDURE ShowMouse;
+
+{-HideMouse----------------------------------------------------------
+If mouse hide counter is zero it removes the cursor from the screen.
+The hide counter is then incremented by one count.
+30Jun98 LdB
+---------------------------------------------------------------------}
+PROCEDURE HideMouse;
+
+{-GetMouseEvent------------------------------------------------------
+Checks whether a mouse event is available. If a mouse event has occurred,
+Event.What is set to evMouseDown, evMouseUp, evMouseMove, or evMouseAuto
+and the button and double click variables are set appropriately.
+06Jan97 LdB
+---------------------------------------------------------------------}
+PROCEDURE GetMouseEvent (Var Event: TEvent);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                      EVENT HANDLER CONTROL ROUTINES                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-InitEvents---------------------------------------------------------
+Initializes the event manager, enabling the mouse handler routine and
+under DOS/DPMI shows the mouse on screen. It is called automatically
+by TApplication.Init.
+02May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE InitEvents;
+
+{-DoneEvents---------------------------------------------------------
+Terminates event manager and disables the mouse and under DOS hides
+the mouse. It is called automatically by TApplication.Done.
+02May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE DoneEvents;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           VIDEO CONTROL ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-InitVideo---------------------------------------------------------
+Initializes the video manager, Saves the current screen mode in
+StartupMode, and switches to the mode indicated by ScreenMode.
+19May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE InitVideo;
+
+{-DoneVideo---------------------------------------------------------
+Terminates the video manager by restoring the initial screen mode
+(given by StartupMode), clearing the screen, and restoring the cursor.
+Called automatically by TApplication.Done.
+03Jan97 LdB
+---------------------------------------------------------------------}
+PROCEDURE DoneVideo;
+
+{-ClearScreen--------------------------------------------------------
+Does nothing provided for compatability purposes only.
+04Jan97 LdB
+---------------------------------------------------------------------}
+PROCEDURE ClearScreen;
+
+{-SetVideoMode-------------------------------------------------------
+Does nothing provided for compatability purposes only.
+04Jan97 LdB
+---------------------------------------------------------------------}
+PROCEDURE SetVideoMode (Mode: Word);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           ERROR CONTROL ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-InitSysError-------------------------------------------------------
+Error handling is not yet implemented so this simply sets
+SysErrActive=True (ie it lies) and exits.
+20May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE InitSysError;
+
+{-DoneSysError-------------------------------------------------------
+Error handling is not yet implemented so this simply sets
+SysErrActive=False and exits.
+20May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE DoneSysError;
+
+{-SystemError---------------------------------------------------------
+Error handling is not yet implemented so this simply drops through.
+20May98 LdB
+---------------------------------------------------------------------}
+FUNCTION SystemError (ErrorCode: Integer; Drive: Byte): Integer;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           STRING FORMAT ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-PrintStr-----------------------------------------------------------
+Does nothing provided for compatability purposes only.
+30Jun98 LdB
+---------------------------------------------------------------------}
+PROCEDURE PrintStr (CONST S: String);
+
+{-FormatStr----------------------------------------------------------
+A string formatting routine that given a string that includes format
+specifiers and a list of parameters in Params, FormatStr produces a
+formatted output string in Result.
+18Feb99 LdB
+---------------------------------------------------------------------}
+PROCEDURE FormatStr (Var Result: String; CONST Format: String; Var Params);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                 >> NEW QUEUED EVENT HANDLER ROUTINES <<                   }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-PutEventInQueue-----------------------------------------------------
+If there is room in the queue the event is placed in the next vacant
+position in the queue manager.
+17Mar98 LdB
+---------------------------------------------------------------------}
+FUNCTION PutEventInQueue (Var Event: TEvent): Boolean;
+
+{-NextQueuedEvent----------------------------------------------------
+If there are queued events the next event is loaded into event else
+evNothing is returned.
+17Mar98 LdB
+---------------------------------------------------------------------}
+PROCEDURE NextQueuedEvent(Var Event: TEvent);
+
+{***************************************************************************}
+{                        INITIALIZED PUBLIC VARIABLES                       }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                     INITIALIZED DOS/DPMI VARIABLES                        }
+{---------------------------------------------------------------------------}
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+{ ******************************* REMARK ****************************** }
+{    In Hi-Res graphics modes where the usual mouse handler will not    }
+{  work these can be set so the user can provide his own hide, show     }
+{  and redraw on move routines, otherwise leave them set as nil.        }
+{ ****************************** END REMARK *** Leon de Boer, 20Jul98 * }
+TYPE DrawProc = PROCEDURE;
+
+CONST
+   HideMouseProc: DrawProc = Nil;                     { Hide mouse procedure }
+   ShowMouseProc: DrawProc = Nil;                     { Show mouse procedure }
+   MouseMoveProc: DrawProc = Nil;                     { Mouse moved procedure }
+
+PROCEDURE HideMouseCursor;
+PROCEDURE ShowMouseCursor;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                      INITIALIZED WIN/NT VARIABLES                         }
+{---------------------------------------------------------------------------}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+CONST
+   AppWindow    : HWnd = 0;                           { Application window }
+   DefGfvFont   : HFont = 0;                          { Default GFV font }
+   DefFontWeight: Integer = fw_Normal;                { Default font weight }
+   DefFontStyle : String = 'Times New Roman';         { Default font style }
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                        INITIALIZED OS2 VARIABLES                          }
+{---------------------------------------------------------------------------}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+CONST
+   AppWindow   : HWnd = 0;                            { Application window }
+   Anchor      : HAB = 0;                             { Anchor block }
+   MsgQue      : HMq = 0;                             { Message queue }
+   DefGFVFont  : LongInt = 0;                         { Default font style }
+   DefPointer  : HPointer = 0;                        { Default pointer }
+   DefFontStyle: String = 'Times';                    { Default font style }
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                INITIALIZED DOS/DPMI/WIN/NT/OS2 VARIABLES                  }
+{---------------------------------------------------------------------------}
+CONST
+   CheckSnow    : Boolean = False;                    { Compatability only }
+   MouseEvents  : Boolean = False;                    { Mouse event state }
+   MouseReverse : Boolean = False;                    { Mouse reversed }
+   HiResScreen  : Boolean = False;                    { Compatability only }
+   CtrlBreakHit : Boolean = False;                    { Compatability only }
+   SaveCtrlBreak: Boolean = False;                    { Compatability only }
+   SysErrActive : Boolean = False;                    { Compatability only }
+   FailSysErrors: Boolean = False;                    { Compatability only }
+   ButtonCount  : Byte = 0;                           { Mouse button count }
+   DoubleDelay  : Word = 8;                           { Double click delay }
+   RepeatDelay  : Word = 8;                           { Auto mouse delay }
+   SysColorAttr : Word = $4E4F;                       { System colour attr }
+   SysMonoAttr  : Word = $7070;                       { System mono attr }
+   StartupMode  : Word = $FFFF;                       { Compatability only }
+   CursorLines  : Word = $FFFF;                       { Compatability only }
+   ScreenBuffer : Pointer = Nil;                      { Compatability only }
+   SaveInt09    : Pointer = Nil;                      { Compatability only }
+   SysErrorFunc : TSysErrorFunc = SystemError;        { System error ptr }
+
+{---------------------------------------------------------------------------}
+{          >>> NEW INITIALIZED DOS/DPMI/WIN/NT/OS2 VARIABLES <<<            }
+{---------------------------------------------------------------------------}
+CONST
+   DefLineNum     : Integer = 25;                     { Default line number }
+   DefFontHeight  : Integer = 0;                      { Default font height }
+   SysFontWidth   : Integer = 8;                      { System font width }
+   SysFontHeight  : Integer = 16;                     { System font height }
+
+{***************************************************************************}
+{                      UNINITIALIZED PUBLIC VARIABLES                       }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                UNINITIALIZED DOS/DPMI/WIN/NT/OS2 VARIABLES                }
+{---------------------------------------------------------------------------}
+VAR
+   MouseIntFlag: Byte;                                { Mouse in int flag }
+   MouseButtons: Byte;                                { Mouse button state }
+   ScreenWidth : Byte;                                { Screen text width }
+   ScreenHeight: Byte;                                { Screen text height }
+   ScreenMode  : Word;                                { Screen mode }
+   MouseWhere  : TPoint;                              { Mouse position }
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                               IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+  {$IFDEF PPC_FPC}                                    { FPC DOS COMPILER }
+  USES Go32;                                          { Standard unit }
+  {$ENDIF}
+{$ENDIF}
+
+{***************************************************************************}
+{                        PRIVATE INTERNAL CONSTANTS                         }
+{***************************************************************************}
+
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+{---------------------------------------------------------------------------}
+{                 DOS/DPMI MOUSE INTERRUPT EVENT QUEUE SIZE                 }
+{---------------------------------------------------------------------------}
+CONST EventQSize = 16;                                { Default irq bufsize }
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                DOS/DPMI/WIN/NT/OS2 NEW EVENT QUEUE MAX SIZE               }
+{---------------------------------------------------------------------------}
+CONST QueueMax = 64;                                  { Max new queue size }
+
+{***************************************************************************}
+{                          PRIVATE INTERNAL TYPES                           }
+{***************************************************************************}
+
+{$IFDEF OS_WINDOWS}                                   { DOS/DPMI CODE }
+{---------------------------------------------------------------------------}
+{                   SYBIL2+ WIN/NT COMPILER TYPE FIX UPS                    }
+{---------------------------------------------------------------------------}
+   {$IFDEF PPC_SPEED}                                 { SYBIL2+ COMPILER }
+   TYPE TLogFont = LogFont;                           { Type fix up }
+   TYPE TMsg = Msg;                                   { Type fix up }
+   TYPE TTextMetric = TextMetric;                     { Type fix up }
+   {$ENDIF}
+{$ENDIF}
+
+{***************************************************************************}
+{                  PRIVATE INTERNAL INITIALIZED VARIABLES                   }
+{***************************************************************************}
+
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+{---------------------------------------------------------------------------}
+{                       DOS/DPMI INITIALIZED VARIABLES                      }
+{---------------------------------------------------------------------------}
+   {$IFDEF GO32V2}                                    { GO32V2 needs these }
+   CONST
+     RealSeg: Word = 0;                               { Real mode segment }
+     RealOfs: Word = 0;                               { Real mode offset }
+     MouseCallback: Pointer = Nil;                    { Mouse call back ptr }
+   {$ENDIF}
+
+{$ENDIF}
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+{---------------------------------------------------------------------------}
+{           WIN/NT TABLE OF ALT + ASCII CODES FROM VIRTUAL CODES            }
+{---------------------------------------------------------------------------}
+CONST AltVirtualToAscii: Array [0..127] Of Word =
+     ($00, $00, $00, $00, $00, $00, $00, $00,
+      kbAltBack, kbAltTab, $00, $00, $00, kbEnter, $00, $00,
+{10H} $00, $00, $00, $00, $00, $00, $00, $00,
+      $00, $00, $00, kbEsc, $00, $00, $00, $00,
+{20H} kbAltSpace, kbAltPgUp, kbAltPgDn, kbAltEnd, kbAltHome,
+        kbAltLeft, kbAltUp, kbAltRight,
+      kbAltDown, $00, $00, $00, $00, kbAltIns, kbAltDel, $00,
+{30H} kbAlt0, kbAlt1, kbAlt2, kbAlt3, kbAlt4, kbAlt5, kbAlt6, kbAlt7,
+      kbAlt8, kbAlt9, $00, $00, $00, $00, $00, $00,
+{40H} $00, kbAltA, kbAltB, kbAltC, kbAltD, kbAltE, kbAltF, kbAltG,
+      kbAltH, kbAltI, kbAltJ, kbAltK, kbAltL, kbAltM, kbAltN, kbAltO,
+{50H} kbAltP, kbAltQ, kbAltR, kbAltS, kbAltT, kbAltU, kbAltV, kbAltW,
+      kbAltX, kbAltY, kbAltZ, $00, $00, $00, $00, $00,
+{60H} $00, $00, $00, $00, $00, $00, $00, $00,
+      $00, $00, $372A, $4E2B, $00, $4A2D, $00, $352F,
+{70H} kbAltF1, kbAltF2, kbAltF3, kbAltF4, kbAltF5, kbAltF6, kbAltF7, kbAltF8,
+      kbAltF9, kbAltF10, $00, $00, $00, $00, $00, $00);
+
+{---------------------------------------------------------------------------}
+{            WIN/NT TABLE OF WINDOWS ASCII TO INTERNATIONAL ASCII           }
+{---------------------------------------------------------------------------}
+CONST WinAsciiToIntAscii: Array [128..255] Of Byte = (
+{80H} $00, $00, $00, $00, $00, $00, $00, $00,
+      $00, $00, $00, $00, $00, $00, $00, $00,
+{90H} $00, $00, $00, $00, $00, $00, $00, $00,
+      $00, $00, $00, $00, $00, $00, $00, $00,
+{A0H} $00, $AD, $BD, $9C, $CF, $BE, $B3, $F5,
+      $00, $B8, $A6, $AE, $AA, $B0, $A9, $00,
+{B0H} $F8, $F1, $FD, $00, $EF, $E6, $F4, $00,
+      $3C, $3E, $A7, $AF, $AC, $AB, $F3, $A8,
+{C0H} $B7, $B5, $B6, $C7, $8E, $8F, $92, $80,
+      $D4, $90, $D2, $D3, $DE, $D6, $D7, $D8,
+{D0H} $D1, $A5, $E3, $E0, $E2, $E5, $99, $00,
+      $9D, $EB, $E9, $EA, $9A, $ED, $E7, $E1,
+{E0H} $85, $A0, $83, $C6, $84, $86, $91, $87,
+      $8A, $82, $88, $89, $8D, $A1, $8C, $8B,
+{F0H} $D0, $A4, $95, $A2, $93, $E4, $94, $F6,
+      $9B, $97, $A3, $96, $81, $EC, $E8, $98);
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{          DOS/DPMI/WIN/NT/OS2 ALT KEY SCANCODES FROM KEYS (0-127)          }
+{---------------------------------------------------------------------------}
+CONST AltCodes: Array [0..127] Of Byte = (
+      $00, $00, $00, $00, $00, $00, $00, $00,         { $00 - $07 }
+      $00, $00, $00, $00, $00, $00, $00, $00,         { $08 - $0F }
+      $00, $00, $00, $00, $00, $00, $00, $00,         { $10 - $17 }
+      $00, $00, $00, $00, $00, $00, $00, $00,         { $18 - $1F }
+      $00, $00, $00, $00, $00, $00, $00, $00,         { $20 - $27 }
+      $00, $00, $00, $00, $00, $82, $00, $00,         { $28 - $2F }
+      $81, $78, $79, $7A, $7B, $7C, $7D, $7E,         { $30 - $37 }
+      $7F, $80, $00, $00, $00, $83, $00, $00,         { $38 - $3F }
+      $00, $1E, $30, $2E, $20, $12, $21, $22,         { $40 - $47 }
+      $23, $17, $24, $25, $26, $32, $31, $18,         { $48 - $4F }
+      $19, $10, $13, $1F, $14, $16, $2F, $11,         { $50 - $57 }
+      $2D, $15, $2C, $00, $00, $00, $00, $00,         { $58 - $5F }
+      $00, $00, $00, $00, $00, $00, $00, $00,         { $60 - $67 }
+      $00, $00, $00, $00, $00, $00, $00, $00,         { $68 - $6F }
+      $00, $00, $00, $00, $00, $00, $00, $00,         { $70 - $77 }
+      $00, $00, $00, $00, $00, $00, $00, $00);        { $78 - $7F }
+
+{***************************************************************************}
+{                  PRIVATE INTERNAL INITIALIZED VARIABLES                   }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                           NEW CONTROL VARIABLES                           }
+{---------------------------------------------------------------------------}
+CONST
+   HideCount : Integer = 0;                           { Cursor hide count }
+   QueueCount: Word = 0;                              { Queued message count }
+   QueueHead : Word = 0;                              { Queue head pointer }
+   QueueTail : Word = 0;                              { Queue tail pointer }
+
+{***************************************************************************}
+{                 PRIVATE INTERNAL UNINITIALIZED VARIABLES                  }
+{***************************************************************************}
+
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+{---------------------------------------------------------------------------}
+{                     UNINITIALIZED DOS/DPMI VARIABLES                      }
+{---------------------------------------------------------------------------}
+VAR
+   LastDouble : Boolean;                              { Last double buttons }
+   LastButtons: Byte;                                 { Last button state }
+   DownButtons: Byte;                                 { Last down buttons }
+   EventCount : Word;                                 { Events in queue }
+   AutoDelay  : Word;                                 { Delay time count }
+   DownTicks  : Word;                                 { Down key tick count }
+   AutoTicks  : Word;                                 { Held key tick count }
+   LastWhereX : Word;                                 { Last x position }
+   LastWhereY : Word;                                 { Last y position }
+   DownWhereX : Word;                                 { Last x position }
+   DownWhereY : Word;                                 { Last y position }
+   EventQHead : Pointer;                              { Head of queue }
+   EventQTail : Pointer;                              { Tail of queue }
+   EventQueue : Array [0..EventQSize - 1] Of TEvent;  { Event queue }
+   EventQLast : RECORD END;                           { Simple end marker }
+
+{---------------------------------------------------------------------------}
+{                ABSOLUTE PRIVATE DOS/DPMI ADDRESS VARIABLES                }
+{---------------------------------------------------------------------------}
+VAR
+   {$IFNDEF GO32V1}
+   ShiftState: Byte Absolute $40:$17;                 { Shift state mask }
+   Ticks: Word Absolute $40:$6C;                      { DOS tick counter }
+   {$ENDIF}
+
+   {$IFDEF GO32V2}                                    { GO32V2 registers }
+   ActionRegs: TRealRegs;                             { Real mode registers }
+   {$ENDIF}
+
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                UNINITIALIZED DOS/DPMI/WIN/NT/OS2 VARIABLES                }
+{---------------------------------------------------------------------------}
+VAR
+   SaveExit: Pointer;                                 { Saved exit pointer }
+   Queue   : Array [0..QueueMax-1] Of TEvent;         { New message queue }
+
+{***************************************************************************}
+{                         PRIVATE INTERNAL ROUTINES                         }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                  DOS/DPMI ONLY PRIVATE INTERNAL ROUTINES                  }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+
+{$IFDEF GO32V2}                                       { GO32V2 CODE }
+{---------------------------------------------------------------------------}
+{  MouseTrap -> Platforms GO32V2 - FPC COMPILER Updated 10Sep98 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE Mouse_Trap; FAR; ASSEMBLER;
+ASM
+   PUSH %ES;                                          { Save ES register }
+   PUSH %DS;                                          { Save DS register }
+   PUSHL %EDI;                                        { Save register }
+   PUSHL %ESI;                                        { Save register }
+   ;{ caution : ds is not the selector for our data !! }
+   PUSH %ES;                                          { Push data seg }
+   POP %DS;                                           { Load data seg }
+   PUSHL %EDI;                                        { Actionregs address }
+   MOVL MOUSECALLBACK, %EAX;                          { Fetch callback addr }
+   CMPL $0, %EAX;                                     { Check for nil ptr }
+   JS .L_NoCallBack;                                  { Ignore if nil }
+   POPL %EAX;                                         { %EAX = @actionregs }
+   MOVL (%EAX), %EDI;                                 { EDI from actionregs }
+   MOVL 4(%EAX), %ESI;                                { ESI from actionregs }
+   MOVL 16(%EAX), %EBX;                               { EBX from actionregs }
+   MOVL 20(%EAX), %EDX;                               { EDX from actionregs }
+   MOVL 24(%EAX), %ECX;                               { ECX from actionregs }
+   MOVL 28(%EAX), %EAX;                               { EAX from actionregs }
+   CALL *MOUSECALLBACK;                               { Call callback proc }
+.L_NoCallBack:
+   POPL %ESI;                                         { Recover register }
+   POPL %EDI;                                         { Recover register }
+   POP %DS;                                           { Restore DS register }
+   POP %ES;                                           { Restore ES register }
+   MOVL (%ESI), %EAX;
+   MOVL %EAX, %ES:42(%EDI);                           { Set as return addr }
+   ADDW $4, %ES:46(%EDI);                             { adjust stack }
+   IRET;                                              { Interrupt return }
+END;
+{$ENDIF}
+
+{$IFDEF PPC_FPC}                                      { FPC COMPILER CODE }
+{---------------------------------------------------------------------------}
+{  Mouse_Action -> Platforms DPMI - FPC COMPILER Updated 10Sep98 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE Mouse_Action (Mask : Integer; P : Pointer);
+VAR Error: Word; ErrStr: String; {$IFDEF GO32V2} Rg: TRealRegs; {$ENDIF}
+BEGIN
+   {$IFDEF GO32V1}                                    { GO32V1 CODE }
+   ErrStr := 'GO32V1 mouse handler set failed !!';    { Set error string }
+   ASM
+     MOVL $0xFF, %EAX;                                { GO32v1 special id }
+     MOVL P, %ECX;                                    { Fuction to chain }
+     MOVL $0x20, %EBX;                                { Event queue size > 0 }
+     MOVL $0x12345678, %EDX;                          { Test for version ? }
+     INT $0x33;                                       { Call special wrapper }
+     CMPW $0xFF0, %AX;                                { AX=$FF0 if success }
+     JNZ .L_GO32V1Err;
+     MOVW $0, %AX;                                    { Zero register }
+     JMP .LGO32V1Ok;                                  { Now jump over }
+   .L_GO32V1Err:
+     MOVW $0xFFFF, %AX;                               { -1 to register }
+   .L_GO32V1Ok:
+     MOVW %AX, Error;                                 { Set error result }
+   END;
+   {$ENDIF}
+   {$IFDEF GO32V2}                                    { GO32V2 CODE }
+   Error := 0;                                        { Preset no error }
+   ErrStr := 'GO32V2 mouse handler set failed !!';    { Set error string }
+   If (P <> MouseCallBack) Then Begin                 { Check func different }
+     If (RealSeg <> 0) Then Begin                     { Remove old calback }
+       Rg.AX := 12;                                   { Function id }
+       Rg.CX := 0;                                    { Zero mask register }
+       Rg.ES := 0;                                    { Zero proc seg }
+       Rg.DX := 0;                                    { Zero proc ofs }
+       RealIntr($33, Rg);                             { Stop INT 33 callback }
+       ASM
+         MOVW $0x304, %AX;                            { Set function id }
+         MOVW REALSEG, %CX;                           { Bridged real seg }
+         MOVW REALOFS, %DX;                           { Bridged real ofs }
+         INT $0x31;                                   { Release bridge }
+       END;
+     End;
+     MouseCallback := P;                              { Set call back addr }
+     If (P <> Nil) Then Begin                         { Check non nil proc }
+       ASM
+         LEAL ACTIONREGS, %EDI;                       { Addr of actionregs }
+         LEAL MOUSE_TRAP, %ESI;                       { Procedure address }
+         PUSH %DS;                                    { Save DS segment }
+         PUSH %ES;                                    { Save ES segment }
+         PUSH %DS;
+         POP  %ES;                                    { ES now has dataseg }
+         PUSH %CS;
+         POP  %DS;                                    { DS now has codeseg }
+         MOVW $0x303, %AX;                            { Function id }
+         INT  $0x31;                                  { Call DPMI bridge }
+         POP  %ES;                                    { Restore ES segment }
+         POP  %DS;                                    { Restore DS segment }
+         MOVW %CX, REALSEG;                           { Transfer real seg }
+         MOVW %DX, REALOFS;                           { Transfer real ofs }
+         MOVW $0, %AX;                                { Preset zero error }
+         JNC .L_call_ok;                              { Branch if ok }
+         MOVW $0xFFFF, %AX;                           { Force a -1 error }
+       .L_call_ok:
+         MOVW %AX, ERROR;                             { Return error state }
+       END;
+       Rg.CX := Mask;                                 { Set mask register }
+     End Else Begin
+       Rg.EDI := 0;                                   { Zero proc register }
+       Rg.CX := 0;                                    { Zero mask register }
+     End;
+     If (Error = 0) Then Begin                        { If no error }
+       Rg.AX := 12;                                   { Set function id }
+       Rg.ES := RealSeg;                              { Real mode segment }
+       Rg.DX := RealOfs;                              { Real mode offset }
+       RealIntr($33, Rg);                             { Set interrupt 33 }
+     End Else Begin
+       RealSeg := 0;                                  { Zero real mode seg }
+       RealOfs := 0;                                  { Zero real mode ofs }
+     End;
+   End;
+   {$ENDIF}
+   If (Error <> 0) Then Begin                         { Error encountered }
+     WriteLn(ErrStr);                                 { Write error }
+     ReadLn;                                          { Wait for user to see }
+   End;
+END;
+
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  MouseInt -> Platforms DOS/DPMI - Updated 30Jun98 LdB                     }
+{---------------------------------------------------------------------------}
+PROCEDURE MouseInt; FAR; ASSEMBLER;
+{$IFDEF ASM_BP}                                       { BP COMPATABLE ASM }
+ASM
+   MOV SI, SEG @DATA;                                 { Fetch data segment }
+   MOV DS, SI;                                        { Fix data segment }
+   MOV SI, CX;                                        { Transfer x position }
+   MOV MouseButtons, BL;                              { Update mouse buttons }
+   MOV MouseWhere.X, SI;                              { Update x position }
+   MOV MouseWhere.Y, DX;                              { Update y position }
+   CMP EventCount, EventQSize;                        { Check if queue full }
+   JZ @@QueueFull;                                    { Queue is full exit }
+   MOV ES, Seg0040;                                   { Fetch DOS segment }
+   MOV AX, ES:Ticks;                                  { Fetch dos tick count }
+   MOV DI, WORD PTR EventQTail;                       { Address of tail }
+   PUSH DS;                                           { Push to stack }
+   POP ES;                                            { ES to data segment }
+   CLD;                                               { Store forward }
+   STOSW;                                             { Store tick count }
+   XCHG AX, BX;                                       { Transfer register }
+   STOSW;                                             { Store button state }
+   XCHG AX, SI;                                       { Transfer register }
+   STOSW;                                             { Store x position }
+   XCHG AX, DX;                                       { Transfer register }
+   STOSW;                                             { Store y position }
+   CMP DI, OFFSET EventQLast;                         { Roll if at queue end }
+   JNE @@NoRollNeeded;                                { Not at queue end }
+   MOV DI, OFFSET EventQueue;                         { Roll back to start }
+@@NoRollNeeded:
+   MOV WORD PTR EventQTail, DI;                       { Update queue tail }
+   INC EventCount;                                    { One message added }
+@@QueueFull:
+   MOV MouseIntFlag, 1;                               { Set interrupt flag }
+   MOV SI, WORD PTR MouseMoveProc;                    { Low address word }
+   OR SI, WORD PTR MouseMoveProc+2;                   { "OR" high word }
+   JZ @@Exit;                                         { No move call so exit }
+   DB $66; PUSH AX;                                   { Store EAX }
+   DB $66; PUSH BX;                                   { Store EBX }
+   DB $66; PUSH CX;                                   { Store ECX }
+   DB $66; PUSH DX;                                   { Store EDX }
+   DB $66; PUSH SI;                                   { Store ESI }
+   DB $66; PUSH DI;                                   { Store EDI }
+   DB $66; PUSH BP;                                   { Store EBP }
+   PUSH ES;                                           { Store ES }
+   PUSH BP;                                           { Standard BP push }
+   MOV BP, SP;                                        { Transfer stack ptr }
+   CALL MouseMoveProc;                                { Standard procedure }
+   POP BP;                                            { Standard BP recover }
+   POP ES;                                            { Recover ES }
+   DB $66; POP BP;                                    { Recover EBP }
+   DB $66; POP DI;                                    { Recover EDI }
+   DB $66; POP SI;                                    { Recover ESI }
+   DB $66; POP DX;                                    { Recover EDX }
+   DB $66; POP CX;                                    { Recover ECX }
+   DB $66; POP BX;                                    { Recover EBX }
+   DB $66; POP AX;                                    { Recover EAX }
+@@Exit:
+END;
+{$ENDIF}
+{$IFDEF ASM_FPC}                                      { FPC COMPATABLE ASM }
+ASM
+   MOVW %CX, %SI;                                     { Transfer x position }
+   MOVB %BL, MOUSEBUTTONS;                            { Update mouse buttons }
+   MOVW %SI, MOUSEWHERE;                              { Update x position }
+   MOVW %DX, MOUSEWHERE+2;                            { Update y position }
+   CMPW $16, EVENTCOUNT;                              { Check if queue full }
+   JZ .L_QueueFull;                                   { Queue is full exit }
+   PUSH %ES;                                          { Save segment }
+   MOVW $0x40, %AX;                                   { Fetch DOS segment }
+   MOVW %AX, %ES;                                     { Transfer to segment }
+   MOVL $0x6C, %EDI;                                  { Address of ticks }
+   MOVW %ES:(%EDI), %AX;                              { Fetch dos tick count }
+   POP %ES;                                           { Recover segment }
+   MOVL EVENTQTAIL, %EDI;                             { Queue tail address }
+   CLD;                                               { Store forward }
+   STOSW;                                             { Store tick count }
+   XCHGW %BX, %AX;                                    { Transfer register }
+   STOSW;                                             { Store button state }
+   XCHGW %SI, %AX;                                    { Transfer register }
+   STOSW;                                             { Store x position }
+   XCHGW %DX, %AX;                                    { Transfer register }
+   STOSW;                                             { Store y position }
+   LEAL EVENTQLAST, %EAX;                             { Roll point address }
+   CMPL %EAX, %EDI;                                   { Roll if at queue end }
+   JNE .L_NoRollNeeded;                               { Not at queue end }
+   LEAL EVENTQUEUE, %EDI;                             { Roll back to start }
+.L_NoRollNeeded:
+   MOVL %EDI, EVENTQTAIL;                             { Update queue tail }
+   INCW EVENTCOUNT;                                   { One message added }
+.L_QueueFull:
+   MOVB $1, MOUSEINTFLAG;                             { Set interrupt flag }
+   MOVL MOUSEMOVEPROC, %EAX;                          { Load proc address }
+   CMPL $0, %EAX;                                     { Check for nil ptr }
+   JZ .L_Exit;                                        { No move call so exit }
+   PUSHL %EAX;                                        { Store EAX }
+   PUSHL %EBX;                                        { Store EBX }
+   PUSHL %ECX;                                        { Store ECX }
+   PUSHL %EDX;                                        { Store EDX }
+   PUSHL %ESI;                                        { Store ESI }
+   PUSHL %EDI;                                        { Store EDI }
+   PUSHL %EBP;                                        { Store EBP }
+   PUSH %ES;                                          { Store ES }
+   CALL %EAX;                                         { Standard procedure }
+   POP %ES;                                           { Recover ES }
+   POPL %EBP;                                         { Recover EBP }
+   POPL %EDI;                                         { Recover EDI }
+   POPL %ESI;                                         { Recover ESI }
+   POPL %EDX;                                         { Recover EDX }
+   POPL %ECX;                                         { Recover ECX }
+   POPL %EBX;                                         { Recover EBX }
+   POPL %EAX;                                         { Recover EAX }
+.L_Exit:
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  HideMouseCursor -> Platforms DOS/DPMI - Updated 10Sep98 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE HideMouseCursor; ASSEMBLER;
+{$IFDEF ASM_BP}                                       { BP COMPATABLE ASM }
+ASM
+   CMP MouseEvents, 0;                                { Check mouse system }
+   JZ @@Exit;                                         { Branch if not active }
+   MOV AX, WORD PTR [HideMouseProc];                  { Fetch offset of addr }
+   OR AX, WORD PTR [HideMouseProc+2];                 { Check for nil ptr }
+   JZ @@UseMouseInt;                                  { Branch if nil }
+   CALL FAR PTR [HideMouseProc];                      { Call hide mouse }
+   JMP @@Exit;                                        { Now exit }
+@@UseMouseInt:
+   MOV AX, $2;                                        { Load function id }
+   PUSH BP;                                           { Safety!! save reg }
+   INT $33;                                           { Hide the mouse }
+   POP BP;                                            { Restore register }
+@@Exit:
+END;
+{$ENDIF}
+{$IFDEF ASM_FPC}                                      { FPC COMPATABLE ASM }
+ASM
+   CMPB $0, MouseEvents;                              { Check mouse system }
+   JZ .L_Exit;                                        { Branch if not active }
+   MOVL HideMouseProc, %EAX;                          { Fetch address }
+   ORL %EAX, %EAX;                                    { Check for nil ptr }
+   JZ .L_UseMouseInt;                                 { Branch if nil }
+   CALL HideMouseProc;                                { Call show mouse }
+   JMP .L_Exit;                                       { Now exit }
+.L_UseMouseInt:
+   MOVW $2, %AX;                                      { Load function id }
+   PUSHL %EBP;                                        { Save regigister }
+   INT $0x33;                                         { Hide the mouse }
+   POPL %EBP;                                         { Restore register }
+.L_Exit:
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  ShowMouseCursor -> Platforms DOS/DPMI - Updated 10Sep98 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE ShowMouseCursor; ASSEMBLER;
+{$IFDEF ASM_BP}                                       { BP COMPATABLE ASM }
+ASM
+   CMP MouseEvents, 0;                                { Check mouse system }
+   JZ @@Exit;                                         { Branch if not active }
+   MOV AX, WORD PTR [ShowMouseProc];                  { Fetch offset of addr }
+   OR AX, WORD PTR [ShowMouseProc+2];                 { Check for nil ptr }
+   JZ @@UseMouseInt;                                  { Branch if nil }
+   CALL FAR PTR [ShowMouseProc];                      { Call show mouse }
+   JMP @@Exit;                                        { Now exit }
+@@UseMouseInt:
+   MOV AX, $1;                                        { Load function id }
+   PUSH BP;                                           { Safety!! save reg }
+   INT $33;                                           { Show the mouse }
+   POP BP;                                            { Restore register }
+@@Exit:
+END;
+{$ENDIF}
+{$IFDEF ASM_FPC}                                      { FPC COMPATABLE ASM }
+ASM
+   CMPB $0, MouseEvents;                              { Check mouse system }
+   JZ .L_Exit;                                        { Branch if not active }
+   MOVL ShowMouseProc, %EAX;                          { Fetch address }
+   ORL %EAX, %EAX;                                    { Check for nil ptr }
+   JZ .L_UseMouseInt;                                 { Branch if nil }
+   CALL ShowMouseProc;                                { Call show mouse }
+   JMP .L_Exit;                                       { Now exit }
+.L_UseMouseInt:
+   MOVW $1, %AX;                                      { Load function id }
+   PUSHL %EBP;                                        { Save regigister }
+   INT $0x33;                                         { Hide the mouse }
+   POPL %EBP;                                         { Restore register }
+.L_Exit:
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  HookMouse -> Platforms DOS/DPMI - Updated 27Aug98 LdB                    }
+{---------------------------------------------------------------------------}
+PROCEDURE HookMouse;
+BEGIN
+   {$IFDEF ASM_BP}                                    { BP COMPTABABLE ASM }
+   ASM
+     MOV AX, $000C;                                   { Set user interrupt }
+     MOV CX, $FFFF;                                   { For all event masks }
+     MOV DX, OFFSET CS:MouseInt;                      { Mouse int is hook }
+     PUSH CS;                                         { Push code segment }
+     POP ES;                                          { ES:DX -> MouseInt }
+     PUSH BP;                                         { Safety!! save reg }
+     INT $33;                                         { Hook the routine }
+     POP BP;                                          { Restore register }
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+     {$IFDEF GO32V2}                                  { GO32V2 CODE }
+     Lock_Code(Pointer(@Mouse_Trap), 400);            { Lock trap code }
+     Lock_Data(ActionRegs, SizeOf(ActionRegs));       { Lock registers }
+     {$ENDIF}
+   Mouse_Action(-1, @MouseInt);                       { Set masks/interrupt }
+   {$ENDIF}
+END;
+
+
+{---------------------------------------------------------------------------}
+{  UnHookMouse -> Platforms DOS/DPMI - Updated 27Aug98 LdB                  }
+{---------------------------------------------------------------------------}
+PROCEDURE UnHookMouse;
+BEGIN
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASM
+     MOV AX, $000C;                                   { Set user interrupt }
+     XOR CX, CX;                                      { Clear all masks }
+     XOR DX, DX;                                      { Clear register }
+     MOV ES, CX;                                      { ES:DX -> Nil }
+     PUSH BP;                                         { Safety!! save reg }
+     INT $33;                                         { Release mouse hook }
+     POP BP;                                          { Restore register }
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   Mouse_Action(0, Nil);                              { Clear mask/interrupt }
+     {$IFDEF GO32V2}                                  { GO32V2 CODE }
+     Unlock_Code(Pointer(@Mouse_Trap), 400);          { Release trap code }
+     Unlock_Data(ActionRegs, SizeOf(TRealRegs));      { Release registers }
+     {$ENDIF}
+   {$ENDIF}
+END;
+
+{---------------------------------------------------------------------------}
+{  GetMousePosition -> Platforms DOS/DPMI - Updated 19May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE GetMousePosition (Var X, Y: Integer); ASSEMBLER;
+{$IFDEF ASM_BP}                                       { BP COMPATABLE ASM }
+ASM
+   MOV AX, $3;                                        { Set function id }
+   PUSH BP;                                           { Safety!! save reg }
+   INT $33;                                           { Get button data }
+   POP BP;                                            { Restore register }
+   LES DI, X;                                         { Adress of x }
+   MOV ES:[DI], CX;                                   { Return x position }
+   LES DI, Y;                                         { Adress of y }
+   MOV ES:[DI], DX;                                   { Return y position }
+END;
+{$ENDIF}
+{$IFDEF ASM_FPC}                                      { FPC COMPATABLE ASM }
+ASM
+   MOVW $3, %AX;                                      { Set function id }
+   PUSHL %EBP;                                        { Save register }
+   INT $0x33;                                         { Get button data }
+   POPL %EBP;                                         { Restore register }
+   MOVL X, %EDI;                                      { Adress of x }
+   MOVW %CX, (%EDI);                                  { Return x position }
+   MOVL Y, %EDI;                                      { Adress of y }
+   MOVW %DX, (%EDI);                                  { Return y position }
+END;
+{$ENDIF}
+
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{               DOS/DPMI/WIN/NT/OS2 PRIVATE INTERNAL ROUTINES               }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  ExitDrivers -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jun98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE ExitDrivers; FAR;
+BEGIN
+   DoneSysError;                                      { Relase error trap }
+   DoneEvents;                                        { Close event driver }
+   ExitProc := SaveExit;                              { Restore old exit }
+END;
+
+{---------------------------------------------------------------------------}
+{  DetectVideo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE DetectVideo;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+ASSEMBLER;
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASM
+     MOV AH, $0F;                                     { Set function id }
+     PUSH BP;                                         { Safety!! save reg }
+     INT $10;                                         { Get current crt mode }
+     POP BP;                                          { Restore register }
+     PUSH AX;                                         { Hold result }
+     MOV AX, $1130;                                   { Set function id }
+     MOV BH, 0;                                       { Zero register }
+     MOV DL, 0;                                       { Zero register }
+     PUSH BP;                                         { Safety!! save reg }
+     INT $10;                                         { Get ext-video mode }
+     POP BP;                                          { Restore register }
+     POP AX;                                          { Recover held value }
+     MOV DH, AH;                                      { Transfer high mode }
+     CMP DL, 25;                                      { Check screen ht }
+     SBB AH, AH;                                      { Subtract borrow }
+     INC AH;                                          { Make #1 if in high }
+     CMP AL, smMono;                                  { Is screen mono }
+     JZ @@Exit1;                                      { Exit of mono }
+     CMP AL, smBW80;                                  { Is screen B&W }
+     JZ @@Exit1;                                      { Exit if B&W }
+     MOV AX, smCO80;                                  { Else set to colour }
+   @@Exit1:
+     MOV ScreenMode, AX;                              { Hold screen mode }
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   ASM
+     MOVB $0x0F, %AH;                                 { Set function id }
+     PUSHL %EBP;                                      { Save register }
+     INT $0x10;                                       { Get current crt mode }
+     POPL %EBP;                                       { Restore register }
+     PUSHL %EAX;                                      { Hold result }
+     MOVW $0x1130, %AX;                               { Set function id }
+     MOVB $0, %BH;                                    { Zero register }
+     MOVB $0, %DL;                                    { Zero register }
+     PUSHL %EBP;                                      { Safety!! save reg }
+     INT $0x10;                                       { Get ext-video mode }
+     POPL %EBP;                                       { Restore register }
+     POPL %EAX;                                       { Recover held value }
+     MOVB %AH, %DH;                                   { Transfer high mode }
+     CMPB $25, %DL;                                   { Check screen ht }
+     SBB %AH, %AH;                                    { Subtract borrow }
+     INCB %AH;                                        { Make #1 if in high }
+     CMPB $07, %AL;                                   { Is screen mono }
+     JZ .L_Exit1;                                     { Exit of mono }
+     CMPB $02, %AL;                                   { Is screen B&W }
+     JZ .L_Exit1;                                     { Exit if B&W }
+     MOVW $03, %AX;                                   { Else set to colour }
+   .L_Exit1:
+     MOVW %AX, SCREENMODE;                            { Hold screen mode }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+VAR Dc: HDC;
+BEGIN
+   Dc := GetDc(0);                                    { Get screen context }
+   If ((GetDeviceCaps(Dc, BitsPixel) > 1) OR          { Colour capacity }
+   (GetDeviceCaps(Dc, Planes) > 1)) Then              { Colour capacity }
+     ScreenMode := smCO80 Else ScreenMode := smMono;  { Screen mode }
+   ReleaseDc(0, Dc);                                  { Release context }
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+VAR Ps: Hps; Dc: Hdc; Colours: LongInt;
+BEGIN
+   Ps := WinGetPS(HWND_Desktop);                      { Get desktop PS }
+   Dc := GpiQueryDevice(Ps);                          { Get gpi context }
+   DevQueryCaps(Dc, Caps_Phys_Colors, 1, Colours);    { Colour capacity }
+   If (Colours> 2) Then ScreenMode := smCO80          { Colour screen }
+     Else ScreenMode := smMono;                       { Mono screen }
+   WinReleasePS(Ps);                                  { Release desktop PS }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  DetectMouse -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May98 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION DetectMouse: Byte;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOV AX, $3533;                                   { Set function id }
+     PUSH BP;                                         { Safety!! save reg }
+     INT $21;                                         { Get mouse interrupt }
+     POP BP;                                          { Restore register }
+     MOV AX, ES;                                      { Transfer register }
+     OR AX, BX;                                       { Check for nil ptr }
+     JZ @@Exit2;                                      { Jump no mouse driver }
+     XOR AX, AX;                                      { Set function id }
+     PUSH BP;                                         { Safety!! save reg }
+     INT $33;                                         { Reset mouse }
+     POP BP;                                          { Restore register }
+     OR AX, AX;                                       { Check for success }
+     JZ @@Exit2;                                      { Reset mouse failed }
+     MOV AX, BX;                                      { Return button count }
+   @@Exit2:
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOVW $0x200, %AX;                                { Get real mode int }
+     MOVW $0x33, %BX;                                 { Vector 33H }
+     PUSHL %EBP;                                      { Save register }
+     INT $0x31;                                       { Get the address }
+     POPL %EBP;                                       { Restore register }
+     MOVW %CX, %AX;                                   { Transfer register }
+     ORW %DX, %AX;                                    { Check for nil ptr }
+     JZ .L_Exit2;                                     { Jump no mouse driver }
+     XORW %AX, %AX;                                   { Set function id }
+     PUSHL %EBP;                                      { Save register }
+     INT $0x33;                                       { Reset mouse driver }
+     POPL %EBP;                                       { Restore register }
+     ORW %AX, %AX;                                    { Check for success }
+     JZ .L_Exit2;                                     { Reset mouse failed }
+     MOVW %BX, %AX;                                   { Return button count }
+   .L_Exit2:
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+BEGIN
+   If (GetSystemMetrics(sm_MousePresent) <> 0) Then
+     DetectMouse := 2 Else DetectMouse := 0;          { Buttons present }
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+BEGIN
+   DetectMouse := WinQuerySysValue(HWND_Desktop,
+     SV_CMouseButtons);                               { Buttons present }
+END;
+{$ENDIF}
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           BUFFER MOVE ROUTINES                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  CStrLen -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25May96 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION CStrLen (Const S: String): Integer;
+VAR I, J: Integer;
+BEGIN
+   J := 0;                                            { Set result to zero }
+   For I := 1 To Length(S) Do
+     If (S[I] <> '~') Then Inc(J);                    { Inc count if not ~ }
+   CStrLen := J;                                      { Return length }
+END;
+
+{---------------------------------------------------------------------------}
+{  MoveStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10Jul99 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE MoveStr (Var Dest; Const Str: String; Attr: Byte);
+VAR I: Word; P: PWord;
+BEGIN
+   For I := 1 To Length(Str) Do Begin                 { For each character }
+     P := @TWordArray(Dest)[I-1];                     { Pointer to word }
+     If (Attr <> 0) Then WordRec(P^).Hi := Attr;      { Copy attribute }
+     WordRec(P^).Lo := Byte(Str[I]);                  { Copy string char }
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  MoveCStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10Jul99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE MoveCStr (Var Dest; Const Str: String; Attrs: Word);
+VAR B: Byte; I, J: Word; P: PWord;
+BEGIN
+   J := 0;                                            { Start position }
+   For I := 1 To Length(Str) Do Begin                 { For each character }
+     If (Str[I] <> '~') Then Begin                    { Not tilde character }
+       P := @TWordArray(Dest)[J];                     { Pointer to word }
+       If (Lo(Attrs) <> 0) Then
+         WordRec(P^).Hi := Lo(Attrs);                 { Copy attribute }
+       WordRec(P^).Lo := Byte(Str[I]);                { Copy string char }
+       Inc(J);                                        { Next position }
+     End Else Begin
+       B := Hi(Attrs);                                { Hold attribute }
+       WordRec(Attrs).Hi := Lo(Attrs);                { Copy low to high }
+       WordRec(Attrs).Lo := B;                        { Complete exchange }
+     End;
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  MoveBuf -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10Jul99 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE MoveBuf (Var Dest, Source; Attr: Byte; Count: Word);
+VAR I: Word; P: PWord;
+BEGIN
+   For I := 1 To Count Do Begin
+     P := @TWordArray(Dest)[I-1];                     { Pointer to word }
+     If (Attr <> 0) Then WordRec(P^).Hi := Attr;      { Copy attribute }
+     WordRec(P^).Lo := TByteArray(Source)[I-1];       { Copy source data }
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  MoveChar -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10Jul99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE MoveChar (Var Dest; C: Char; Attr: Byte; Count: Word);
+VAR I: Word; P: PWord;
+BEGIN
+   For I := 1 To Count Do Begin
+     P := @TWordArray(Dest)[I-1];                     { Pointer to word }
+     If (Attr <> 0) Then WordRec(P^).Hi := Attr;      { Copy attribute }
+     If (Ord(C) <> 0) Then WordRec(P^).Lo := Byte(C); { Copy character }
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        KEYBOARD SUPPORT ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  GetAltCode -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25May96 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION GetAltCode (Ch: Char): Word;
+BEGIN
+   GetAltCode := 0;                                   { Preset zero return }
+   Ch := UpCase(Ch);                                  { Convert upper case }
+   If (Ch < #128) Then
+     GetAltCode := AltCodes[Ord(Ch)] SHL 8            { Return code }
+     Else If (Ch = #240) Then GetAltCode := $0200     { Return code }
+       Else GetAltCode := 0;                          { Return zero }
+END;
+
+{---------------------------------------------------------------------------}
+{  GetCtrlCode -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25May96 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION GetCtrlCode (Ch: Char): Word;
+BEGIN
+   GetCtrlCode := GetAltCode(Ch) OR (Ord(Ch) - $40);  { Ctrl+key code }
+END;
+
+{---------------------------------------------------------------------------}
+{  GetAltChar -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25May96 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION GetAltChar (KeyCode: Word): Char;
+VAR I: Integer;
+BEGIN
+   GetAltChar := #0;                                  { Preset fail return }
+   If (Lo(KeyCode) = 0) Then Begin                    { Extended key }
+     If (Hi(KeyCode) < 128) Then Begin                { Key between 0-127 }
+       I := 0;                                        { Start at first }
+       While (I < 128) AND (Hi(KeyCode) <> AltCodes[I])
+         Do Inc(I);                                   { Search for match }
+       If (I < 128) Then GetAltChar := Chr(I);        { Return character }
+     End Else
+       If (Hi(KeyCode)=$02) Then GetAltChar := #240;  { Return char }
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  GetCtrlChar -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25May96 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION GetCtrlChar (KeyCode: Word): Char;
+VAR C: Char;
+BEGIN
+  C := #0;                                            { Preset #0 return }
+  If (Lo(KeyCode) > 0) AND (Lo(KeyCode) <= 26) Then   { Between 1-26 }
+    C := Chr(Lo(KeyCode) + $40);                      { Return char A-Z }
+  GetCtrlChar := C;                                   { Return result }
+END;
+
+{---------------------------------------------------------------------------}
+{  CtrlToArrow -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25May96 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION CtrlToArrow (KeyCode: Word): Word;
+CONST NumCodes = 11;
+      CtrlCodes : Array [0..NumCodes-1] Of Char =
+        (#19, #4, #5, #24, #1, #6, #7, #22, #18, #3, #8);
+      ArrowCodes: Array [0..NumCodes-1] Of Word =
+       (kbLeft, kbRight, kbUp, kbDown, kbHome, kbEnd, kbDel, kbIns,
+        kbPgUp, kbPgDn, kbBack);
+VAR I: Integer;
+BEGIN
+   CtrlToArrow := KeyCode;                            { Preset key return }
+   For I := 0 To NumCodes - 1 Do
+     If WordRec(KeyCode).Lo = Byte(CtrlCodes[I])      { Matches a code }
+     Then Begin
+       CtrlToArrow := ArrowCodes[I];                  { Return key stroke }
+       Exit;                                          { Now exit }
+     End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        KEYBOARD CONTROL ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  GetShiftState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08Jul96 LdB     }
+{---------------------------------------------------------------------------}
+FUNCTION GetShiftState: Byte;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOV ES, Seg0040;                                 { Load DOS segment }
+     XOR AX, AX;
+     MOV DX, AX;                                      { Clear registers }
+     MOV AL, ES:[$0017];                              { Read shift state }
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   BEGIN
+   ASM
+     MOVW $0x0200, %AX;                               { Set function id }
+     PUSHL %EBP;                                      { Save register }
+     INT $0x16;                                       { Get shift status }
+     POPL %EBP;                                       { Restore register }
+   END;
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+CONST vk_Scroll = $91;                                { Borland forgot this! }
+VAR B: Byte;
+BEGIN
+   B := 0;                                            { Clear all masks }
+   If (GetKeyState(vk_Shift) AND $80 <> 0) Then
+     B := B OR kbBothShifts;                          { Set both shifts }
+   If (GetKeyState(vk_Control) AND $80 <> 0) Then
+     B := B OR kbCtrlShift;                           { Set control mask }
+   If (GetKeyState(vk_Menu) AND $80 <> 0) Then
+     B := B OR kbAltShift;                            { Set alt mask }
+   If (GetKeyState(vk_Scroll) AND $81 <> 0) Then
+     B := B OR kbScrollState;                         { Set scroll lock mask }
+   If (GetKeyState(vk_NumLock) AND $81 <> 0) Then
+     B := B OR kbNumState;                            { Set number lock mask }
+   If (GetKeyState(vk_Capital) AND $81 <> 0) Then
+     B := B OR kbCapsState;                           { Set caps lock mask }
+   If (GetKeyState(vk_Insert) AND $81 <> 0) Then
+     B := B OR kbInsState;                            { Set insert mask }
+   GetShiftState := B;                                { Return masks }
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+VAR Key: KbdInfo;
+BEGIN
+   Key.cb := SizeOf(Key);                             { Keyboard size }
+   If KbdGetStatus(Key, 0) = 0 Then                   { Get key status }
+     GetShiftState := Key.fsState Else                { Return shift state }
+     GetShiftState := 0;                              { Failed so return 0 }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  GetKeyEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE GetKeyEvent (Var Event: TEvent);
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+ASSEMBLER;
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASM
+     MOV AH, $1;                                      { Set function id }
+     PUSH BP;                                         { Safety!! save reg }
+     INT $16;                                         { Check for keypress }
+     POP BP;                                          { Restore register }
+     MOV AX, $0;                                      { Zero register AX }
+     MOV BX, AX;                                      { Zero register BX }
+     JZ @@Exit3;                                      { No keypress jump }
+     MOV AH, $00;                                     { Set function id }
+     PUSH BP;                                         { Safety!! save reg }
+     INT $16;                                         { Read the key }
+     POP BP;                                          { Restore register }
+     XCHG AX, BX;                                     { Exchange registers }
+     MOV AX, evKeyDown;                               { Set keydown event }
+   @@Exit3:
+     LES DI, Event;                                   { ES:DI -> Event }
+     MOV ES:[DI].TEvent.What, AX;                     { Store event mask }
+     MOV ES:[DI].TEvent.KeyCode, BX;                  { Store key code }
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   ASM
+     MOVB $1, %AH;                                    { Set function id }
+     PUSHL %EBP;                                      { Save register }
+     INT $0x16;                                       { Check for keypress }
+     POPL %EBP;                                       { Restore register }
+     MOVW $0x0, %AX;                                  { Zero register AX }
+     MOVW %AX, %BX;                                   { Zero register BX }
+     JZ .L_Exit3;                                     { No keypress jump }
+     MOVB $0, %AH;                                    { Set function id }
+     PUSHL %EBP;                                      { Save register }
+     INT $0x16;                                       { Read the key }
+     POPL %EBP;                                       { Restore register }
+     XCHGW %BX, %AX;                                  { Exchange registers }
+     MOVW $0x10, %AX;                                 { Set keydown event }
+   .L_Exit3:
+     MOVL Event, %EDI;                                { EDI -> Event }
+     CLD;
+     STOSW;                                           { Store event mask }
+     XCHGW %BX, %AX;                                  { Transfer key code }
+     STOSW;                                           { Store key code }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+CONST NumPos: Byte = 0; Numeric: Byte = 0;
+VAR Handled: Boolean; B: Byte; Msg: TMsg;
+BEGIN
+   Event.What := evNothing;                           { Preset no event }
+   {$IFDEF PPC_FPC}                                   { FPC WINDOWS COMPILER }
+   If (PeekMessage(@Msg, 0, 0, WM_MouseFirst-1, pm_Remove)
+   OR PeekMessage(@Msg, 0, WM_MouseLast+1, $FFFF, pm_Remove))
+   {$ELSE}                                            { OTHER COMPILERS }
+   If (PeekMessage(Msg, 0, 0, WM_MouseFirst-1, pm_Remove)
+   OR PeekMessage(Msg, 0, WM_MouseLast+1, $FFFF, pm_Remove))
+   {$ENDIF}
+   Then Begin                                         { Non mouse message }
+     Handled := False;                                { Preset not handled }
+     Case Msg.Message Of
+       WM_Char: Begin                                 { CHARACTER KEY }
+         NumPos := 0;                                 { Zero number position }
+         Event.CharCode := Char(Msg.wParam);          { Transfer character }
+         If (Event.CharCode > #127) Then
+           Event.CharCode := Chr(WinAsciiToIntAscii[
+             Ord(Event.CharCode)]);                   { Convert to ascii }
+         Event.ScanCode := Lo(HiWord(Msg.lParam));    { Transfer scan code }
+         If (Event.CharCode <> #0) Then Begin         { If valid key then }
+           Event.What := evKeyDown;                   { Key down event }
+           Handled := True;                           { Message was handled }
+           If (Event.KeyCode = kbTab) AND             { Tab key is special }
+           (GetShiftState AND kbBothShifts <> 0) Then { Check shift state }
+             Event.KeyCode := kbShiftTab;             { If set make shifttab }
+         End;
+       End;
+       WM_SysKeyDown: Begin                           { SYSTEM KEY DOWN }
+         If (NumPos > 0) Then Begin                   { Numerics entry op }
+           Case Msg.wParam Of
+             VK_Insert: B := 0;                       { Key value = 0 }
+             VK_End: B := 1;                          { Key value = 1 }
+             VK_Down: B := 2;                         { Key value = 2 }
+             VK_Next: B := 3;                         { Key value = 3 }
+             VK_Left: B := 4;                         { Key value = 4 }
+             VK_Clear: B := 5;                        { Key value = 5 }
+             VK_Right: B := 6;                        { Key value = 6 }
+             VK_Home: B := 7;                         { Key value = 7 }
+             VK_Up: B := 8;                           { Key value = 8 }
+             VK_Prior: B := 9;                        { Key value = 9 }
+             VK_NumPad0..VK_NumPad9: B := Msg.wParam
+               - $60;                                 { Numbic key pad }
+             Else NumPos := 0;                        { Invalid key }
+           End;
+           If ((NumPos > 0) AND (NumPos < 4)) AND     { Valid position }
+           ((B >= $0) AND (B <= $9)) Then Begin       { Valid key }
+             Numeric := Numeric*10 + B;               { Adjust numeric }
+             Inc(NumPos);                             { Next position }
+             If (NumPos = 4) Then Begin               { We have three keys }
+               Event.What := evKeyDown;               { Set keydown event }
+               Event.CharCode := Chr(Numeric);        { Transfer code }
+               NumPos := 0;                           { Zero number position }
+             End;
+             Handled := True;                         { Message was handled }
+           End Else NumPos := 0;                      { Zero number position }
+         End;
+         If (Msg.WParam = vk_Menu) Then Begin         { ALT key down }
+           Numeric := 0;                              { Zero numeric }
+           NumPos := 1;                               { Set to start point }
+           Handled := True;                           { Message was handled }
+         End;
+         If NOT Handled Then Begin                    { Key press not handled }
+           If (Lo(Msg.wParam) < 128) Then Begin       { Ignore if above 128 }
+             If (Msg.wParam = vk_F10) Then Begin      { F10 reports oddly }
+               If (GetKeyState(vk_Shift) AND $80 <> 0)
+                 Then Event.KeyCode := kbShiftF10 Else{ Shift F10 }
+               If (GetKeyState(vk_Menu) AND $80 <> 0)
+                 Then Event.KeyCode := kbAltF10 Else  { Alt F10 }
+               If (GetKeyState(vk_Control) AND $80 <> 0)
+                 Then Event.KeyCode := kbCtrlF10      { Ctrl F10 }
+               Else Event.KeyCode := kbF10;           { Normal F10 }
+             End Else Event.KeyCode :=
+               AltVirtualToAscii[Lo(Msg.wParam)];     { Convert key code }
+           End Else Event.KeyCode := 0;               { Clear Event.keycode }
+           If (Event.KeyCode <> 0) Then Begin         { If valid key then }
+             Event.What := evKeyDown;                 { Key down event }
+             Handled := True;                         { Message was handled }
+           End;
+         End;
+       End;
+       WM_KeyDown: Begin                              { ARROWS/F1..F12 KEYS }
+         If (((Msg.WParam >= Vk_F1) AND (Msg.WParam <= Vk_F12)) OR
+        ((Msg.WParam >= Vk_Prior) AND (Msg.WParam <= Vk_Delete)))
+         Then Begin                                   { Special key press }
+           Event.CharCode := #0;                      { Clear char code }
+           Event.ScanCode := Lo(HiWord(Msg.LParam));  { Create scan code }
+           If (GetKeyState(vk_Shift) AND $80 <> 0)
+           Then Begin                                 { Shift key down }
+             Case Msg.wParam Of
+               vk_F1..vk_F9: Event.KeyCode :=
+                 Event.KeyCode + $1900;               { Shift F1..F9 keys }
+               vk_F11: Event.KeyCode := kbShiftF11;   { Shift F11 key }
+               vk_F12: Event.KeyCode := kbShiftF12;   { Shift F12 key }
+             End;
+           End Else If (GetKeyState(vk_Control) AND $80 <> 0)
+           Then Begin                                 { Control key down }
+             Case Msg.wParam Of
+               vk_F1..vk_F9: Event.KeyCode :=
+                 Event.KeyCode + $2300;               { Ctrl F1..F9 keys }
+               vk_F11: Event.KeyCode := kbCtrlF11;    { Ctrl F11 key }
+               vk_F12: Event.KeyCode := kbCtrlF12;    { Ctrl F12 key }
+             End;
+           End;
+           If (Event.KeyCode <> 0) Then Begin         { If valid key then }
+             Event.What := evKeyDown;                 { Key down event }
+             Handled := True;                         { Message was handled }
+           End;
+         End;
+         NumPos := 0;                                 { Zero number position }
+       End;
+     End;
+     If NOT Handled Then Begin                        { Check we did not handle }
+       TranslateMessage(Msg);                         { Translate message }
+       DispatchMessage(Msg);                          { Dispatch message }
+     End;
+   End;
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+VAR Msg: QMsg;
+BEGIN
+   Event.What := evNothing;                           { Preset no event }
+   If (WinPeekMsg(Anchor, Msg, 0, 0, WM_MouseFirst-1, pm_Remove)
+   OR WinPeekMsg(Anchor, Msg, 0, WM_MouseLast+1, $FFFFFFFF, pm_Remove))
+   Then Begin                                         { Check for message }
+     If (Msg.Msg = WM_Char) AND                       { Character message }
+     (Msg.Mp1 AND KC_KeyUp <> 0) AND                  { Key released }
+     (Msg.Mp1 AND KC_Composite = 0)                   { Not composite key }
+     Then Begin
+       If (Short1FromMP(Msg.Mp1) AND KC_ScanCode <> 0 )
+       Then Begin
+         Event.ScanCode := Ord(Char4FromMP(Msg.Mp1)); { Return scan code }
+         Event.CharCode := Char1FromMP(Msg.Mp2);      { Return char code }
+         If (Event.CharCode = Chr($E0)) Then Begin
+           Event.CharCode := #0;
+           Event.ScanCode := Byte(Char2FromMP(Msg.Mp2));
+         End;
+         If (Event.KeyCode <> 0) Then
+           Event.What := evKeyDown;                   { Key down event }
+       End;
+     End;
+     If (Event.What = evNothing) Then                 { Event not handled }
+       WinDispatchMsg(Anchor, Msg);                   { Disptach message }
+   End;
+END;
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          MOUSE CONTROL ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  HideMouse -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun98 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE HideMouse;
+BEGIN
+   If (HideCount = 0) Then Begin                      { Is mouse hidden yet? }
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+     HideMouseCursor;                                 { Hide mouse cursor }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     ShowCursor(False);                               { Hide mouse cursor }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (AppWindow <> 0) Then                         { Window valid }
+       WinShowCursor(AppWindow, False);               { Hide mouse cursor }
+     {$ENDIF}
+   End;
+   Inc(HideCount);                                    { Inc hide count }
+END;
+
+{---------------------------------------------------------------------------}
+{  ShowMouse -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jun98 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE ShowMouse;
+BEGIN
+   Dec(HideCount);                                    { Dec hide count }
+   If (HideCount = 0) Then Begin                      { Is mouse visible? }
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+     ShowMouseCursor;                                 { Show mouse cursor }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     ShowCursor(True);                                { Show mouse cursor }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (AppWindow <> 0) Then                         { Window valid }
+       WinShowCursor(AppWindow, True);                { Show mouse cursor }
+     {$ENDIF}
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  GetMouseEvent -> Platforms DOS/DPMI/WINDOWS/OS2 - Updated 09Sep98 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE GetMouseEvent (Var Event: TEvent);
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+ASSEMBLER;
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+ASM
+   CMP MouseEvents, 0;                                { Any mouse events }
+   JNZ @@MouseOk;                                     { Check mouse active }
+   JMP @@NoEventExit;                                 { Mouse not active }
+@@MouseOk:
+   CLI;                                               { Disable interrupts }
+   CMP EventCount, 0;                                 { Check event count  }
+   JNE @@MouseEventInQueue;                           { If > 0 event avail }
+   MOV BL, MouseButtons;                              { Fetch mouse buttons }
+   MOV CX, MouseWhere.Word[0];                        { Fetch mouse where.x }
+   MOV DX, MouseWhere.Word[2];                        { Fetch mouse where.y }
+   MOV ES, Seg0040;                                   { DOS DAT SEG }
+   MOV DI, ES:Ticks;                                  { Fetch current time }
+   JMP @@NextMsgReady;                                { Now process }
+@@MouseEventInQueue:
+   MOV SI, WORD PTR EventQHead;                       { Event queue head }
+   CLD;                                               { Direction forward  }
+   LODSW;                                             { Fetch word 1 }
+   XCHG AX, DI;                                       { Set timer ticks }
+   LODSW;                                             { Fetch word 2 }
+   XCHG AX, BX;                                       { Set button masks }
+   LODSW;                                             { Fetch word 3 }
+   XCHG AX, CX;                                       { Set mouse x position }
+   LODSW;                                             { Fetch word 4 }
+   XCHG AX, DX;                                       { Set mouse y position }
+   CMP SI, OFFSET EventQLast;                         { Check if roll needed }
+   JNE @@NoRoll;
+   MOV SI, OFFSET EventQueue;                         { Roll back to start }
+@@NoRoll:
+   MOV WORD PTR EventQHead, SI;                       { Update queue head }
+   DEC EventCount;                                    { One event cleared }
+@@NextMsgReady:
+   STI;                                               { Enable interrupts }
+   CMP MouseReverse, 0;                               { Check mouse reversed }
+   JE @@MouseNormal;
+   MOV BH, BL;                                        { Transfer button mask }
+   AND BH, 3;                                         { Clear others masks }
+   JE @@MouseNormal;                                  { Neither set exit }
+   CMP BH, 3;                                         { Check not all set }
+   JE @@MouseNormal;                                  { Both set exit }
+   XOR BL, 3;                                         { Invert button masks }
+@@MouseNormal:
+   MOV BH, [LastDouble];                              { Load last double }
+   MOV AL, [LastButtons];                             { Load last buttons }
+   CMP AL, BL;                                        { Are buttons same? }
+   JE @@SameButtonsDown;
+   OR AL, AL;                                         { Any last buttons? }
+   JE @@ButtonsDown;
+   OR BL, BL;                                         { Any buttons down? }
+   JE @@MouseUp;
+   MOV BL, AL;                                        { Transfer new buttons }
+@@SameButtonsDown:
+   CMP CX, [LastWhereX];                              { Mouse moved from x }
+   JNE @@MouseMove;
+   CMP DX, [LastWhereY];                              { Mouse moved from y }
+   JNE @@MouseMove;
+   OR BL, BL;                                         { Any buttons pressed? }
+   JE @@NoButtonsDown;
+   MOV AX, DI;                                        { Current tick count }
+   SUB AX, [AutoTicks];                               { Subtract last count }
+   CMP AX, [AutoDelay];                               { Greater than delay? }
+   JAE @@MouseAuto;                                   { Mouse auto event }
+@@NoButtonsDown:
+   JMP @@NoEventExit;                                 { No event exit }
+@@ButtonsDown:
+   MOV BH, 0;                                         { Preset no dbl click  }
+   CMP BL, [DownButtons];                             { Check to last down }
+   JNE @@MouseDown;
+   CMP CX, [DownWhereX];                              { Check x position }
+   JNE @@MouseDown;
+   CMP DX, [DownWhereY];                              { Check y position }
+   JNE @@MouseDown;
+   MOV AX, DI;                                        { Transfer tick count }
+   SUB AX, [DownTicks];                               { Sub last down count }
+   CMP AX, [DoubleDelay];                             { Greater than delay? }
+   JAE @@MouseDown;
+   MOV BH, 1;                                         { Double click }
+@@MouseDown:
+   MOV [DownButtons], BL;                             { Hold down buttons }
+   MOV [DownWhereX], CX;                              { Hold x down point }
+   MOV [DownWhereY], DX;                              { Hold y down point }
+   MOV [DownTicks], DI;                               { Hold tick value }
+   MOV [AutoTicks], DI;                               { Hold tick value }
+   MOV AX, [RepeatDelay];                             { Load delay count }
+   MOV [AutoDelay], AX;                               { Set delay time }
+   MOV AX, evMouseDown;                               { Mouse down event }
+   JMP @@UpdateValues;                                { Update, svae & exit }
+@@MouseUp:
+   MOV AX, evMouseUp;                                 { Mouse button up }
+   JMP @@UpdateValues;                                { Update, save & exit }
+@@MouseMove:
+   MOV AX, evMouseMove;                               { Mouse has moved }
+   JMP @@UpdateValues;                                { Update, save & exit }
+@@MouseAuto:
+   MOV AX, evMouseAuto;                               { Mouse auto event }
+   MOV [AutoTicks], DI;                               { Reset auto ticks }
+   MOV [AutoDelay], 1;                                { Reset delay count }
+@@UpdateValues:
+   MOV [LastButtons], BL;                             { Save last buttons }
+   MOV [LastDouble], BH;                              { Save double state }
+   MOV [LastWhereX], CX;                              { Save x position }
+   MOV [LastWhereY], DX;                              { Save y position }
+   JMP @@StoreAndExit;                                { Now store and exit }
+@@NoEventExit:
+   XOR AX, AX;                                        { Clear register }
+   MOV BX, AX;                                        { Clear register }
+   MOV CX, AX;                                        { Clear register }
+   MOV DX, AX;                                        { Clear register }
+@@StoreAndExit:
+   LES DI, Event;                                     { Address of event }
+   CLD;                                               { Set direction fwd }
+   STOSW;                                             { Save 1st word }
+   XCHG AX, BX;                                       { Transfer register }
+   STOSW;                                             { Save 2nd word }
+   XCHG AX, CX;                                       { Transfer register }
+   STOSW;                                             { Save 3rd word }
+   XCHG AX, DX;                                       { Transfer register }
+   STOSW;                                             { Save 4th word }
+END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+ASM
+   CMPB $0, MOUSEEVENTS;                              { Any mouse events }
+   JNZ .L_MouseOk;                                    { Check mouse active }
+   JMP .L_NoEventExit;                                { Mouse not active }
+.L_MouseOk:
+   CLI;
+   CMPW $0, EVENTCOUNT;                               { Check event count  }
+   JNE .L_MouseEventInQueue;                          { If > 0 event avail }
+   MOVB MOUSEBUTTONS, %BL;                            { Fetch mouse buttons }
+   MOVW MOUSEWHERE, %CX;                              { Fetch mouse where.x }
+   MOVW MOUSEWHERE+2, %DX;                            { Fetch mouse where.y }
+   PUSH %ES;                                          { Save segment }
+   MOVW $0x40, %AX;                                   { Fetch DOS segment }
+   MOVW %AX, %ES;                                     { Transfer to segment }
+   MOVL $0x6C, %EDI;                                  { Tick address }
+   MOVW %ES:(%EDI), %DI;                              { Fetch dos tick count }
+   POP %ES;                                           { Recover segment }
+   JMP .L_NextMsgReady;                               { Now process }
+.L_MouseEventInQueue:
+   MOVL EVENTQHEAD, %ESI;                             { Event queue head }
+   CLD;                                               { Direction forward  }
+   LODSW;                                             { Fetch word 1 }
+   XCHGW %DI, %AX;                                    { Set timer ticks }
+   LODSW;                                             { Fetch word 2 }
+   XCHGW %BX, %AX;                                    { Set button masks }
+   LODSW;                                             { Fetch word 3 }
+   XCHGW %CX, %AX;                                    { Set mouse x position }
+   LODSW;                                             { Fetch word 4 }
+   XCHGW %DX, %AX;                                    { Set mouse y position }
+   LEAL EVENTQLAST, %EAX;                             { Address of roll pt }
+   CMPL %EAX, %ESI;                                   { Check if roll needed }
+   JNE .L_NoHeadRoll;
+   LEAL EVENTQUEUE, %ESI;                             { Roll back to start }
+.L_NoHeadRoll:
+   MOVL %ESI, EVENTQHEAD;                             { Update queue head }
+   DECW EVENTCOUNT;                                   { One event cleared }
+.L_NextMsgReady:
+   STI;                                               { Enable interrupts }
+   CMPB $0, MOUSEREVERSE;                             { Check mouse reversed }
+   JE .L_MouseNormal;
+   MOVB %BL, %BH;                                     { Transfer button mask }
+   ANDB $3, %BH;                                      { Clear others masks }
+   JE .L_MouseNormal;                                 { Neither set exit }
+   CMPB $3, %BH;                                      { Check not all set }
+   JE .L_MouseNormal;                                 { Both set exit }
+   XORB $3, %BL;                                      { Invert button masks }
+.L_MouseNormal:
+   MOVB LASTDOUBLE, %BH;                              { Load last double }
+   MOVB LASTBUTTONS, %AL;                             { Load last buttons }
+   CMPB %BL, %AL;                                     { Are buttons same? }
+   JE .L_SameButtonsDown;
+   ORB %AL, %AL;                                      { Any last buttons? }
+   JE .L_ButtonsDown;
+   ORB %BL, %BL;                                      { Any buttons down? }
+   JE .L_MouseUp;
+   MOVB %AL, %BL;                                     { Transfer new buttons }
+.L_SameButtonsDown:
+   CMPW LASTWHEREX, %CX;                              { Mouse moved from x }
+   JNE .L_MouseMove;
+   CMPW LASTWHEREY, %DX;                              { Mouse moved from y }
+   JNE .L_MouseMove;
+   ORB %BL, %BL;                                      { Any buttons pressed? }
+   JE .L_NoButtonsDown;
+   MOVW %DI, %AX;                                     { Current tick count }
+   SUBW AUTOTICKS, %AX;                               { Subtract last count }
+   CMPW AUTODELAY, %AX;                               { Greater than delay? }
+   JAE .L_MouseAuto;                                  { Mouse auto event }
+.L_NoButtonsDown:
+   JMP .L_NoEventExit;                                { No event exit }
+.L_ButtonsDown:
+   MOVB $0, %BH;                                      { Preset no dbl click  }
+   CMPB DOWNBUTTONS, %BL;                             { Check to last down }
+   JNE .L_MouseDown;
+   CMPW DOWNWHEREX, %CX;                              { Check x position }
+   JNE .L_MouseDown;
+   CMPW DOWNWHEREY, %DX;                              { Check y position }
+   JNE .L_MouseDown;
+   MOVW %DI, %AX;                                     { Transfer tick count }
+   SUBW DOWNTICKS, %AX;                               { Sub last down count }
+   CMPW DOUBLEDELAY, %AX;                             { Greater than delay? }
+   JAE .L_MouseDown;
+   MOVB $1, %BH;                                      { Double click }
+.L_MouseDown:
+   MOVB %BL, DOWNBUTTONS;                             { Hold down buttons }
+   MOVW %CX, DOWNWHEREX;                              { Hold x down point }
+   MOVW %DX, DOWNWHEREY;                              { Hold y down point }
+   MOVW %DI, DOWNTICKS;                               { Hold tick value }
+   MOVW %DI, AUTOTICKS;                               { Hold tick value }
+   MOVW REPEATDELAY, %AX;                             { Load delay count }
+   MOVW %AX, AUTODELAY;                               { Set delay time }
+   MOVW $1, %AX;                                      { Mouse down event }
+   JMP .L_UpdateValues;                               { Update, svae & exit }
+.L_MouseUp:
+   MOVW $2, %AX;                                      { Mouse button up }
+   JMP .L_UpdateValues;                               { Update, save & exit }
+.L_MouseMove:
+   MOVW $4, %AX;                                      { Mouse has moved }
+   JMP .L_UpdateValues;                               { Update, save & exit }
+.L_MouseAuto:
+   MOVW $8, %AX;                                      { Mouse auto event }
+   MOVW %DI, AUTOTICKS;                               { Reset auto ticks }
+   MOVW $1, AUTODELAY;                                { Reset delay count }
+.L_UpdateValues:
+   MOVB %BL, LASTBUTTONS;                             { Save last buttons }
+   MOVB %BH, LASTDOUBLE;                              { Save double state }
+   MOVW %CX, LASTWHEREX;                              { Save x position }
+   MOVW %DX, LASTWHEREY;                              { Save y position }
+   JMP .L_StoreAndExit;                               { Now store and exit }
+.L_NoEventExit:
+   XORW %AX, %AX;                                     { Clear register }
+   MOVW %AX, %BX;                                     { Clear register }
+   MOVW %AX, %CX;                                     { Clear register }
+   MOVW %AX, %DX;                                     { Clear register }
+.L_StoreAndExit:
+   MOVL Event, %EDI;                                  { Adress of event }
+   CLD;                                               { Set direction fwd }
+   STOSW;                                             { Save 1st word }
+   XCHGW %BX, %AX;                                    { Transfer register }
+   STOSW;                                             { Save 2nd word }
+   XCHGW %CX, %AX;                                    { Transfer register }
+   STOSW;                                             { Save 3rd word }
+   XCHGW %DX, %AX;                                    { Transfer register }
+   STOSW;                                             { Save 4th word }
+END;
+{$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+VAR Msg: TMsg;
+BEGIN
+   Event.What := evNothing;                           { Preset no event }
+   {$IFDEF PPC_FPC}                                   { FPC WINDOWS COMPILER }
+   If PeekMessage(@Msg, 0, WM_MouseFirst,
+   WM_MouseLast, pm_Remove) Then Begin                { Fetch mouse message }
+   {$ELSE}                                            { OTHER COMPILERS }
+   If PeekMessage(Msg, 0, WM_MouseFirst,
+   WM_MouseLast, pm_Remove) Then Begin                { Fetch mouse message }
+   {$ENDIF}
+     TranslateMessage(Msg);                           { Translate message }
+     DispatchMessage(Msg);                            { Dispatch message }
+   End;
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+VAR Msg: QMsg;
+BEGIN
+   Event.What := evNothing;                           { Preset no event }
+   If WinPeekMsg(Anchor, Msg, 0, WM_MouseFirst,
+   WM_MouseLast, pm_Remove) Then Begin                { Fetch mouse message }
+     WinDispatchMsg(Anchor, Msg);                     { Dispatch message }
+   End;
+END;
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                      EVENT HANDLER CONTROL ROUTINES                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  InitEvents -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 07Sep99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE InitEvents;
+BEGIN
+   If (ButtonCount <> 0) Then Begin                   { Mouse is available }
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+     EventQHead := @EventQueue;                       { Initialize head }
+     EventQtail := @EventQueue;                       { Initialize tail }
+     LastDouble  := False;                            { Clear last double }
+     LastButtons := 0;                                { Clear last buttons }
+     DownButtons := 0;                                { Clear down buttons }
+     HookMouse;                                       { Hook the mouse }
+     GetMousePosition(MouseWhere.X, MouseWhere.Y);    { Get mouse position }
+     LastWhereX := MouseWhere.X;                      { Set last x position }
+     LastWhereY := MouseWhere.Y;                      { Set last y position }
+     MouseEvents := True;                             { Set initialized flag }
+     ShowMouseCursor;                                 { Show the mouse }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     MouseEvents := True;                             { Set initialized flag }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (Anchor=0) Then Anchor := WinInitialize(0);   { Create anchor block }
+     If (MsgQue = 0) AND (Anchor <> 0) Then
+       MsgQue := WinCreateMsgQueue(Anchor, 0);        { Initialize queue }
+     If (MsgQue = 0) Then Halt(254);                  { Check queue created }
+     MouseEvents := True;                             { Set initialized flag }
+     {$ENDIF}
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  DoneEvents -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE DoneEvents;
+BEGIN
+   If MouseEvents Then Begin                          { Initialized check }
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+     HideMouseCursor;                                 { Hide the mouse }
+     MouseEvents := False;                            { Clear event flag }
+     UnHookMouse;                                     { Unhook the mouse }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     MouseEvents := False;                            { Clr initialized flag }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (MsgQue <> 0) Then WinDestroyMsgQueue(MsgQue);{ Destroy msg queue }
+     If (Anchor <> 0) Then WinTerminate(Anchor);      { Destroy anchor block }
+     MsgQue := 0;                                     { Zero msg queue handle }
+     Anchor := 0;                                     { Zero anchor block }
+     MouseEvents := False;                            { Clr initialized flag }
+     {$ENDIF}
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           VIDEO CONTROL ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+{$IFDEF PPC_FPC}                                      { FPC COMPILER ONLY }
+{ ******************************* REMARK ****************************** }
+{   This is purely temporary for FPC because the Graph is SuperVGA you  }
+{  have no mouse pointer on screen because the mouse drivers don't go   }
+{  up to supporting SVGA modes. This simply makes a cross hair so you   }
+{  can see the mouse for now..will be fixed soon.                       }
+{ ****************************** END REMARK *** Leon de Boer, 04Nov99 * }
+VAR LastX, LastY: Integer;
+
+PROCEDURE ShowTheMouse; FAR;
+BEGIN
+   If (MouseEvents = True) AND (HideCount = 0)        { Mouse visible }
+   Then Begin
+     SetWriteMode(XORPut);                            { XOR write mode }
+     SetColor(15);                                    { Set color to white }
+     Line(LastX-5, LastY, LastX+5, LastY);            { Remove horz line  }
+     Line(LastX, LastY-5, LastX, LastY+5);            { Remove vert line }
+     LastX := MouseWhere.X;                           { Update x position }
+     LastY := MouseWHere.Y;                           { Update y position }
+     Line(LastX-5, LastY, LastX+5, LastY);            { Draw horz line }
+     Line(LastX, LastY-5, LastX, LastY+5);            { Draw vert line }
+     SetWriteMode(NormalPut);                         { Write mode to normal }
+   End;
+END;
+{$ENDIF}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  InitVideo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Nov99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE InitVideo;
+VAR {$IFDEF OS_DOS} I, J: Integer; Ts: TextSettingsType; {$ENDIF}
+    {$IFDEF OS_WINDOWS} Dc, Mem: HDc; TempFont: TLogFont; Tm: TTextmetric; {$ENDIF}
+    {$IFDEF OS_OS2} Ts, Fs: Integer; Ps: HPs; Tm: FontMetrics; {$ENDIF}
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+   I := Detect;                                       { Detect video card }
+   J := 0;                                            { Zero select mode }
+   InitGraph(I, J, '');                               { Initialize graphics }
+   I := GetMaxX;                                      { Fetch max x size }
+   J := GetMaxY;                                      { Fetch max y size }
+   {$IFDEF PPC_FPC}                                   { FPC DOS COMPILER }
+     ASM
+       MOVW $7, %AX;                                  { Set function  id }
+       MOVW $0, %CX;                                  { Clear register }
+       MOVW I, %DX;                                   { Maximum x size }
+       INT $0x33;                                     { Set mouse x movement }
+       MOVW $8, %AX;                                  { Set function id }
+       MOVW $0, %CX;                                  { Clear register }
+       MOVW J, %DX;                                   { Maximum y size }
+       INT $0x33;                                     { Set mouse y movement }
+     END;
+     Lock_Code(Pointer(@ShowTheMouse), 400);          { Lock cursor code }
+     MouseMoveProc := ShowTheMouse;                   { Set move function }
+     ShowMouseProc := ShowTheMouse;                   { Set show function }
+     HideMouseProc := ShowTheMouse;                   { Set hide function }
+   {$ELSE}                                            { OTHER DOS COMPILERS }
+     ASM
+       MOV AX, 7;                                     { Set function  id }
+       XOR CX, CX;                                    { Clear register }
+       MOV DX, I;                                     { Maximum x size }
+       INT 33H;                                       { Set mouse x movement }
+       MOV AX, 8;                                     { Set function id }
+       XOR CX, CX;                                    { Clear register }
+       MOV DX, J;                                     { Maximum y size }
+       INT 33H;                                       { Set mouse y movement }
+     END;
+   {$ENDIF}
+     SysScreenWidth := GetMaxX+1;                     { Max screen width }
+     SysScreenHeight := GetMaxY+1;                    { Max screen height }
+
+     If (DefFontHeight = 0) Then                      { Font height not set }
+       J := SysScreenHeight DIV DefLineNum            { Approx font height }
+       Else J := DefFontHeight;                       { Use set font height }
+     I := J DIV (TextHeight('H')+4);                  { Approx magnification }
+     If (I < 1) Then I := 1;                          { Must be 1 or above }
+     GetTextSettings(Ts);                             { Get text style }
+     SetTextStyle(Ts.Font, Ts.Direction, I);          { Set new font settings }
+     SysFontWidth := TextWidth('H');                  { Transfer font width }
+     SysFontHeight := TextHeight('H')+4;              { Transfer font height }
+   {$ENDIF}
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     SysScreenWidth := GetSystemMetrics(
+       SM_CXFullScreen)-GetSystemMetrics(SM_CXFrame); { Max screen width }
+     SysScreenHeight := GetSystemMetrics(
+       SM_CYFullScreen);                              { Max screen height }
+     With TempFont Do Begin
+       If (DefFontHeight = 0) Then Begin              { Font height not set }
+         lfHeight := SysScreenHeight DIV DefLineNum;  { Best guess height }
+       End Else lfHeight := -DefFontHeight;           { Specific font height }
+       lfWidth         := 0;                          { No specific width }
+       lfEscapement    := 0;                          { No specifics }
+       lfOrientation   := 0;                          { Normal orientation }
+       lfWeight        := DefFontWeight;              { Default font weight }
+       lfItalic        := 0;                          { No italics }
+       lfUnderline     := 0;                          { No underlines }
+       lfStrikeOut     := 0;                          { No strikeouts }
+       lfCharSet       := ANSI_CharSet;               { ANSI font set }
+       lfOutPrecision  := Out_Default_Precis;         { Default precision out }
+       lfClipPrecision := Clip_Default_Precis;        { Default clip precision }
+       lfQuality       := Proof_Quality;              { Proof quality }
+       lfPitchAndFamily:= Variable_Pitch OR
+         Fixed_Pitch;                                 { Either fitch format }
+       FillChar(lfFaceName, SizeOf(lfFaceName), #0);  { Clear memory area }
+       Move(DefFontStyle[1], lfFacename,
+         Length(DefFontStyle));                       { Transfer style name }
+     End;
+     DefGFVFont := CreateFontIndirect(TempFont);      { Create a default font }
+     Dc := GetDc(0);                                  { Get screen context }
+     Mem := CreateCompatibleDC(Dc);                   { Compatable context }
+     SelectObject(Mem, DefGFVFont);                   { Select the font }
+     {$IFDEF PPC_FPC}                                 { FPC WINDOWS COMPILER }
+       GetTextMetrics(Mem, @Tm);                      { Get text metrics }
+     {$ELSE}                                          { OTHER COMPILERS }
+       GetTextMetrics(Mem, Tm);                       { Get text metrics }
+     {$ENDIF}
+     SysFontWidth := Tm.tmaveCharWidth+1;             { Ave char font width }
+     SysFontHeight := Tm.tmHeight;                    { Ave char font height }
+     DeleteDc(Mem);                                   { Destroy context }
+     ReleaseDc(0, Dc);                                { Release context }
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+     Ts := WinQuerySysValue(HWND_Desktop,
+       SV_CYTitleBar) + 2*WinQuerySysValue(HWND_Desktop,
+       SV_CYSizeBorder);                              { Title size }
+     Fs := 2*WinQuerySysValue(HWND_DeskTop,
+       SV_CXSizeBorder);                              { Frame size }
+     SysScreenWidth := WinQuerySysValue(HWND_Desktop,
+       SV_CXFullScreen) - Fs;                         { Max screen width }
+     SysScreenHeight := WinQuerySysValue(HWND_Desktop,
+       SV_CYFullScreen) - Ts;                         { Max screen height }
+     (*With DefGFVFont Do Begin
+       usRecordLength := SizeOf(fAttrs);              { Structure size }
+       fsSelection := $20;                              { Uses default selection }
+       lMatch := 0;                                   { Does not force match }
+       idRegistry := 0;                               { Uses default registry }
+       usCodePage := 850;                             { Code-page 850 }
+       If (DefFontHeight = 0) Then Begin              { Font height not set }
+         lMaxBaselineExt := SysScreenHeight DIV DefLineNum;  { Best guess height }
+       End Else lMaxBaselineExt := DefFontHeight;     { Specific font height }
+       lAveCharWidth := 0;                            { Req font default width }
+       fsType := 0;                                   { Uses default type }
+       fsFontUse := fAttr_FontUse_Nomix;              { Doesn't mix with graphics }
+       FillChar(szFaceName, SizeOf(szFaceName), #0);  { Clear memory area }
+       Move(DefFontStyle[1], szFacename,
+         Length(DefFontStyle));                       { Transfer style name }
+     End;*)
+     Ps := WinGetPS(HWND_Desktop);                    { Get desktop PS }
+     (*GpiCreateLogFont(Ps, Nil, 1, DefGFVFont);*)        { Create the font }
+     GpiQueryFontMetrics(Ps, SizeOf(Tm), Tm);         { Get text metrics }
+     SysFontWidth := Tm.lAveCharWidth+1;              { Transfer font width }
+     SysFontHeight := Tm.lMaxBaselineExt;             { Transfer font height }
+    { SysFontheight := SysScreenheight DIV DefLineNum;}
+     WinReleasePS(Ps);                                { Release desktop PS }
+     DefPointer := WinQuerySysPointer(HWND_DESKTOP,
+       SPTR_ARROW, False);                            { Hold default pointer }
+   {$ENDIF}
+   ScreenWidth := SysScreenWidth DIV SysFontWidth;    { Calc screen width }
+   ScreenHeight := SysScreenHeight DIV SysFontHeight; { Calc screen height }
+   SysScreenWidth := ScreenWidth * SysFontWidth;      { Actual width }
+   SysScreenHeight := ScreenHeight * SysFontHeight;   { Actual height }
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   Inc(SysScreenWidth, 2*GetSystemMetrics(SM_CXFrame)); { Max screen width }
+   Inc(SysScreenHeight, GetSystemMetrics(SM_CYCaption)
+     + GetSystemMetrics(SM_CYFrame));                 { Max screen height }
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   Inc(SysScreenWidth, Fs);                           { Max screen width }
+   Inc(SysScreenHeight, Ts);                          { Max screen height }
+   {$ENDIF}
+END;
+
+{---------------------------------------------------------------------------}
+{  DoneVideo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May98 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE DoneVideo;
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+     {$IFDEF PPC_FPC}
+     MouseMoveProc := Nil;                            { Clr mouse move ptr }
+     ShowMouseProc := Nil;                            { Clr show mouse ptr }
+     HideMouseProc := Nil;                            { Clr hide mouse ptr }
+     UnLock_Code(Pointer(@ShowTheMouse), 400);        { Unlock cursor code }
+     {$ENDIF}
+     CloseGraph;                                      { Close down graphics }
+   {$ENDIF}
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     If (DefGFVFont <> 0) Then                        { Check font created }
+       DeleteObject(DefGFVFont);                      { Delete the font }
+   {$ENDIF}
+END;
+
+{---------------------------------------------------------------------------}
+{  ClearScreen -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 04Jan97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE ClearScreen;
+BEGIN
+END;
+
+{---------------------------------------------------------------------------}
+{  SetVideoMode -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 10Nov99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE SetVideoMode (Mode: Word);
+BEGIN
+   If (Mode > $100) Then DefLineNum := 50             { 50 line mode request }
+     Else DefLineNum := 24;                           { Normal 24 line mode }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           ERROR CONTROL ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  InitSysError -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 20May98 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE InitSysError;
+BEGIN
+   SysErrActive := True;                              { Set active flag }
+END;
+
+{---------------------------------------------------------------------------}
+{  DoneSysError -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 20May98 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE DoneSysError;
+BEGIN
+   SysErrActive := False;                             { Clear active flag }
+END;
+
+{---------------------------------------------------------------------------}
+{  SystemError -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 20May98 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION SystemError (ErrorCode: Integer; Drive: Byte): Integer;
+BEGIN
+   If (FailSysErrors = False) Then Begin              { Check error ignore }
+
+   End Else SystemError := 1;                         { Return 1 for ignored }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           STRING FORMAT ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  PrintStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18Feb99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE PrintStr (CONST S: String);
+{$IFNDEF OS_DOS} VAR Ts: String; {$ENDIF}
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+   Write(S);                                          { Write to screen }
+   {$ENDIF}
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   Ts := S + #0;                                      { Make asciiz }
+     {$IFNDEF PPC_SPEED}                              { NON SPEED COMPILER }
+     MessageBox(0, @Ts[1], Nil, mb_Ok OR mb_IconStop);{ Display to screen }
+     {$ELSE}                                          { SYBIL 2+ COMPILER }
+     MessageBox(0, CString(@Ts[1]), Nil, mb_Ok OR
+       mb_IconStop);                                  { Display to screen }
+     {$ENDIF}
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   Ts := S + #0;                                      { Make asciiz }
+   WinMessageBox(0, 0, @Ts[1], Nil, mb_Ok OR
+     0, mb_IconHand);                                 { Display to screen }
+   {$ENDIF}
+END;
+
+{---------------------------------------------------------------------------}
+{  FormatStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 13Jul99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE FormatStr (Var Result: String; CONST Format: String; Var Params);
+TYPE TLongArray = Array[0..0] Of LongInt;
+VAR ResultLength, FormatIndex, Justify, Wth: Byte; Fill: Char; S: String;
+
+   FUNCTION LongToStr (L: Longint; Radix: Byte): String;
+   CONST HexChars: Array[0..15] Of Char =
+    ('0', '1', '2', '3', '4', '5', '6', '7',
+     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
+   VAR I: LongInt; S: String; Sign: String[1];
+   BEGIN
+     LongToStr := '';                                 { Preset empty return }
+     If (L < 0) Then Begin                            { If L is negative }
+       Sign := '-';                                   { Sign is negative }
+       L := Abs(L);                                   { Convert to positive }
+     End Else Sign := '';                             { Sign is empty }
+     S := '';                                         { Preset empty string }
+     Repeat
+       I := L MOD Radix;                              { Radix mod of value }
+       S := HexChars[I] + S;                          { Add char to string }
+       L := L DIV Radix;                              { Divid by radix }
+     Until (L = 0);                                   { Until no remainder }
+     LongToStr := Sign + S;                           { Return result }
+   END;
+
+   PROCEDURE HandleParameter (I : LongInt);
+   BEGIN
+     While (FormatIndex <= Length(Format)) Do Begin   { While length valid }
+       While (Format[FormatIndex] <> '%') AND         { Param char not found }
+       (FormatIndex <= Length(Format)) Do Begin       { Length still valid }
+         Result[ResultLength+1] := Format[FormatIndex]; { Transfer character }
+         Inc(ResultLength);                           { One character added }
+         Inc(FormatIndex);                            { Next param char }
+       End;
+       If (FormatIndex < Length(Format)) AND          { Not last char and }
+       (Format[FormatIndex] = '%') Then Begin         { '%' char found }
+         Fill := ' ';                                 { Default fill char }
+         Justify := 0;                                { Default justify }
+         Wth := 0;                                    { Default 0=no width }
+         Inc(FormatIndex);                            { Next character }
+         If (Format[FormatIndex] = '0') Then
+           Fill := '0';                               { Fill char to zero }
+         If (Format[FormatIndex] = '-') Then Begin    { Optional just char }
+           Justify := 1;                              { Right justify }
+           Inc(FormatIndex);                          { Next character }
+         End;
+         While ((FormatIndex <= Length(Format)) AND   { Length still valid }
+         (Format[FormatIndex] >= '0') AND
+         (Format[FormatIndex] <= '9')) Do Begin       { Numeric character }
+           Wth := Wth * 10;                           { Multiply x10 }
+           Wth := Wth + Ord(Format[FormatIndex])-$30; { Add numeric value }
+           Inc(FormatIndex);                          { Next character }
+         End;
+         If ((FormatIndex <= Length(Format)) AND      { Length still valid }
+         (Format[FormatIndex] = '#')) Then Begin      { Parameter marker }
+           Inc(FormatIndex);                          { Next character }
+           HandleParameter(Wth);                      { Width is param idx }
+         End;
+         If (FormatIndex <= Length(Format)) Then Begin{ Length still valid }
+           Case Format[FormatIndex] Of
+             'c': S := Char(TLongArray(Params)[I]);  { Character parameter }
+             'd': S := LongToStr(TLongArray(Params)[I],
+               10);                                   { Decimal parameter }
+             's': S := PString(TLongArray(Params)[I])^;{ String parameter }
+             'x': S := LongToStr(TLongArray(Params)[I],
+               16);                                   { Hex parameter }
+             '%': Begin                               { Literal % }
+               S := '%';                              { Set string }
+               Inc(FormatIndex);                      { Next character }
+               Move(S[1], Result[ResultLength+1], 1); { '%' char to result }
+               Inc(ResultLength, Length(S));          { Inc result length }
+               Continue;                              { Now continue }
+             End;
+           End;
+           Inc(I);                                    { Next parameter }
+           Inc(FormatIndex);                          { Next character }
+           If (Wth > 0) Then Begin                    { Width control active }
+             If (Length(S) > Wth) Then Begin          { We must shorten S }
+               If (Justify=1) Then                    { Check right justify }
+                 S := Copy(S, Length(S)-Wth+1, Wth)   { Take right side data }
+                 Else S := Copy(S, 1, Wth);           { Take left side data }
+             End Else Begin                           { We must pad out S }
+               If (Justify=1) Then                    { Right justify }
+                 While (Length(S) < Wth) Do
+                   S := S+Fill Else                   { Right justify fill }
+                 While (Length(S) < Wth) Do
+                   S := Fill + S;                     { Left justify fill }
+             End;
+           End;
+           Move(S[1], Result[ResultLength+1],
+             Length(S));                              { Move data to result }
+           ResultLength := ResultLength + Length(S);  { Adj result length }
+         End;
+       End;
+     End;
+   END;
+
+BEGIN
+   ResultLength := 0;                                 { Zero result length }
+   FormatIndex := 1;                                  { Format index to 1 }
+   HandleParameter(0);                                { Handle parameter }
+   {$IFDEF PPC_DELPHI3}                               { DELPHI 3+ COMPILER }
+   SetLength(Result, ResultLength);                   { Set string length }
+   {$ELSE}                                            { OTHER COMPILERS }
+   Result[0] := Chr(ResultLength);                    { Set string length }
+   {$ENDIF}
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                    NEW QUEUED EVENT HANDLER ROUTINES                      }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  PutEventInQueue -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Mar98 LdB   }
+{---------------------------------------------------------------------------}
+FUNCTION PutEventInQueue (Var Event: TEvent): Boolean;
+BEGIN
+   If (QueueCount < QueueMax) Then Begin              { Check room in queue }
+     Queue[QueueHead] := Event;                       { Store event }
+     Inc(QueueHead);                                  { Inc head position }
+     If (QueueHead = QueueMax) Then QueueHead := 0;   { Roll to start check }
+     Inc(QueueCount);                                 { Inc queue count }
+     PutEventInQueue := True;                         { Return successful }
+   End Else PutEventInQueue := False;                 { Return failure }
+END;
+
+{---------------------------------------------------------------------------}
+{  NextQueuedEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Mar98 LdB   }
+{---------------------------------------------------------------------------}
+PROCEDURE NextQueuedEvent(Var Event: TEvent);
+BEGIN
+   If (QueueCount > 0) Then Begin                     { Check queued event }
+     Event := Queue[QueueTail];                       { Fetch next event }
+     Inc(QueueTail);                                  { Inc tail position }
+     If (QueueTail = QueueMax) Then QueueTail := 0;   { Roll to start check }
+     Dec(QueueCount);                                 { Dec queue count }
+   End Else Event.What := evNothing;                  { Return empty event }
+END;
+
+{***************************************************************************}
+{                      UNIT INITIALIZATION ROUTINE                          }
+{***************************************************************************}
+BEGIN
+   ButtonCount := DetectMouse;                        { Detect mouse }
+   DetectVideo;                                       { Detect video }
+   SaveExit := ExitProc;                              { Save old exit }
+   ExitProc := @ExitDrivers;                          { Set new exit }
+END.

+ 623 - 0
fv/fileio.pas

@@ -0,0 +1,623 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{          System independent FILE I/O control             }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail address        }
+{   [email protected] - backup e-mail address         }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                 - Speed Pascal 1.0+       (32 Bit)       }
+{                 - C'T patch to BP         (16 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     12 Jun 96   First DOS/DPMI platform release    }
+{  1.10     12 Mar 97   Windows conversion added.          }
+{  1.20     29 Aug 97   Platform.inc sort added.           }
+{  1.30     12 Jun 98   Virtual pascal 2.0 code added.     }
+{  1.40     10 Sep 98   Checks run & commenting added.     }
+{  1.50     28 Oct 98   Fixed for FPC version 0.998        }
+{                       Only Go32v2 supported no Go32v1    }
+{  1.60     14 Jun 99   References to Common.pas added.    }
+{  1.61     07 Jul 99   Speedsoft SYBIL 2.0 code added.    }
+{  1.62     03 Nov 99   FPC windows support added.         }
+{**********************************************************}
+
+UNIT FileIO;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC} { FPC doesn't support these switches }
+  {$F-} { Short calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$E+} {  Emulation is on }
+  {$N-} {  No 80x87 code generation }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+{$IFDEF OS_DOS}                                       { DOS/DPMI ONLY }
+  {$IFDEF PPC_FPC}                                    { FPC COMPILER }
+    {$IFNDEF GO32V2}                                  { MUST BE GO32V2 }
+    This only works in GO32V2 mode in FPC!
+    {$ENDIF}
+  {$ENDIF}
+{$ENDIF}
+
+USES Common;                                          { Standard GFV unit }
+
+{***************************************************************************}
+{                             PUBLIC CONSTANTS                              }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                         FILE ACCESS MODE CONSTANTS                        }
+{---------------------------------------------------------------------------}
+CONST
+   fa_Create    = $3C00;                              { Create new file }
+   fa_OpenRead  = $3D00;                              { Read access only }
+   fa_OpenWrite = $3D01;                              { Write access only }
+   fa_Open      = $3D02;                              { Read/write access }
+
+{---------------------------------------------------------------------------}
+{                         FILE SHARE MODE CONSTANTS                         }
+{---------------------------------------------------------------------------}
+CONST
+   fm_DenyAll   = $0010;                              { Exclusive file use }
+   fm_DenyWrite = $0020;                              { Deny write access }
+   fm_DenyRead  = $0030;                              { Deny read access }
+   fm_DenyNone  = $0040;                              { Deny no access }
+
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+CONST
+   HFILE_ERROR = -1;                                  { File handle error }
+{$ENDIF}
+
+{***************************************************************************}
+{                          PUBLIC TYPE DEFINITIONS                          }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                              ASCIIZ FILENAME                              }
+{---------------------------------------------------------------------------}
+TYPE
+   AsciiZ = Array [0..255] Of Char;                   { Filename array }
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           FILE CONTROL ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-FileClose----------------------------------------------------------
+The file opened by the handle is closed. If close action is successful
+true is returned but if the handle is invalid or a file error occurs
+false will be returned.
+20Oct98 LdB
+---------------------------------------------------------------------}
+FUNCTION FileClose (Handle: Word): Boolean;
+
+{-FileOpen-----------------------------------------------------------
+Given a valid filename to file that exists, is not locked with a valid
+access mode the file is opened and the file handle returned. If the
+name or mode is invalid or an error occurs the return will be zero.
+27Oct98 LdB
+---------------------------------------------------------------------}
+FUNCTION FileOpen (Var FileName: AsciiZ; Mode: Word): Word;
+
+{-SetFileSize--------------------------------------------------------
+The file opened by the handle is set the given size. If the action is
+successful zero is returned but if the handle is invalid or a file error
+occurs a standard file error value will be returned.
+21Oct98 LdB
+---------------------------------------------------------------------}
+FUNCTION SetFileSize (Handle: Word; FileSize: LongInt): Word;
+
+{-SetFilePos---------------------------------------------------------
+The file opened by the handle is set the given position in the file.
+If the action is successful zero is returned but if the handle is invalid
+the position is beyond the file size or a file error occurs a standard
+file error value will be returned.
+21Oct98 LdB
+---------------------------------------------------------------------}
+FUNCTION SetFilePos (Handle: Word; Pos: LongInt; MoveType: Word;
+Var Actual: LongInt): Word;
+
+{-FileRead-----------------------------------------------------------
+The file opened by the handle has count bytes read from it an placed
+into the given buffer. If the read action is successful the actual bytes
+transfered is returned in actual and the function returns zero. If an
+error occurs the function will return a file error constant and actual
+will contain the bytes transfered before the error if any.
+22Oct98 LdB
+---------------------------------------------------------------------}
+FUNCTION FileRead (Handle: Word; Var Buf; Count: Sw_Word; Var Actual: Sw_Word): Word;
+
+{-FileWrite----------------------------------------------------------
+The file opened by the handle has count bytes written to it from the
+given buffer. If the write action is successful the actual bytes
+transfered is returned in actual and the function returns zero. If an
+error occurs the function will return a file error constant and actual
+will contain the bytes transfered before the error if any.
+22Oct98 LdB
+---------------------------------------------------------------------}
+FUNCTION FileWrite (Handle: Word; Var Buf; Count: Sw_Word; Var Actual: Sw_Word): Word;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                               IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT UNITS }
+
+  {$IFNDEF PPC_SPEED}                                 { NON SPEED COMPILER }
+    {$IFDEF PPC_FPC}                                  { FPC WINDOWS COMPILER }
+    USES Windows;                                     { Standard unit }
+    {$ELSE}                                           { NON FPC COMPILER }
+    USES WinTypes, WinProcs;                          { Stardard units }
+    {$ENDIF}
+  TYPE LongWord = LongInt;                            { Type fixup }
+  {$ELSE}                                             { SPEEDSOFT COMPILER }
+  USES WinNT, WinBase;                                { Standard units }
+  {$ENDIF}
+
+{$ENDIF}
+
+{$IFDEF OS_OS2}                                       { OS2 COMPILERS }
+
+  {$IFDEF PPC_VIRTUAL}                                { VIRTUAL PASCAL UNITS }
+  USES OS2Base;                                       { Standard unit }
+  {$ENDIF}
+
+  {$IFDEF PPC_SPEED}                                  { SPEED PASCAL UNITS }
+  USES BseDos, Os2Def;                                { Standard units }
+  {$ENDIF}
+
+  {$IFDEF PPC_BPOS2}                                  { C'T PATCH TO BP UNITS }
+  USES DosTypes, DosProcs;                            { Standard units }
+  {$ENDIF}
+
+{$ENDIF}
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{  FileClose -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 20Oct98 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION FileClose (Handle: Word): Boolean;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOV BX, Handle;                                  { DOS file handle }
+     MOV AX, $3E00;                                   { Close function }
+     PUSH BP;                                         { Store register }
+     INT $21;                                         { Close the file }
+     POP BP;                                          { Reload register }
+     MOV AL, True;                                    { Preset true }
+     JNC @@Exit1;                                     { Return success }
+     MOV AL, False;                                   { Return failure }
+   @@Exit1:
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   VAR Regs: TRealRegs;
+   BEGIN
+     Regs.RealEBX := Handle;                          { Transfer handle }
+     Regs.RealEAX := $3E00;                           { Close file function }
+     SysRealIntr($21, Regs);                          { Call DOS interrupt }
+     If (Regs.RealFlags AND $1 = 0) Then              { Check carry flag }
+       FileClose := True Else FileClose := False;     { Return true/false }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+BEGIN
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOWS CODE }
+   If (_lclose(Handle) = 0) Then FileClose := True    { Close the file }
+     Else FileClose := False;                         { Closure failed }
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   FileClose := CloseHandle(Handle);                  { Close the file }
+   {$ENDIF}
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+BEGIN
+   If (DosClose(Handle) = 0) Then FileClose := True   { Try to close file }
+     Else FileClose := False;                         { Closure failed }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FileOpen -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION FileOpen (Var FileName: AsciiZ; Mode: Word): Word;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOV AX, Mode;                                    { Mode to open file }
+     XOR CX, CX;                                      { No attributes set }
+     PUSH DS;                                         { Save segment }
+     LDS DX, FileName;                                { Filename to open }
+     PUSH BP;                                         { Store register }
+     INT $21;                                         { Open/create file }
+     POP BP;                                          { Restore register }
+     POP DS;                                          { Restore segment }
+     JNC @@Exit2;                                     { Check for error }
+     XOR AX, AX;                                      { Open fail return 0 }
+   @@Exit2:
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   VAR Regs: TRealRegs;
+   BEGIN
+     SysCopyToDos(LongInt(@FileName), 256);           { Transfer filename }
+     Regs.RealEDX := Tb MOD 16;
+     Regs.RealDS := Tb DIV 16;                        { Linear addr of Tb }
+     Regs.RealEAX := Mode;                            { Mode to open with }
+     Regs.RealECX := 0;                               { No attributes set }
+     SysRealIntr($21, Regs);                          { Call DOS int 21 }
+     If (Regs.RealFlags AND 1 <> 0) Then FileOpen := 0{ Error encountered }
+       Else FileOpen := Regs.RealEAX AND $FFFF;       { Return file handle }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+VAR Hnd: Integer; OpenMode: Sw_Word;
+  {$IFDEF BIT_16} Buf: TOfStruct; {$ENDIF}            { 16 BIT VARIABLES }
+  {$IFDEF BIT_32} ShareMode, Flags: LongInt; {$ENDIF} { 32 BIT VARIABLES }
+BEGIN
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOW CODE }
+   If (Mode = fa_Create) Then OpenMode := of_Create   { Set create mask bit }
+     Else OpenMode := Mode AND $00FF;                 { Set open mask bits }
+   Hnd := OpenFile(FileName, Buf, OpenMode);          { Open the file }
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   If (Mode = fa_Create) Then Begin                   { Create file }
+     OpenMode := Generic_Read OR Generic_Write;       { Set access mask bit }
+     Flags := Create_Always;                          { Create always mask }
+   End Else Begin                                     { Open the file }
+     OpenMode := Generic_Read;                        { Read only access set }
+     If (Mode AND $0001 <> 0) Then                    { Check write flag }
+       OpenMode := OpenMode AND NOT Generic_Read;     { Write only access set }
+     If (Mode AND $0002 <> 0) Then                    { Check read/write flag }
+       OpenMode := OpenMode OR Generic_Write;         { Read/Write access }
+     Flags := Open_Existing;                          { Open existing mask }
+   End;
+   ShareMode := file_Share_Read OR
+     file_Share_Write;                                { Deny none flag set }
+   Hnd := CreateFile(FileName, OpenMode, ShareMode,
+    Nil, Flags, File_Attribute_Normal, 0);            { Open the file }
+   {$ENDIF}
+   If (Hnd <> -1) Then FileOpen := Hnd Else           { Return handle }
+     FileOpen := 0;                                   { Return error }
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+VAR OpenFlags, OpenMode: Word; Handle, ActionTaken: Sw_Word;
+BEGIN
+   If (Mode = fa_Create) Then Begin                   { Create file }
+     OpenMode := Open_Flags_NoInherit OR
+       Open_Share_DenyNone OR
+       Open_Access_ReadWrite;                         { Open mode }
+     OpenFlags := OPEN_ACTION_CREATE_IF_NEW OR
+        OPEN_ACTION_REPLACE_IF_EXISTS;                { Open flags }
+   End Else Begin
+     OpenMode := Mode AND $00FF OR
+       Open_Share_DenyNone;                           { Set open mode bits }
+     OpenFlags := OPEN_ACTION_OPEN_IF_EXISTS;         { Set open flags }
+   End;
+   {$IFDEF PPC_BPOS2}                                 { C'T patched COMPILER }
+   If (DosOpen(@FileName, Handle, ActionTaken, 0, 0,
+     OpenFlags, OpenMode, 0) = 0) Then
+       FileOpen := Handle Else FileOpen := 0;         { Return handle/fail }
+   {$ELSE}                                            { OTHER OS2 COMPILERS }
+   If (DosOpen(FileName, Handle, ActionTaken, 0, 0,
+     OpenFlags, OpenMode, Nil) = 0) Then
+       FileOpen := Handle Else FileOpen := 0;         { Return handle/fail }
+   {$ENDIF}
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  SetFileSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Feb97 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION SetFileSize (Handle: Word; FileSize: LongInt): Word;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOV DX, FileSize.Word[0];                        { Load file position }
+     MOV CX, FileSize.Word[2];
+     MOV BX, Handle;                                  { Load file handle }
+     MOV AX, $4200;                                   { Load function id }
+     PUSH BP;                                         { Store register }
+     INT $21;                                         { Position the file }
+     POP BP;                                          { Reload register }
+     JC @@Exit3;                                      { Exit if error }
+     XOR CX, CX;                                      { Force truncation }
+     MOV BX, Handle;                                  { File handle }
+     MOV AX, $4000;                                   { Load function id }
+     PUSH BP;                                         { Store register }
+     INT $21;                                         { Truncate file }
+     POP BP;                                          { Reload register }
+     JC @@Exit3;                                      { Exit if error }
+     XOR AX, AX;                                      { Return successful }
+   @@Exit3:
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   VAR Regs: TRealRegs;
+   BEGIN
+     Regs.RealEDX := FileSize AND $FFFF;              { Lo word of filesize }
+     Regs.RealECX := (FileSize SHR 16) AND $FFFF;     { Hi word of filesize }
+     Regs.RealEBX := LongInt(Handle);                 { Load file handle }
+     Regs.RealEAX := $4000;                           { Load function id }
+     SysRealIntr($21, Regs);                          { Call DOS int 21 }
+     If (Regs.RealFlags AND 1 <> 0) Then
+       SetFileSize := Regs.RealEAX AND $FFFF          { Error encountered }
+       Else SetFileSize := 0;                         { Return successful }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+VAR {$IFDEF BIT_16} Buf, {$ENDIF} Actual: LongInt;
+BEGIN
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOWS CODE }
+   Actual := _llseek(Handle, FileSize, 0);            { Position file }
+   If (Actual = FileSize) Then Begin                  { No position error }
+     Actual := _lwrite(Handle, Pointer(@Buf), 0);     { Truncate the file }
+     If (Actual <> -1) Then SetFileSize := 0 Else     { No truncate error }
+       SetFileSize := 103;                            { File truncate error }
+   End Else SetFileSize := 103;                       { File truncate error }
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   Actual := SetFilePointer(Handle, FileSize, Nil, 0);{ Position file }
+   If (Actual = FileSize) Then Begin                  { No position error }
+     If SetEndOfFile(Handle) Then SetFileSize := 0    { No truncate error }
+       Else SetFileSize := 103;                       { File truncate error }
+   End Else SetFileSize := 103;                       { File truncate error }
+   {$ENDIF}
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+BEGIN
+   {$IFDEF PPC_BPOS2}                                 { C'T patched COMPILER }
+   SetFileSize := DosNewSize(Handle, FileSize);       { Truncate the file }
+   {$ELSE}                                            { OTHER OS2 COMPILERS }
+   SetFileSize := DosSetFileSize(Handle, FileSize);   { Truncate the file }
+   {$ENDIF}
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  SetFilePos -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Feb97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION SetFilePos (Handle: Word; Pos: LongInt; MoveType: Word;
+Var Actual: LongInt): Word;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOV AX, MoveType;                                { Load move type }
+     MOV AH, $42;                                     { Load function id }
+     MOV DX, Pos.Word[0];                             { Load file position }
+     MOV CX, Pos.Word[2];
+     MOV BX, Handle;                                  { Load file handle }
+     PUSH BP;                                         { Store register }
+     INT $21;                                         { Position the file }
+     POP BP;                                          { Reload register }
+     JC @@Exit6;
+     LES DI, Actual;                                  { Actual var addr }
+     MOV ES:[DI], AX;
+     MOV ES:[DI+2], DX;                               { Update actual }
+     XOR AX, AX;                                      { Set was successful }
+   @@Exit6:
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   VAR Regs: TRealRegs;
+   BEGIN
+     Actual := 0;                                     { Zero actual count }
+     Regs.RealEAX := ($42 SHL 8) + Byte(MoveType);    { Set function id }
+     Regs.RealEBX := LongInt(Handle);                 { Fetch file handle }
+     Regs.RealEDX := Pos AND $FFFF;                   { Keep low word }
+     Regs.RealECX := Pos SHR 16;                      { Keep high word }
+     SysRealIntr($21, Regs);                          { Call dos interrupt }
+     If (Regs.RealFlags AND $1 = 0) Then Begin
+       Actual := Lo(Regs.RealEDX) SHL 16 +
+         Lo(Regs.RealEAX);                            { Current position }
+       SetFilePos := 0;                               { Function successful }
+     End Else SetFilePos := Lo(Regs.RealEAX);         { I/O error returned }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WINDOWS CODE }
+BEGIN
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOWS CODE }
+   Actual := _llseek(Handle, Pos, MoveType);          { Position file }
+   If (Actual <> -1) Then SetFilePos := 0 Else        { No position error }
+     SetFilePos := 107;                               { File position error }
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   Actual := SetFilePointer(Handle, Pos, Nil, MoveType);{ Position file }
+   If (Actual <> -1) Then SetFilePos := 0 Else        { No position error }
+     SetFilePos := 107;                               { File position error }
+   {$ENDIF}
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+BEGIN
+   {$IFDEF PPC_BPOS2}
+   If (DosChgFilePtr(Handle, Pos, MoveType, Actual)=0){ Set file position }
+     Then SetFilePos := 0 Else SetFilePos := 107;     { File position error }
+   {$ELSE}                                            { OTHER OS2 COMPILERS }
+   If (DosSetFilePtr(Handle, Pos, MoveType, Actual)=0){ Set file position }
+     Then SetFilePos := 0 Else SetFilePos := 107;     { File position error }
+   {$ENDIF}
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FileRead -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION FileRead (Handle: Word; Var Buf; Count: Sw_Word; Var Actual: Sw_Word): Word;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     XOR AX, AX;                                      { Zero register }
+     LES DI, Actual;                                  { Actual var address }
+     MOV ES:[DI], AX;                                 { Zero actual var }
+     PUSH DS;                                         { Save segment }
+     LDS DX, Buf;                                     { Data destination }
+     MOV CX, Count;                                   { Amount to read }
+     MOV BX, Handle;                                  { Load file handle }
+     MOV AX, $3F00;                                   { Load function id }
+     PUSH BP;                                         { Store register }
+     INT $21;                                         { Read from file }
+     POP BP;                                          { Reload register }
+     POP DS;                                          { Restore segment }
+     JC @@Exit4;                                      { Check for error }
+     LES DI, Actual;                                  { Actual var address }
+     MOV ES:[DI], AX;                                 { Update bytes moved }
+     XOR AX, AX;                                      { Return success }
+   @@Exit4:
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   BEGIN
+     Actual := System.Do_Read(LongInt(Handle),
+       LongInt(@Buf), Count);                         { Read data from file }
+     FileRead := InOutRes;                            { I/O status returned }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+
+BEGIN
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOWS CODE }
+   Actual := _lread(Handle, Pointer(@Buf), Count);    { Read from file }
+   If (Actual = Count) Then FileRead := 0 Else        { No read error }
+     FileRead := 104;                                 { File read error }
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   If ReadFile(Handle, Buf, Count, DWord(Actual),
+     Nil) AND (Actual = Count) Then FileRead := 0     { No read error }
+     Else FileRead := 104;                            { File read error }
+   {$ENDIF}
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+BEGIN
+   If (DosRead(Handle, Buf, Count, Actual) = 0) AND   { Read from file }
+   (Actual = Count) Then FileRead := 0 Else           { No read error }
+     FileRead := 104;                                 { File read error }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FileWrite -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct98 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION FileWrite (Handle: Word; Var Buf; Count: Sw_Word; Var Actual: Sw_Word): Word;
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     XOR AX, AX;                                      { Zero register }
+     LES DI, Actual;                                  { Actual var address }
+     MOV ES:[DI], AX;                                 { Zero actual var }
+     PUSH DS;                                         { Save segment }
+     LDS DX, Buf;                                     { Data source buffer }
+     MOV CX, Count;                                   { Amount to write }
+     MOV BX, Handle;                                  { Load file handle }
+     MOV AX, $4000;                                   { Load function id }
+     PUSH BP;                                         { Store register }
+     INT $21;                                         { Write to file }
+     POP BP;                                          { Reload register }
+     POP DS;                                          { Restore segment }
+     JC @@Exit5;                                      { Check for error }
+     LES DI, Actual;                                  { Actual var address }
+     MOV ES:[DI], AX;                                 { Update bytes moved }
+     XOR AX, AX;                                      { Write successful }
+   @@Exit5:
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   BEGIN
+     Actual := System.Do_Write(LongInt(Handle),
+       LongInt(@Buf), Count);                         { Write data to file }
+     FileWrite := InOutRes;                           { I/O status returned }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+BEGIN
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOWS CODE }
+   Actual := _lwrite(Handle, Pointer(@Buf), Count);   { Write to file }
+   If (Actual = Count) Then FileWrite := 0 Else       { No write error }
+     FileWrite := 105;                                { File write error }
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   If WriteFile(Handle, Buf, Count, DWord(Actual),
+     Nil) AND (Actual = Count) Then FileWrite := 0    { No write error }
+     Else FileWrite := 105;                           { File write error }
+   {$ENDIF}
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+BEGIN
+   If (DosWrite(Handle, Buf, Count, Actual) = 0) AND  { Write to file }
+   (Actual = Count) Then FileWrite := 0 Else          { No write error }
+     FileWrite := 105;                                { File write error }
+END;
+{$ENDIF}
+
+END.

+ 225 - 0
fv/gadgets.pas

@@ -0,0 +1,225 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{   System independent GRAPHICAL clone of GADGETS.PAS      }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1999 by Leon de Boer                     }
+{   [email protected]  - primary e-mail address        }
+{   [email protected] - backup e-mail address         }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                                                          }
+{*******************[ DOCUMENTATION ]**********************}
+{                                                          }
+{   This unit had to be for GFV due to some problems with  }
+{  the original Borland International implementation.      }
+{                                                          }
+{   First it used the DOS unit for it's time calls in the  }
+{  TClockView object. Since this unit can not be compiled  }
+{  under WIN/NT/OS2 we use a new unit TIME.PAS which was   }
+{  created and works under these O/S.                      }
+{                                                          }
+{   Second the HeapView object accessed MemAvail from in   }
+{  the Draw call. As GFV uses heap memory during the Draw  }
+{  call the OldMem value always met the test condition in  }
+{  the update procedure. The consequence was the view      }
+{  would continually redraw. By moving the memavail call   }
+{  the update procedure this eliminates this problem.      }
+{                                                          }
+{   Finally the original object relied on the font char    }
+{  blocks being square to erase it's entire view area as   }
+{  it used a simple writeline call in the Draw method.     }
+{  Under GFV font blocks are not necessarily square and    }
+{  so both objects had their Draw routines rewritten. As   }
+{  the Draw had to be redone it was done in the GFV split  }
+{  drawing method to accelerate the graphical speed.       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     12 Nov 99   First multi platform release       }
+{**********************************************************}
+
+UNIT Gadgets;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F-} { Near calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES Common, Time, Objects, Drivers, Views, App;      { Standard GFV units }
+
+{***************************************************************************}
+{                        PUBLIC OBJECT DEFINITIONS                          }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                  THeapView OBJECT - ANCESTOR VIEW OBJECT                  }
+{---------------------------------------------------------------------------}
+TYPE
+   THeapView = OBJECT (TView)
+         OldMem: LongInt;                             { Last memory count }
+      PROCEDURE Update;
+      PROCEDURE DrawBackGround; Virtual;
+   END;
+   PHeapView = ^THeapView;                            { Heapview pointer }
+
+{---------------------------------------------------------------------------}
+{                 TClockView OBJECT - ANCESTOR VIEW OBJECT                  }
+{---------------------------------------------------------------------------}
+TYPE
+   TClockView = OBJECT (TView)
+         Refresh : Byte;                              { Refresh rate }
+         LastTime: Longint;                           { Last time displayed }
+         TimeStr : String[10];                        { Time string }
+      CONSTRUCTOR Init (Var Bounds: TRect);
+      FUNCTION FormatTimeStr (H, M, S: Word): String; Virtual;
+      PROCEDURE Update; Virtual;
+      PROCEDURE DrawBackGround; Virtual;
+   END;
+   PClockView = ^TClockView;                          { Clockview ptr }
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                             IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{***************************************************************************}
+{                              OBJECT METHODS                               }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          THeapView OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--THeapView----------------------------------------------------------------}
+{  Update -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Nov99 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE THeapView.Update;
+BEGIN
+   If (OldMem <> MemAvail) Then Begin                 { Memory differs }
+     OldMem := MemAvail;                              { Hold memory avail }
+     SetDrawMask(vdBackGnd OR vdInner);               { Set draw masks }
+     DrawView;                                        { Now redraw }
+   End;
+END;
+
+{--THeapView----------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Nov99 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE THeapView.DrawBackGround;
+VAR HOfs: Integer; S: String;
+BEGIN
+   Str(OldMem, S);                                    { Convert to string }
+   HOfs := ColourOfs;                                 { Hold any offset }
+   ColourOfs := 2;                                    { Set colour offset }
+   Inherited DrawBackGround;                          { Clear the backgound }
+   ColourOfs := HOfs;                                 { Reset any offset }
+   WriteStr(-(RawSize.X-TextWidth(S)+1), 0, S, 2);    { Write the string }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TClockView OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TClockView---------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Nov99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TClockView.Init (Var Bounds: TRect);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   FillChar(LastTime, SizeOf(LastTime), #$FF);        { Fill last time }
+   TimeStr := '';                                     { Empty time string }
+   Refresh := 1;                                      { Refresh per second }
+END;
+
+{--TClockView---------------------------------------------------------------}
+{  FormatStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Nov99 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION TClockView.FormatTimeStr (H, M, S: Word): String;
+VAR Hs, Ms, Ss: String;
+BEGIN
+   Str(H, Hs);                                        { Convert hour string }
+   While (Length(Hs) < 2) Do Hs := '0' + Hs;          { Add lead zero's }
+   Str(M, Ms);                                        { Convert min string }
+   While (Length(Ms) < 2) Do Ms := '0' + Ms;          { Add lead zero's }
+   Str(S, Ss);                                        { Convert sec string }
+   While (Length(Ss) < 2) Do Ss := '0' + Ss;          { Add lead zero's }
+   FormatTimeStr := Hs + ':'+ Ms + ':' + Ss;          { Return string }
+END;
+
+{--TClockView---------------------------------------------------------------}
+{  Update -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Nov99 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TClockView.Update;
+VAR Hour, Min, Sec, Sec100: Word;
+BEGIN
+   GetTime(Hour, Min, Sec, Sec100);                   { Get current time }
+   If (Abs(Sec - LastTime) >= Refresh) Then Begin     { Refresh time elapsed }
+     LastTime := Sec;                                 { Hold second }
+     TimeStr := FormatTimeStr(Hour, Min, Sec);        { Create time string }
+     SetDrawMask(vdBackGnd OR vdInner);               { Set draw masks }
+     DrawView;                                        { Now redraw }
+   End;
+END;
+
+{--TClockView---------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Nov99 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TClockView.DrawBackGround;
+VAR HOfs: Integer;
+BEGIN
+   HOfs := ColourOfs;                                 { Hold any offset }
+   ColourOfs := 2;                                    { Set colour offset }
+   Inherited DrawBackGround;                          { Clear the backgound }
+   ColourOfs := HOfs;                                 { Reset any offset }
+   WriteStr(0, 0, TimeStr, 2);                        { Write the string }
+END;
+
+END.

+ 302 - 0
fv/gfvgraph.pas

@@ -0,0 +1,302 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{          System independent GFV GRAPHICS UNIT            }
+{                                                          }
+{   Copyright (c) 1999 by Leon de Boer                     }
+{   [email protected]  - primary e-mail address        }
+{   [email protected] - backup e-mail address         }
+{                                                          }
+{   This unit provides the interlink between the graphics  }
+{   used in GFV and the graphics API for the different     }
+{   operating systems.                                     }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                 - Speed Pascal 1.0+       (32 Bit)       }
+{                                                          }
+{*****************[ REVISION HISTORY ]*********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------- }
+{  1.00     26 Nov 99   Unit started from relocated code   }
+{                       originally from views.pas          }
+{**********************************************************}
+
+UNIT GFVGraph;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC} { FPC doesn't support these switches }
+  {$F-} { Near far calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$E+} { Emulation is on }
+  {$N-} { No 80x87 code generation }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+{***************************************************************************}
+{                              PUBLIC CONSTANTS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                          STANDARD COLOUR CONSTANTS                        }
+{---------------------------------------------------------------------------}
+CONST
+   Black        = 0;                                  { Black }
+   Blue         = 1;                                  { Blue }
+   Green        = 2;                                  { Green }
+   Cyan         = 3;                                  { Cyan }
+   Red          = 4;                                  { Red }
+   Magenta      = 5;                                  { Magenta }
+   Brown        = 6;                                  { Brown }
+   LightGray    = 7;                                  { Light grey }
+   DarkGray     = 8;                                  { Dark grey }
+   LightBlue    = 9;                                  { Light blue }
+   LightGreen   = 10;                                 { Light green }
+   LightCyan    = 11;                                 { Light cyan }
+   LightRed     = 12;                                 { Light red }
+   LightMagenta = 13;                                 { Light magenta }
+   Yellow       = 14;                                 { Yellow }
+   White        = 15;                                 { White }
+
+{---------------------------------------------------------------------------}
+{                            WRITE MODE CONSTANTS                           }
+{---------------------------------------------------------------------------}
+CONST
+   NormalPut = 0;                                     { Normal overwrite }
+   CopyPut   = 0;                                     { Normal put image }
+   AndPut    = 1;                                     { AND colour write }
+   OrPut     = 2;                                     { OR colour write }
+   XorPut    = 3;                                     { XOR colour write }
+   NotPut    = 4;                                     { NOT colour write }
+
+{---------------------------------------------------------------------------}
+{                          CLIP CONTROL CONSTANTS                           }
+{---------------------------------------------------------------------------}
+CONST
+   ClipOn = True;                                     { Clipping on }
+   ClipOff = False;                                   { Clipping off }
+
+{---------------------------------------------------------------------------}
+{                       VIDEO CARD DETECTION CONSTANTS                      }
+{---------------------------------------------------------------------------}
+CONST
+   Detect = 0;                                        { Detect video }
+
+{---------------------------------------------------------------------------}
+{                        TEXT JUSTIFICATION CONSTANTS                       }
+{---------------------------------------------------------------------------}
+CONST
+   LeftText   = 0;                                    { Left justify }
+   CenterText = 1;                                    { Centre justify }
+   RightText  = 2;                                    { Right justify }
+   BottomText = 0;                                    { Bottom justify }
+   TopText    = 2;                                    { Top justify }
+
+{---------------------------------------------------------------------------}
+{                           FILL PATTERN CONSTANTS                          }
+{---------------------------------------------------------------------------}
+CONST
+   EmptyFill      = 0;                                { No fill pattern }
+   SolidFill      = 1;                                { Solid colour }
+   LineFill       = 2;                                { Line fill }
+   LtSlashFill    = 3;                                { Fwd slash line type }
+   SlashFill      = 4;                                { Fwd slash pattern }
+   BkSlashFill    = 5;                                { Back slash pattern }
+   LtBkSlashFill  = 6;                                { Back slash line type }
+   HatchFill      = 7;                                { Hatch pattern }
+   XHatchFill     = 8;                                { Cross hatch pattern }
+   InterleaveFill = 9;                                { Interleaved pattern }
+   WideDotFill    = 10;                               { Wide dot pattern }
+   CloseDotFill   = 11;                               { Close dot pattern }
+   UserFill       = 12;                               { User defined fill }
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+{---------------------------------------------------------------------------}
+{      WIN/NT STANDARD TColorRef CONSTANTS TO MATCH COLOUR CONSTANTS        }
+{---------------------------------------------------------------------------}
+CONST
+   rgb_Black        = $00000000;                      { 0 = Black }
+   rgb_Blue         = $007F0000;                      { 1 = Blue }
+   rgb_Green        = $00007F00;                      { 2 = Green }
+   rgb_Cyan         = $007F7F00;                      { 3 = Cyan }
+   rgb_Red          = $0000007F;                      { 4 = Red }
+   rgb_Magenta      = $007F7F00;                      { 5 = Magenta }
+   rgb_Brown        = $00007F7F;                      { 6 = Brown }
+   rgb_LightGray    = $00AFAFAF;                      { 7 = LightGray }
+   rgb_DarkGray     = $004F4F4F;                      { 8 = DarkGray }
+   rgb_LightBlue    = $00FF0000;                      { 9 = Light Blue }
+   rgb_LightGreen   = $0000FF00;                      { 10 = Light Green }
+   rgb_LightCyan    = $00FFFF00;                      { 11 = Light Cyan }
+   rgb_LightRed     = $000000FF;                      { 12 = Light Red }
+   rgb_LightMagenta = $00FFFF00;                      { 13 = Light Magenta }
+   rgb_Yellow       = $0000FFFF;                      { 14 = Yellow }
+   rgb_White        = $00FFFFFF;                      { 15 = White }
+{$ENDIF}
+
+{***************************************************************************}
+{                          PUBLIC TYPE DEFINITIONS                          }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                        ViewPortType RECORD DEFINITION                     }
+{---------------------------------------------------------------------------}
+TYPE
+   ViewPortType = PACKED RECORD
+     X1, Y1, X2, Y2: Integer;                         { Corners of viewport }
+     Clip          : Boolean;                         { Clip status }
+   END;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                     GRAPHICS MODE CONTROL ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-SetWriteMode-------------------------------------------------------
+Sets the current write mode constant all subsequent draws etc. are
+then via the set mode.
+26Nov99 LdB
+---------------------------------------------------------------------}
+PROCEDURE SetWriteMode (Mode: Byte);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                         VIEWPORT CONTROL ROUTINES                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-GetViewSettings----------------------------------------------------
+Returns the current viewport and clip parameters in the variable.
+26Nov99 LdB
+---------------------------------------------------------------------}
+PROCEDURE GetViewSettings (Var CurrentViewPort: ViewPortType);
+
+{-SetViewPort--------------------------------------------------------
+Set the current viewport and clip parameters to that requested.
+26Nov99 LdB
+---------------------------------------------------------------------}
+PROCEDURE SetViewPort (X1, Y1, X2, Y2: Integer; Clip: Boolean);
+
+{***************************************************************************}
+{                        INITIALIZED PUBLIC VARIABLES                       }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                INITIALIZED DOS/DPMI/WIN/NT/OS2 VARIABLES                  }
+{---------------------------------------------------------------------------}
+CONST
+   WriteMode      : Byte = 0;                         { Current write mode }
+   SysScreenWidth : Integer = 640;                    { Default screen width }
+   SysScreenHeight: Integer = 480;                    { Default screen height}
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                               IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{***************************************************************************}
+{                      PRIVATE INITIALIZED VARIABLES                        }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{               DOS/DPMI/WIN/NT/OS2 INITIALIZED VARIABLES                   }
+{---------------------------------------------------------------------------}
+CONST
+   Cxp     : Integer = 0;                             { Current x position }
+   Cyp     : Integer = 0;                             { Current y position }
+   ViewPort: ViewPortType = (X1:0; Y1:0; X2: 639;
+                             Y2: 479; Clip: True);    { Default viewport }
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                     GRAPHICS MODE CONTROL ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  SetWriteMode -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 09Aug99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE SetWriteMode (Mode: Byte);
+BEGIN
+   WriteMode := Mode;                                 { Hold writemode value }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                         VIEW PORT CONTROL ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  GetViewSettings -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 09Aug99 LdB   }
+{---------------------------------------------------------------------------}
+PROCEDURE GetViewSettings (Var CurrentViewPort: ViewPortType);
+BEGIN
+   CurrentViewPort := ViewPort;                       { Return view port }
+END;
+
+{---------------------------------------------------------------------------}
+{  SetViewPort -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 09Aug99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE SetViewPort (X1, Y1, X2, Y2: Integer; Clip: Boolean);
+BEGIN
+   If (X1 < 0) Then X1 := 0;                          { X1 negative fix }
+   If (X1 > SysScreenWidth) Then
+     X1 := SysScreenWidth;                            { X1 off screen fix }
+   If (Y1 < 0) Then Y1 := 0;                          { Y1 negative fix }
+   If (Y1 > SysScreenHeight) Then
+     Y1 := SysScreenHeight;                           { Y1 off screen fix }
+   If (X2 < 0) Then X2 := 0;                          { X2 negative fix }
+   If (X2 > SysScreenWidth) Then X2 := SysScreenWidth;{ X2 off screen fix }
+   If (Y2 < 0) Then Y2 := 0;                          { Y2 negative fix }
+   If (Y2 > SysScreenHeight) Then
+     Y2 := SysScreenHeight;                           { Y2 off screen fix }
+   ViewPort.X1 := X1;                                 { Set X1 port value }
+   ViewPort.Y1 := Y1;                                 { Set Y1 port value }
+   ViewPort.X2 := X2;                                 { Set X2 port value }
+   ViewPort.Y2 := Y2;                                 { Set Y2 port value }
+   ViewPort.Clip := Clip;                             { Set port clip value }
+   Cxp := X1;                                         { Set current x pos }
+   Cyp := Y1;                                         { Set current y pos }
+END;
+
+END.

+ 379 - 0
fv/histlist.pas

@@ -0,0 +1,379 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{   System independent GRAPHICAL clone of HISTLIST.PAS     }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail address        }
+{   [email protected] - backup e-mail address         }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     11 Nov 96   First DOS/DPMI platform release.   }
+{  1.10     13 Jul 97   Windows platform code added.       }
+{  1.20     29 Aug 97   Platform.inc sort added.           }
+{  1.30     13 Oct 97   Delphi 2 32 bit code added.        }
+{  1.40     05 May 98   Virtual pascal 2.0 code added.     }
+{  1.50     30 Sep 99   Complete recheck preformed         }
+{  1.51     03 Nov 99   FPC windows support added          }
+{**********************************************************}
+
+UNIT HistList;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F-} { Short calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES Common, Objects;                                 { Standard GFV units }
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                     HISTORY SYSTEM CONTROL ROUTINES                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-InitHistory--------------------------------------------------------
+Initializes the history system usually called from Application.Init
+30Sep99 LdB
+---------------------------------------------------------------------}
+PROCEDURE InitHistory;
+
+{-DoneHistory--------------------------------------------------------
+Destroys the history system usually called from Application.Done
+30Sep99 LdB
+---------------------------------------------------------------------}
+PROCEDURE DoneHistory;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          HISTORY ITEM ROUTINES                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-HistoryCount-------------------------------------------------------
+Returns the number of strings in the history list with ID number Id.
+30Sep99 LdB
+---------------------------------------------------------------------}
+FUNCTION HistoryCount (Id: Byte): Word;
+
+{-HistoryStr---------------------------------------------------------
+Returns the Index'th string in the history list with ID number Id.
+30Sep99 LdB
+---------------------------------------------------------------------}
+FUNCTION HistoryStr (Id: Byte; Index: Integer): String;
+
+{-ClearHistory-------------------------------------------------------
+Removes all strings from all history lists.
+30Sep99 LdB
+---------------------------------------------------------------------}
+PROCEDURE ClearHistory;
+
+{-HistoryAdd---------------------------------------------------------
+Adds the string Str to the history list indicated by Id.
+30Sep99 LdB
+---------------------------------------------------------------------}
+PROCEDURE HistoryAdd (Id: Byte; Const Str: String);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{              HISTORY STREAM STORAGE AND RETREIVAL ROUTINES                }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-LoadHistory--------------------------------------------------------
+Reads the application's history block from the stream S by reading the
+size of the block, then the block itself. Sets HistoryUsed to the end
+of the block read. Use LoadHistory to restore a history block saved
+with StoreHistory
+30Sep99 LdB
+---------------------------------------------------------------------}
+PROCEDURE LoadHistory (Var S: TStream);
+
+{-StoreHistory--------------------------------------------------------
+Writes the currently used portion of the history block to the stream
+S, first writing the length of the block then the block itself. Use
+the LoadHistory procedure to restore the history block.
+30Sep99 LdB
+---------------------------------------------------------------------}
+PROCEDURE StoreHistory (Var S: TStream);
+
+{***************************************************************************}
+{                        INITIALIZED PUBLIC VARIABLES                       }
+{***************************************************************************}
+{---------------------------------------------------------------------------}
+{                 INITIALIZED DOS/DPMI/WIN/NT/OS2 VARIABLES                 }
+{---------------------------------------------------------------------------}
+CONST
+   HistorySize: Word = 1024;                          { Maximum history size }
+   HistoryUsed: LongInt = 0;                          { History used }
+   HistoryBlock: Pointer = Nil;                       { Storage block }
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{***************************************************************************}
+{                      PRIVATE RECORD DEFINITIONS                           }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                       THistRec RECORD DEFINITION                          }
+{---------------------------------------------------------------------------}
+TYPE
+   THistRec = PACKED RECORD
+     Zero: byte;                                      { Start marker }
+     Id  : byte;                                      { History id }
+     Str : String;                                    { History string }
+   END;
+   PHistRec = ^THistRec;                              { History record ptr }
+
+{***************************************************************************}
+{                      UNINITIALIZED PRIVATE VARIABLES                      }
+{***************************************************************************}
+{---------------------------------------------------------------------------}
+{                UNINITIALIZED DOS/DPMI/WIN/NT/OS2 VARIABLES                }
+{---------------------------------------------------------------------------}
+VAR
+   CurId: Byte;                                       { Current history id }
+   CurString: PString;                                { Current string }
+
+{***************************************************************************}
+{                          PRIVATE UNIT ROUTINES                            }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{  StartId -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE StartId (Id: Byte);
+BEGIN
+   CurId := Id;                                       { Set current id }
+   CurString := HistoryBlock;                         { Set current string }
+END;
+
+{---------------------------------------------------------------------------}
+{  DeleteString -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE DeleteString;
+VAR Len: Integer; P, P2: PChar;
+BEGIN
+   P := PChar(CurString);                             { Current string }
+   P2 := PChar(CurString);                            { Current string }
+   Len := PByte(P2)^+3;                               { Length of data }
+   Dec(P, 2);                                         { Correct position }
+   Inc(P2, PByte(P2)^+1);                             { Next hist record }
+   Move(P2^, P^, HistoryUsed - LongInt(P2));          { Shuffle history }
+   Dec(HistoryUsed, Len);                             { Adjust history used }
+END;
+
+{---------------------------------------------------------------------------}
+{  AdvanceStringPtr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB  }
+{---------------------------------------------------------------------------}
+PROCEDURE AdvanceStringPtr;
+VAR P: PHistRec;
+BEGIN
+   While (CurString <> Nil) Do Begin
+     Inc(PChar(CurString), PByte(CurString)^+1);      { Move to next string }
+     If (LongInt(CurString) >= HistoryUsed) Then Begin{ Last string check }
+       CurString := Nil;                              { Clear current string }
+       Exit;                                          { Now exit }
+     End;
+     P := PHistRec(CurString);                        { Transfer record ptr }
+     Inc(PChar(CurString), 2);                        { Move to string }
+     If (P^.Id = CurId) Then Exit;                    { Found the string }
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  InsertString -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE InsertString (Id: Byte; Const Str: String);
+VAR P1, P2: PChar;
+BEGIN
+   While ((HistoryUsed-LongInt(HistoryBlock) +
+    Length(Str) > HistorySize)) Do RunError(199);   { Check sufficient memory }
+   P1 := PChar(HistoryBlock)+1;                     { First history record }
+   P2 := P1+Length(Str)+3;                          { History record after }
+   Move(P1^, P2^, HistoryUsed -
+     LongInt(HistoryBlock) - 1);                    { Shuffle history data }
+   PHistRec(P1)^.Zero := 0;                         { Set marker byte }
+   PHistRec(P1)^.Id := Id;                          { Set history id }
+   {$IFDEF PPC_DELPHI3}                             { DELPHI3+ COMPILER }
+   Move(Str[1], PHistRec(P1)^.Str[1], Length(Str)); { Set history string }
+   SetLength(PHistRec(P1)^.Str, Length(Str));       { Set string length }
+   {$ELSE}                                          { OTHER COMPILERS }
+   Move(Str[0], PHistRec(P1)^.Str, Length(Str)+1);  { Set history string }
+   {$ENDIF}
+   Inc(HistoryUsed, Length(Str)+3);                 { Inc history used }
+END;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                     HISTORY SYSTEM CONTROL ROUTINES                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  InitHistory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE InitHistory;
+BEGIN
+   GetMem(HistoryBlock, HistorySize);                 { Allocate block }
+   ClearHistory;                                      { Clear the history }
+END;
+
+{---------------------------------------------------------------------------}
+{  DoneHistory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE DoneHistory;
+BEGIN
+   If (HistoryBlock <> Nil) Then                      { History block valid }
+     FreeMem(HistoryBlock, HistorySize);              { Release history block }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          HISTORY ITEM ROUTINES                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  HistoryCount -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION HistoryCount(Id: Byte): Word;
+VAR Count: Word;
+BEGIN
+   StartId(Id);                                       { Set to first record }
+   Count := 0;                                        { Clear count }
+   If (HistoryBlock <> Nil) Then Begin                { History initalized }
+     AdvanceStringPtr;                                { Move to first string }
+     While (CurString <> Nil) Do Begin
+       Inc(Count);                                    { Add one to count }
+       AdvanceStringPtr;                              { Move to next string }
+     End;
+  End;
+  HistoryCount := Count;                              { Return history count }
+END;
+
+{---------------------------------------------------------------------------}
+{  HistoryStr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION HistoryStr(Id: Byte; Index: Integer): String;
+VAR I: Integer;
+BEGIN
+   StartId(Id);                                       { Set to first record }
+   If (HistoryBlock <> Nil) Then Begin                { History initalized }
+     For I := 0 To Index Do AdvanceStringPtr;         { Find indexed string }
+     If (CurString <> Nil) Then
+       HistoryStr := CurString^ Else                  { Return string }
+       HistoryStr := '';                              { Index not found }
+   End Else HistoryStr := '';                         { History uninitialized }
+END;
+
+{---------------------------------------------------------------------------}
+{  ClearHistory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE ClearHistory;
+BEGIN
+   If (HistoryBlock <> Nil) Then Begin                { History initiated }
+     PChar(HistoryBlock)^ := #0;                      { Clear first byte }
+     HistoryUsed := LongInt(HistoryBlock) + 1;        { Set position }
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  HistoryAdd -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE HistoryAdd (Id: Byte; Const Str: String);
+BEGIN
+   If (Str = '') Then Exit;                           { Empty string exit }
+   If (HistoryBlock = Nil) Then Exit;                 { History uninitialized }
+   StartId(Id);                                       { Set current data }
+   AdvanceStringPtr;                                  { Find the string }
+   While (CurString <> nil) Do Begin
+     If (Str = CurString^) Then DeleteString;         { Delete duplicates }
+     AdvanceStringPtr;                                { Find next string }
+   End;
+   InsertString(Id, Str);                             { Add new history item }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{              HISTORY STREAM STORAGE AND RETREIVAL ROUTINES                }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  LoadHistory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE LoadHistory (Var S: TStream);
+VAR Size: Word;
+BEGIN
+   S.Read(Size, 2);                                   { Read history size }
+   If (HistoryBlock <> Nil) Then Begin                { History initialized }
+     If (Size <= HistorySize) Then Begin
+       S.Read(HistoryBlock^, Size);                   { Read the history }
+       HistoryUsed := LongInt(HistoryBlock) + Size;   { History used }
+     End Else S.Seek(S.GetPos + Size);                { Move stream position }
+   End Else S.Seek(S.GetPos + Size);                  { Move stream position }
+END;
+
+{---------------------------------------------------------------------------}
+{  StoreHistory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE StoreHistory (Var S: TStream);
+VAR Size: Word;
+BEGIN
+   If (HistoryBlock = Nil) Then Size := 0 Else        { No history data }
+     Size := HistoryUsed - LongInt(HistoryBlock);     { Size of history data }
+   S.Write(Size, 2);                                  { Write history size }
+   If (Size > 0) Then S.Write(HistoryBlock^, Size);   { Write history data }
+END;
+
+END.

+ 826 - 0
fv/memory.pas

@@ -0,0 +1,826 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{          System independent clone of MEMORY.PAS          }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail address        }
+{   [email protected] - backup e-mail address         }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     19 feb 96   Initial DOS/DPMI code released.    }
+{  1.10     18 Jul 97   Windows conversion added.          }
+{  1.20     29 Aug 97   Platform.inc sort added.           }
+{  1.30     05 May 98   Virtual pascal 2.0 code added.     }
+{  1.40     01 Oct 99   Complete multiplatform rewrite     }
+{  1.41     03 Nov 99   FPC Windows support added          }
+{**********************************************************}
+
+UNIT Memory;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F+} { Force far calls }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES Common;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           MEMORY ACCESS ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-MemAlloc-----------------------------------------------------------
+Allocates the requested size of memory if this takes memory free below
+the safety pool then a nil pointer is returned.
+01Oct99 LdB
+---------------------------------------------------------------------}
+FUNCTION MemAlloc (Size: Word): Pointer;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                 MEMORY MANAGER SYSTEM CONTROL ROUTINES                    }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-LowMemory----------------------------------------------------------
+Returns if the free memory left is below the safety pool value.
+01Oct99 LdB
+---------------------------------------------------------------------}
+FUNCTION LowMemory: Boolean;
+
+{-InitMemory---------------------------------------------------------
+Initializes the memory and safety pool manager. This should be called
+prior to using any of the memory manager routines.
+01Oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE InitMemory;
+
+{-DoneMemory---------------------------------------------------------
+Closes the memory and safety pool manager. This should be called after
+using the memory manager routines so as to clean up.
+01Oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE DoneMemory;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           CACHE MEMORY ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-NewCache-----------------------------------------------------------
+Create a new cache of given size in pointer P failure will return nil.
+01Oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE NewCache (Var P: Pointer; Size: Word);
+
+{-DisposeCache-------------------------------------------------------
+Dispose of a cache buffer given by pointer P.
+01Oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE DisposeCache (P: Pointer);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          BUFFER MEMORY ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-GetBufferSize------------------------------------------------------
+Returns the size of memory buffer given by pointer P.
+01Oct99 LdB
+---------------------------------------------------------------------}
+FUNCTION GetBufferSize (P: Pointer): Word;
+
+{-SetBufferSize------------------------------------------------------
+Change the size of buffer given by pointer P to the size requested.
+01Oct99 LdB
+---------------------------------------------------------------------}
+FUNCTION SetBufferSize (P: Pointer; Size: Word): Boolean;
+
+{-DisposeBuffer------------------------------------------------------
+Dispose of buffer given by pointer P.
+01Oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE DisposeBuffer (P: Pointer);
+
+{-NewBuffer----------------------------------------------------------
+Create a new buffer of given size in ptr P failure will return nil.
+01Oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE NewBuffer (Var P: Pointer; Size: Word);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        DOS MEMORY CONTROL ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-InitDosMem---------------------------------------------------------
+Initialize memory manager routine for a shell to launch a DOS window.
+Interface for compatability only under DPMI/WIN/NT/OS2 platforms.
+01Oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE InitDosMem;
+
+{-DoneDosMem---------------------------------------------------------
+Finished shell to a DOS window so reset memory manager again.
+Interface for compatability only under DPMI/WIN/NT/OS2 platforms.
+01Oct99 LdB
+---------------------------------------------------------------------}
+PROCEDURE DoneDosMem;
+
+{***************************************************************************}
+{                         PUBLIC INITIALIZED VARIABLES                      }
+{***************************************************************************}
+CONST
+   LowMemSize    : Word = 4096 DIV 16;                {   4K }
+   SafetyPoolSize: Word = 8192;                       { Safety pool size }
+{$IFDEF PROC_REAL}                                    { REAL MODE DOS CODE }
+   MaxHeapSize   : Word = 655360 DIV 16;              { 640K }
+   MaxBufMem     : Word = 65536 DIV 16;               {  64K }
+{$ENDIF}
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+   {$IFDEF PPC_FPC}                                   { FPC WINDOWS COMPILER }
+   USES Windows;                                      { Standard unit }
+   {$ELSE}                                            { OTHER COMPILERS }
+   USES WinProcs, WinTypes;                           { Standard units }
+   {$ENDIF}
+{$ENDIF}
+
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+USES Os2Base;                                         { Standard unit }
+{$ENDIF}
+
+{***************************************************************************}
+{                      PRIVATE RECORD TYPE DEFINITIONS                      }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                         TBuffer RECORD DEFINITION                         }
+{---------------------------------------------------------------------------}
+TYPE
+   PBuffer = ^TBuffer;                                { Buffer pointer }
+   TBuffer = PACKED RECORD
+     {$IFDEF PROC_REAL}                               { REAL MODE DOS CODE }
+     Size  : Word;                                    { Buffer size }
+     Master: ^Word;                                   { Master buffer }
+     {$ELSE}                                          { DPMI/WIN/NT/OS2 CODE }
+     Next: PBuffer;                                   { Next buffer }
+     Size: Word;                                      { Buffer size }
+     Data: RECORD END;                                { Buffer data }
+     {$ENDIF}
+   END;
+
+{---------------------------------------------------------------------------}
+{                     POINTER TYPE CONVERSION RECORDS                       }
+{---------------------------------------------------------------------------}
+TYPE
+   PtrRec = PACKED RECORD
+     Ofs, Seg: Word;                                  { Pointer to words }
+   END;
+
+{---------------------------------------------------------------------------}
+{                          TCache RECORD DEFINITION                         }
+{---------------------------------------------------------------------------}
+TYPE
+   PCache = ^TCache;                                  { Cache pointer }
+{$IFDEF PROC_REAL}                                    { REAL MODE DOS CODE }
+   TCache = PACKED RECORD
+      Size  : Word;                                   { Cache size }
+      Master: ^Pointer;                               { Master cache }
+      Data  : RECORD END;                             { Cache data }
+   END;
+{$ELSE}                                               { DPMI/WIN/NT/OS2 CODE }
+   TCache = PACKED RECORD
+     Next  : PCache;                                  { Next cache }
+     Master: ^Pointer;                                { Master cache }
+     Size  : Word;                                    { Size of cache }
+     Data  : RECORD END;                              { Cache data }
+   End;
+{$ENDIF}
+
+{***************************************************************************}
+{                       INITIALIZED PRIVATE VARIABLES                       }
+{***************************************************************************}
+CONST
+   DisablePool: Boolean = False;                      { Disable safety pool }
+   SafetyPool : Pointer = Nil;                        { Safety pool memory }
+{$IFDEF PROC_REAL}                                    { REAL MODE DOS CODE }
+   HeapResult: Integer = 0;                           { Heap result }
+   BufHeapPtr: Word = 0;                              { Heap position }
+   BufHeapEnd: Word = 0;                              { Heap end }
+   CachePtr  : Pointer = Nil;                         { Cache list }
+{$ELSE}                                               { DPMI/WIN/NT/OS2 CODE }
+   CacheList : PCache = Nil;                          { Cache list }
+   BufferList: PBuffer = Nil;                         { Buffer list }
+{$ENDIF}
+
+{***************************************************************************}
+{                          PRIVATE UNIT ROUTINES                            }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{             PRIVATE UNIT ROUTINES - REAL MODE DOS PLATFORMS               }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{$IFDEF PROC_REAL}                                    { REAL MODE DOS CODE }
+{---------------------------------------------------------------------------}
+{  GetBufSize -> Platforms DOS REAL MODE - Updated 01Oct99 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION GetBufSize (P: PBuffer): Word; FAR;
+BEGIN
+   GetBufSize := (P^.Size + 15) SHR 4 + 1;            { Buffer paragraphs }
+END;
+
+{---------------------------------------------------------------------------}
+{  FreeCacheMem -> Platforms DOS REAL MODE - Updated 01Oct99 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE FreeCacheMem; FAR;
+BEGIN
+   While (CachePtr <> HeapEnd) Do
+     DisposeCache(CachePtr);                          { Release blocks }
+END;
+
+{---------------------------------------------------------------------------}
+{  SetMemTop -> Platforms DOS REAL MODE - Updated 01Oct99 LdB               }
+{---------------------------------------------------------------------------}
+PROCEDURE SetMemTop (MemTop: Pointer); ASSEMBLER;
+ASM
+   MOV BX, MemTop.Word[0];                            { Top of memory }
+   ADD BX, 15;
+   MOV CL, 4;
+   SHR BX, CL;                                        { Size in paragraphs }
+   ADD BX, MemTop.Word[2];
+   MOV AX, PrefixSeg;                                 { Add prefix seg }
+   SUB BX, AX;
+   MOV ES, AX;
+   MOV AH, 4AH;
+   INT 21H;                                           { Call to DOS }
+END;
+
+{---------------------------------------------------------------------------}
+{  MoveSeg -> Platforms DOS REAL MODE - Updated 01Oct99 LdB                 }
+{---------------------------------------------------------------------------}
+PROCEDURE MoveSeg (Source, Dest, Size: Word); NEAR; ASSEMBLER;
+ASM
+   PUSH DS;                                           { Save register }
+   MOV AX, Source;
+   MOV DX, Dest;                                      { Destination }
+   MOV BX, Size;
+   CMP AX, DX;                                        { Does Source=Dest? }
+   JB @@3;
+   CLD;                                               { Go forward }
+@@1:
+   MOV CX, 0FFFH;
+   CMP CX, BX;
+   JB @@2;
+   MOV CX, BX;
+@@2:
+   MOV DS, AX;
+   MOV ES, DX;
+   ADD AX, CX;
+   ADD DX, CX;
+   SUB BX, CX;
+   SHL CX, 3;                                         { Mult x8 }
+   XOR SI, SI;
+   XOR DI, DI;
+   REP MOVSW;
+   OR BX, BX;
+   JNE @@1;
+   JMP @@6;
+@@3:                                                  { Source=Dest }
+   ADD AX, BX;                                        { Hold register }
+   ADD DX, BX;                                        { Must go backwards }
+   STD;
+@@4:
+   MOV CX, 0FFFH;
+   CMP CX, BX;
+   JB @@5;
+   MOV CX, BX;
+@@5:
+   SUB AX, CX;
+   SUB DX, CX;
+   SUB BX, CX;
+   MOV DS, AX;
+   MOV ES, DX;
+   SHL CX, 3;                                         { Mult x8 }
+   MOV SI, CX;
+   DEC SI;
+   SHL SI, 1;
+   MOV DI, SI;
+   REP MOVSW;                                         { Move data }
+   OR BX, BX;
+   JNE @@4;
+@@6:
+   POP DS;                                            { Recover register }
+END;
+
+{---------------------------------------------------------------------------}
+{  SetBufSize -> Platforms DOS REAL MODE - Updated 01Oct99 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE SetBufSize (P: PBuffer; NewSize: Word); FAR;
+VAR CurSize: Word;
+BEGIN
+   CurSize := GetBufSize(P);                          { Current size }
+   MoveSeg(PtrRec(P).Seg + CurSize, PtrRec(P).Seg+
+     NewSize, BufHeapPtr - PtrRec(P).Seg - CurSize);  { Move data }
+   Inc(BufHeapPtr, NewSize - CurSize);                { Adjust heap space }
+   Inc(PtrRec(P).Seg, NewSize);                       { Adjust pointer }
+   While PtrRec(P).Seg < BufHeapPtr Do Begin
+     Inc(P^.Master^, NewSize - CurSize);              { Adjust master }
+     Inc(PtrRec(P).Seg, (P^.Size + 15) SHR 4 + 1);    { Adjust paragraphs }
+   End;
+END;
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{            PRIVATE UNIT ROUTINES - DPMI/WIN/NT/OS2 PLATFORMS              }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{$IFNDEF PROC_REAL}                                   { DPMI/WIN/NT/OS2 CODE }
+{---------------------------------------------------------------------------}
+{  FreeCache -> Platforms DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION FreeCache: Boolean; FAR;
+BEGIN
+   FreeCache := False;                                { Preset fail }
+   If (CacheList <> Nil) Then Begin
+     DisposeCache(CacheList^.Next^.Master^);          { Dispose cache }
+     FreeCache := True;                               { Return success }
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  FreeCache -> Platforms DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION FreeSafetyPool: Boolean; FAR;
+BEGIN
+   FreeSafetyPool := False;                           { Preset fail }
+   If (SafetyPool <> Nil) Then Begin                  { Pool exists }
+     FreeMem(SafetyPool, SafetyPoolSize);             { Release memory }
+     SafetyPool := Nil;                               { Clear pointer }
+     FreeSafetyPool := True;                          { Return true }
+   End;
+END;
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                 PRIVATE UNIT ROUTINES - ALL PLATFORMS                     }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  HeapNotify -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION HeapNotify (Size: Word): Integer; FAR;
+{$IFDEF PROC_REAL}                                    { REAL MODE DOS CODE }
+ASSEMBLER;
+ASM
+   CMP Size, 0;                                       { Check for zero size }
+   JNE @@3;                                           { Exit if size = zero }
+@@1:
+   MOV AX, CachePtr.Word[2];
+   CMP AX, HeapPtr.Word[2];                           { Compare segments }
+   JA @@3;
+   JB @@2;
+   MOV AX, CachePtr.Word[0];
+   CMP AX, HeapPtr.Word[0];                           { Compare offsets }
+   JAE @@3;
+@@2:
+   XOR AX, AX;                                        { Clear register }
+   PUSH AX;                                           { Push zero }
+   PUSH AX;                                           { Push zero }
+   CALL DisposeCache;                                 { Dispose cache }
+   JMP @@1;
+@@3:
+   MOV AX, HeapResult;                                { Return result }
+END;
+{$ELSE}                                               { DPMI/WIN/NT/OS2 }
+BEGIN
+   If FreeCache Then HeapNotify := 2 Else             { Release cache }
+     If DisablePool Then HeapNotify := 1 Else         { Safetypool disabled }
+       If FreeSafetyPool Then HeapNotify := 2 Else    { Free safety pool }
+         HeapNotify := 0;                             { Return success }
+END;
+{$ENDIF}
+
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           MEMORY ACCESS ROUTINES                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  MemAlloc -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION MemAlloc (Size: Word): Pointer;
+VAR P: Pointer;
+BEGIN
+   {$IFDEF PROC_REAL}                                 { REAL MODE DOS CODE }
+   HeapResult := 1;                                   { Stop error calls }
+   GetMem(P, Size);                                   { Get memory }
+   HeapResult := 0;                                   { Reset error calls }
+   If (P <> Nil) AND LowMemory Then Begin             { Low memory }
+     FreeMem(P, Size);                                { Release memory }
+     P := Nil;                                        { Clear pointer }
+   End;
+   MemAlloc := P;                                     { Return result }
+   {$ELSE}                                            { DPMI/WIN/NT/OS2 }
+   DisablePool := True;                               { Disable safety }
+   GetMem(P, Size);                                   { Allocate memory }
+   DisablePool := False;                              { Enable safety }
+   MemAlloc := P;                                     { Return result }
+   {$ENDIF}
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                 MEMORY MANAGER SYSTEM CONTROL ROUTINES                    }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  LowMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Checked 29Jun98 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION LowMemory: Boolean;
+{$IFDEF PROC_REAL}                                    { REAL MODE DOS CODE }
+ASSEMBLER;
+ASM
+   MOV AX, HeapEnd.Word[2];                           { Get heap end }
+   SUB AX, HeapPtr.Word[2];
+   SUB AX, LowMemSize;                                { Subtract size }
+   SBB AX, AX;
+   NEG AX;                                            { Return result }
+END;
+{$ELSE}                                               { DPMI/WIN/NT/OS2 CODE }
+BEGIN
+   LowMemory := False;                                { Preset false }
+   If (SafetyPool = Nil) Then Begin                   { Not initialized }
+    SafetyPool := MemAlloc(SafetyPoolSize);           { Allocate safety pool }
+    If (SafetyPool = Nil) Then LowMemory := True;     { Return if low memory }
+   End;
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  InitMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE InitMemory;
+{$IFDEF PROC_REAL} VAR HeapSize: Word; {$ENDIF}
+BEGIN
+   {$IFDEF PROC_REAL}                                 { REAL MODE DOS CODE }
+   HeapError := @HeapNotify;                          { Point to error proc }
+   If (BufHeapPtr = 0) Then Begin
+     HeapSize := PtrRec(HeapEnd).Seg
+       - PtrRec(HeapOrg).Seg;                         { Calculate size }
+     If (HeapSize > MaxHeapSize) Then
+       HeapSize := MaxHeapSize;                       { Restrict max size }
+     BufHeapEnd := PtrRec(HeapEnd).Seg;               { Set heap end }
+     PtrRec(HeapEnd).Seg := PtrRec(HeapOrg).Seg
+      + HeapSize;                                     { Add heapsize }
+     BufHeapPtr := PtrRec(HeapEnd).Seg;               { Set heap pointer }
+   End;
+   CachePtr := HeapEnd;                               { Cache starts at end }
+   {$ELSE}                                            { DPMI/WIN/NT/OS2 CODE }
+   {$IFNDEF PPC_DELPHI3}
+   HeapError := @HeapNotify;                          { Set heap error proc }
+   {$ENDIF}
+   SafetyPoolSize := LowMemSize * 16;                 { Fix safety pool size }
+   LowMemory;                                         { Check for low memory }
+   {$ENDIF}
+END;
+
+{---------------------------------------------------------------------------}
+{  DoneMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE DoneMemory;
+BEGIN
+   {$IFDEF PROC_REAL}                                 { REAl MODE DOS CODE }
+   FreeCacheMem;                                      { Release cache memory }
+   {$ELSE}                                            { DPMI/WIN/NT/OS2 }
+   While FreeCache Do;                                { Free cache memory }
+   FreeSafetyPool;                                    { Release safety pool }
+   {$ENDIF}
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           CACHE MEMORY ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  NewCache -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE NewCache (Var P: Pointer; Size: Word);
+{$IFDEF PROC_REAL}                                    { REAL MODE DOS CODE }
+ASSEMBLER;
+ASM
+   LES DI, P;                                         { Addres of var P }
+   MOV AX, Size;
+   ADD AX, (TYPE TCache)+15;                          { Add offset }
+   MOV CL, 4;
+   SHR AX, CL;
+   MOV DX, CachePtr.Word[2];                          { Reteive cache ptr }
+   SUB DX, AX;
+   JC @@1;
+   CMP DX, HeapPtr.Word[2];                           { Heap ptr end }
+   JBE @@1;
+   MOV CX, HeapEnd.Word[2];
+   SUB CX, DX;
+   CMP CX, MaxBufMem;                                 { Compare to maximum }
+   JA @@1;
+   MOV CachePtr.Word[2], DX;                          { Exchange ptr }
+   PUSH DS;
+   MOV DS, DX;
+   XOR SI, SI;
+   MOV DS:[SI].TCache.Size, AX;                       { Get cache size }
+   MOV DS:[SI].TCache.Master.Word[0], DI;
+   MOV DS:[SI].TCache.Master.Word[2], ES;             { Get master ptr }
+   POP DS;
+   MOV AX, OFFSET TCache.Data;
+   JMP @@2;
+@@1:
+   XOR AX, AX;
+   CWD;                                               { Make double word }
+@@2:
+   CLD;
+   STOSW;                                             { Write low word }
+   XCHG AX, DX;
+   STOSW;                                             { Write high word }
+END;
+{$ELSE}                                               { DPMI/WIN/NT/OS2 CODE }
+VAR Cache: PCache;
+BEGIN
+   Inc(Size, SizeOf(TCache));                         { Add cache size }
+   If (MaxAvail >= Size) Then GetMem(Cache, Size)     { Allocate memory }
+     Else Cache := Nil;                               { Not enough memory }
+   If (Cache <> Nil) Then Begin                       { Cache is valid }
+     If (CacheList = Nil) Then Cache^.Next := Cache
+     Else Begin
+       Cache^.Next := CacheList^.Next;                { Insert in list }
+       CacheList^.Next := Cache;                      { Complete link }
+     End;
+     CacheList := Cache;                              { Hold cache ptr }
+     Cache^.Size := Size;                             { Hold cache size }
+     Cache^.Master := @P;                             { Hold master ptr }
+     Inc(PtrRec(Cache).Ofs, SizeOf(TCache));          { Set cache offset }
+   End;
+   P := Cache;                                        { Return pointer }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  DisposeCache -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE DisposeCache (P: Pointer);
+{$IFDEF PROC_REAL}                                    { REAL MODE DOS CODE }
+ASSEMBLER;
+ASM
+   MOV AX, CachePtr.Word[2];                          { Cache high word }
+   XOR BX, BX;
+   XOR CX, CX;
+   MOV DX, P.Word[2];                                 { P high word }
+@@1:
+   MOV ES, AX;
+   CMP AX, DX;                                        { Check for match }
+   JE @@2;
+   ADD AX, ES:[BX].TCache.Size;                       { Move to next cache }
+   CMP AX, HeapEnd.Word[2];
+   JE @@2;                                            { Are we at heap end }
+   PUSH ES;
+   INC CX;                                            { No so try next }
+   JMP @@1;
+@@2:
+   PUSH ES;
+   LES DI, ES:[BX].TCache.Master;                     { Pointe to master }
+   XOR AX, AX;
+   CLD;
+   STOSW;                                             { Clear master ptr }
+   STOSW;
+   POP ES;
+   MOV AX, ES:[BX].TCache.Size;                       { Next cache }
+   JCXZ @@4;
+@@3:
+   POP DX;
+   PUSH DS;
+   PUSH CX;                                           { Hold registers }
+   MOV DS, DX;
+   ADD DX, AX;
+   MOV ES, DX;
+   MOV SI, DS:[BX].TCache.Size;                       { Get cache size }
+   MOV CL, 3;
+   SHL SI, CL;                                        { Multiply x8 }
+   MOV CX, SI;
+   SHL SI, 1;
+   DEC SI;                                            { Adjust position }
+   DEC SI;
+   MOV DI, SI;
+   STD;
+   REP MOVSW;                                         { Move cache memory }
+   LDS SI, ES:[BX].TCache.Master;
+   MOV DS:[SI].Word[2], ES;                           { Store new master }
+   POP CX;
+   POP DS;                                            { Recover registers }
+   LOOP @@3;
+@@4:
+   ADD CachePtr.Word[2], AX;                          { Add offset }
+END;
+{$ELSE}                                               { DPMI/WIN/NT/OS2 CODE }
+VAR Cache, C: PCache;
+BEGIN
+   PtrRec(Cache).Ofs := PtrRec(P).Ofs-SizeOf(TCache); { Previous cache }
+   PtrRec(Cache).Seg := PtrRec(P).Seg;                { Segment }
+   C := CacheList;                                    { Start at 1st cache }
+   While (C^.Next <> Cache) AND (C^.Next <> CacheList)
+     Do C := C^.Next;                                 { Find previous }
+   If (C^.Next = Cache) Then Begin                    { Cache found }
+     If (C = Cache) Then CacheList := Nil Else Begin  { Only cache in list }
+       If CacheList = Cache Then CacheList := C;      { First in list }
+       C^.Next := Cache^.Next;                        { Remove from list }
+     End;
+     Cache^.Master^ := Nil;                           { Clear master }
+     FreeMem(Cache, Cache^.Size);                     { Release memory }
+   End;
+END;
+{$ENDIF}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          BUFFER MEMORY ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  GetBufferSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB     }
+{---------------------------------------------------------------------------}
+FUNCTION GetBufferSize (P: Pointer): Word;
+BEGIN
+   {$IFDEF PROC_REAL}                                 { DOS CODE }
+   Dec(PtrRec(P).Seg);                                { Segment prior }
+   GetBufferSize := PBuffer(P)^.Size;                 { Size of this buffer }
+   {$ELSE}                                            { DPMI/WIN/NT/OS2 CODE }
+   If (P <> Nil) Then Begin                           { Check pointer }
+     Dec(PtrRec(P).Ofs,SizeOf(TBuffer));              { Correct to buffer }
+     GetBufferSize := PBuffer(P)^.Size;               { Return buffer size }
+   End Else GetBufferSize := 0;                       { Invalid pointer }
+   {$ENDIF}
+END;
+
+{---------------------------------------------------------------------------}
+{  SetBufferSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB     }
+{---------------------------------------------------------------------------}
+FUNCTION SetBufferSize (P: Pointer; Size: Word): Boolean;
+VAR NewSize: Word;
+BEGIN
+   SetBufferSize := False;                            { Preset failure }
+   {$IFDEF PROC_REAL}                                 { REAL MODE DOS CODE }
+   Dec(PtrRec(P).Seg);                                { Prior segment }
+   NewSize := (Size + 15) SHR 4 + 1;                  { Paragraph size }
+   If (BufHeapPtr+NewSize-GetBufSize(P)<=BufHeapEnd)  { Check enough heap }
+   Then Begin
+     SetBufSize(P, NewSize);                          { Set the buffer size }
+     PBuffer(P)^.Size := Size;                        { Set the size }
+     SetBufferSize := True;                           { Return success }
+   End;
+   {$ELSE}                                            { DPMI/WIN/NT/OS2 CODE }
+   SetBufferSize := False;                            { No block resizing }
+   {$ENDIF}
+END;
+
+{---------------------------------------------------------------------------}
+{  DisposeBuffer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE DisposeBuffer (P: Pointer);
+{$IFNDEF PROC_REAL} VAR Buffer,PrevBuf: PBuffer; {$ENDIF}
+BEGIN
+   If (P <> Nil) Then Begin
+     {$IFDEF PROC_REAL}                               { REAL MODE DOS CODE }
+     Dec(PtrRec(P).Seg);                              { Prior segement }
+     SetBufSize(P, 0);                                { Release memory }
+     {$ELSE}                                          { DPMI/WIN/NT/OS2 CODE }
+     Dec(PtrRec(P).Ofs, SizeOf(TBuffer));             { Actual buffer pointer }
+     Buffer := BufferList;                            { Start on first }
+     PrevBuf := Nil;                                  { Preset prevbuf to nil }
+     While (Buffer <> Nil) AND (P <> Buffer) Do Begin { Search for buffer }
+       PrevBuf := Buffer;                             { Hold last buffer }
+       Buffer := Buffer^.Next;                        { Move to next buffer }
+     End;
+     If (Buffer <> Nil) Then Begin                    { Buffer was found }
+       If (PrevBuf = Nil) Then                        { We were first on list }
+         BufferList := Buffer^.Next Else              { Set bufferlist entry }
+         PrevBuf^.Next := Buffer^.Next;               { Remove us from chain }
+       FreeMem(Buffer, Buffer^.Size);                 { Release buffer }
+     End;
+     {$ENDIF}
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  NewBuffer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE NewBuffer (Var P: Pointer; Size: Word);
+VAR BufSize: Word; Buffer: PBuffer;
+BEGIN
+   {$IFDEF PROC_REAL}                                 { REAL MODE DOS CODE }
+   BufSize := (Size + 15) SHR 4 + 1;                  { Paragraphs to alloc }
+   If (BufHeapPtr+BufSize > BufHeapEnd) Then P := Nil { Exceeeds heap }
+   Else Begin
+     Buffer := Ptr(BufHeapPtr, 0);                    { Current position }
+     Buffer^.Size := Size;                            { Set size }
+     Buffer^.Master := @PtrRec(P).Seg;                { Set master }
+     P := Ptr(BufHeapPtr + 1, 0);                     { Position ptr }
+     Inc(BufHeapPtr, BufSize);                        { Allow space on heap }
+   End;
+   {$ELSE}                                            { DPMI/WIN/NT/OS2 CODE }
+   BufSize := Size + SizeOf(TBuffer);                 { Size to allocate }
+   Buffer := MemAlloc(BufSize);                       { Allocate the memory }
+   If (Buffer <> Nil) Then Begin
+     Buffer^.Next := BufferList;                      { First part of chain }
+     BufferList := Buffer;                            { Complete the chain }
+     Buffer^.Size := BufSize;                         { Hold the buffer size }
+     Inc(PtrRec(Buffer).Ofs, SizeOf(TBuffer));        { Buffer to data area }
+   End;
+   P := Buffer;                                       { Return the buffer ptr }
+   {$ENDIF}
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        DOS MEMORY CONTROL ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  InitDosMem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE InitDosMem;
+BEGIN
+   {$IFDEF PROC_REAL}                                 { REAl MODE DOS CODE }
+   SetMemTop(Ptr(BufHeapEnd, 0));                     { Move heap to empty }
+   {$ENDIF}
+END;
+
+{---------------------------------------------------------------------------}
+{  DoneDosMem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE DoneDosMem;
+{$IFDEF PROC_REAL} VAR MemTop: Pointer; {$ENDIF}
+BEGIN
+   {$IFDEF PROC_REAL}                                 { REAL MODE DOS CODE }
+   MemTop := Ptr(BufHeapPtr, 0);                      { Top of memory }
+   If (BufHeapPtr = PtrRec(HeapEnd).Seg) Then Begin   { Is memory empty }
+     FreeCacheMem;                                    { Release memory }
+     MemTop := HeapPtr;                               { Set pointer }
+   End;
+   SetMemTop(MemTop);                                 { Release memory }
+   {$ENDIF}
+END;
+
+END.

+ 1667 - 0
fv/menus.pas

@@ -0,0 +1,1667 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{   System independent GRAPHICAL clone of MENUS.PAS        }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail addr           }
+{   [email protected] - backup e-mail addr            }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                 - Speed pascal 1.0+       (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     12 Jun 96   Initial DOS/DPMI code released.    }
+{  1.10     18 Oct 97   Code converted to GUI & TEXT mode. }
+{  1.20     18 Jul 97   Windows conversion added.          }
+{  1.30     29 Aug 97   Platform.inc sort added.           }
+{  1.40     22 Oct 97   Delphi3 32 bit code added.         }
+{  1.50     05 May 98   Virtual pascal 2.0 code added.     }
+{  1.60     11 May 98   Clean up and ensure error checks.  }
+{  1.70     15 May 98   Documentation & format completed.  }
+{  1.80     30 Sep 99   Complete recheck preformed         }
+{  1.81     03 Nov 99   FPC windows support added          }
+{  1.90     26 Nov 99   Graphics stuff moved to GFVGraph   }
+{**********************************************************}
+
+UNIT Menus;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F-} { Near calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     {$IFNDEF PPC_SPEED}                              { NON SPEED COMPILER }
+       {$IFDEF PPC_FPC}                               { FPC WINDOWS COMPILER }
+       Windows,                                       { Standard unit }
+       {$ELSE}                                        { OTHER COMPILERS }
+       WinTypes,WinProcs,                             { Standard units }
+       {$ENDIF}
+     {$ELSE}                                          { SPEEDSOFT COMPILER }
+       WinBase, WinDef,                               { Standard units }
+     {$ENDIF}
+   {$ENDIF}
+   GFVGraph, Objects, Drivers, Views;                 { GFV standard units }
+
+{***************************************************************************}
+{                              PUBLIC CONSTANTS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                               COLOUR PALETTES                             }
+{---------------------------------------------------------------------------}
+CONST
+   CMenuView   = #2#3#4#5#6#7;                        { Menu colours }
+   CStatusLine = #2#3#4#5#6#7;                        { Statusline colours }
+
+{***************************************************************************}
+{                            RECORD DEFINITIONS                             }
+{***************************************************************************}
+TYPE
+   TMenuStr = String[31];                             { Menu string }
+
+   PMenu = ^TMenu;                                    { Pointer to menu }
+
+{---------------------------------------------------------------------------}
+{                              TMenuItem RECORD                             }
+{---------------------------------------------------------------------------}
+   PMenuItem = ^TMenuItem;
+   TMenuItem = PACKED RECORD
+     Next: PMenuItem;                                 { Next menu item }
+     Name: PString;                                   { Menu item name }
+     Command: Word;                                   { Menu item command }
+     Disabled: Boolean;                               { Menu item state }
+     KeyCode: Word;                                   { Menu item keycode }
+     HelpCtx: Word;                                   { Menu item help ctx }
+     Case Integer Of
+       0: (Param: PString);
+       1: (SubMenu: PMenu);
+   END;
+
+{---------------------------------------------------------------------------}
+{                                TMenu RECORD                               }
+{---------------------------------------------------------------------------}
+   TMenu = PACKED RECORD
+     Items: PMenuItem;                                { Menu item list }
+     Default: PMenuItem;                              { Default menu }
+   END;
+
+{---------------------------------------------------------------------------}
+{                             TStatusItem RECORD                            }
+{---------------------------------------------------------------------------}
+TYPE
+   PStatusItem = ^TStatusItem;
+   TStatusItem = PACKED RECORD
+     Next: PStatusItem;                               { Next status item }
+     Text: PString;                                   { Text of status item }
+     KeyCode: Word;                                   { Keycode of item }
+     Command: Word;                                   { Command of item }
+   END;
+
+{---------------------------------------------------------------------------}
+{                             TStatusDef RECORD                             }
+{---------------------------------------------------------------------------}
+TYPE
+   PStatusDef = ^TStatusDef;
+   TStatusDef = PACKED RECORD
+     Next: PStatusDef;                                { Next status defined }
+     Min, Max: Word;                                  { Range of item }
+     Items: PStatusItem;                              { Item list }
+   END;
+
+{***************************************************************************}
+{                            OBJECT DEFINITIONS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                TMenuView OBJECT - MENU VIEW ANCESTOR OBJECT               }
+{---------------------------------------------------------------------------}
+TYPE
+   PMenuView = ^TMenuView;
+   TMenuView = OBJECT (TView)
+         ParentMenu: PMenuView;                       { Parent menu }
+         Menu      : PMenu;                           { Menu item list }
+         Current   : PMenuItem;                       { Current menu item }
+         OldItem   : PMenuItem;                       { Old item for draws }
+      CONSTRUCTOR Init (Var Bounds: TRect);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION Execute: Word; Virtual;
+      FUNCTION GetHelpCtx: Word; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION FindItem (Ch: Char): PMenuItem;
+      FUNCTION HotKey (KeyCode: Word): PMenuItem;
+      FUNCTION NewSubView (Var Bounds: TRect; AMenu: PMenu;
+        AParentMenu: PMenuView): PMenuView; Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PROCEDURE GetItemRect (Item: PMenuItem; Var R: TRect); Virtual;
+   END;
+
+{---------------------------------------------------------------------------}
+{                    TMenuBar OBJECT - MENU BAR OBJECT                      }
+{---------------------------------------------------------------------------}
+TYPE
+   TMenuBar = OBJECT (TMenuView)
+      CONSTRUCTOR Init (Var Bounds: TRect; AMenu: PMenu);
+      DESTRUCTOR Done; Virtual;
+      PROCEDURE Draw; Virtual;
+      PROCEDURE DrawBackGround; Virtual;
+      PROCEDURE GetItemRect (Item: PMenuItem; Var R: TRect); Virtual;
+   END;
+   PMenuBar = ^TMenuBar;
+
+{---------------------------------------------------------------------------}
+{                   TMenuBox OBJECT - BOXED MENU OBJECT                     }
+{---------------------------------------------------------------------------}
+TYPE
+   TMenuBox = OBJECT (TMenuView)
+      CONSTRUCTOR Init (Var Bounds: TRect; AMenu: PMenu;
+        AParentMenu: PMenuView);
+      PROCEDURE Draw; Virtual;
+      PROCEDURE DrawBackGround; Virtual;
+      PROCEDURE GetItemRect (Item: PMenuItem; Var R: TRect); Virtual;
+   END;
+   PMenuBox = ^TMenuBox;
+
+{---------------------------------------------------------------------------}
+{                  TMenuPopUp OBJECT - POPUP MENU OBJECT                    }
+{---------------------------------------------------------------------------}
+TYPE
+   TMenuPopup = OBJECT (TMenuBox)
+      CONSTRUCTOR Init (Var Bounds: TRect; AMenu: PMenu);
+      DESTRUCTOR Done; Virtual;
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+   END;
+   PMenuPopup = ^TMenuPopup;
+
+{---------------------------------------------------------------------------}
+{                    TStatusLine OBJECT - STATUS LINE OBJECT                }
+{---------------------------------------------------------------------------}
+TYPE
+   TStatusLine = OBJECT (TView)
+         Items: PStatusItem;                          { Status line items }
+         Defs : PStatusDef;                           { Status line default }
+      CONSTRUCTOR Init (Var Bounds: TRect; ADefs: PStatusDef);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION Hint (AHelpCtx: Word): String; Virtual;
+      PROCEDURE Draw; Virtual;
+      PROCEDURE Update; Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PRIVATE
+      PROCEDURE FindItems;
+      PROCEDURE DrawSelect (Selected: PStatusItem);
+   END;
+   PStatusLine = ^TStatusLine;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           MENU INTERFACE ROUTINES                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-NewMenu------------------------------------------------------------
+Allocates and returns a pointer to a new TMenu record. Sets the Items
+and Default fields of the record to the value given by the parameter.
+An error creating will return a nil pointer.
+14May98 LdB
+---------------------------------------------------------------------}
+FUNCTION NewMenu (Items: PMenuItem): PMenu;
+
+{-DisposeMenu--------------------------------------------------------
+Disposes of all the elements of the specified menu (and all submenus).
+14May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE DisposeMenu (Menu: PMenu);
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                             MENU ITEM ROUTINES                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-NewLine------------------------------------------------------------
+Allocates and returns a pointer to a new TMenuItem record that
+represents a separator line in a menu box.
+An error creating will return a nil pointer.
+14May98 LdB
+---------------------------------------------------------------------}
+FUNCTION NewLine (Next: PMenuItem): PMenuItem;
+
+{-NewItem------------------------------------------------------------
+Allocates and returns a pointer to a new TMenuItem record that
+represents a menu item (using NewStr to allocate the Name and Param).
+An error creating will return a nil pointer.
+14May98 LdB
+---------------------------------------------------------------------}
+FUNCTION NewItem (Name, Param: TMenuStr; KeyCode: Word; Command: Word;
+  AHelpCtx: Word; Next: PMenuItem): PMenuItem;
+
+{-NewSubMenu---------------------------------------------------------
+Allocates and returns a pointer to a new TMenuItem record, which
+represents a submenu (using NewStr to allocate the Name).
+An error creating will return a nil pointer.
+14May98 LdB
+---------------------------------------------------------------------}
+FUNCTION NewSubMenu (Name: TMenuStr; AHelpCtx: Word; SubMenu: PMenu;
+  Next: PMenuItem): PMenuItem;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          STATUS INTERFACE ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-NewStatusDef-------------------------------------------------------
+Allocates and returns a pointer to a new TStatusDef record initialized
+with the given parameter values. Calls to NewStatusDef can be nested.
+An error creating will return a nil pointer.
+15May98 LdB
+---------------------------------------------------------------------}
+FUNCTION NewStatusDef (AMin, AMax: Word; AItems: PStatusItem;
+  ANext: PStatusDef): PStatusDef;
+
+{-NewStatusKey-------------------------------------------------------
+Allocates and returns a pointer to a new TStatusItem record initialized
+with the given parameter values (using NewStr to allocate the Text).
+An error in creating will return a nil pointer.
+15May98 LdB
+---------------------------------------------------------------------}
+FUNCTION NewStatusKey (AText: String; AKeyCode: Word; ACommand: Word;
+  ANext: PStatusItem): PStatusItem;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           OBJECT REGISTER ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{-RegisterMenus-------------------------------------------------------
+Calls RegisterType for each of the object types defined in this unit.
+15May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE RegisterMenus;
+
+{***************************************************************************}
+{                           OBJECT REGISTRATION                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                        TMenuBar STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RMenuBar: TStreamRec = (
+     ObjType: 40;                                     { Register id = 40 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TMenuBar)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TMenuBar);
+     {$ENDIF}
+     Load:    @TMenuBar.Load;                         { Object load method }
+     Store:   @TMenuBar.Store                         { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                        TMenuBox STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RMenuBox: TStreamRec = (
+     ObjType: 41;                                     { Register id = 41 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TMenuBox)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TMenuBox);
+     {$ENDIF}
+     Load:    @TMenuBox.Load;                         { Object load method }
+     Store:   @TMenuBox.Store                         { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                      TStatusLine STREAM REGISTRATION                      }
+{---------------------------------------------------------------------------}
+CONST
+   RStatusLine: TStreamRec = (
+     ObjType: 42;                                     { Register id = 42 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TStatusLine)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TStatusLine);
+     {$ENDIF}
+     Load:    @TStatusLine.Load;                      { Object load method }
+     Store:   @TStatusLine.Store                      { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                       TMenuPopup STREAM REGISTRATION                      }
+{---------------------------------------------------------------------------}
+CONST
+   RMenuPopup: TStreamRec = (
+     ObjType: 43;                                     { Register id = 43 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TMenuPopup)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TMenuPopup);
+     {$ENDIF}
+     Load:    @TMenuPopup.Load;                       { Object load method }
+     Store:   @TMenuPopup.Store                       { Object store method }
+   );
+
+{***************************************************************************}
+{                        INITIALIZED PUBLIC VARIABLES                       }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                       INITIALIZED PUBLIC VARIABLES                        }
+{---------------------------------------------------------------------------}
+CONST
+   AdvancedMenus: Boolean = False;                    { Advanced menus }
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{***************************************************************************}
+{                               OBJECT METHODS                              }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TMenuView OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TMenuView----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TMenuView.Init (Var Bounds: TRect);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   EventMask := EventMask OR evBroadcast;             { See broadcast events }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TMenuView.Load (Var S: TStream);
+
+   FUNCTION DoLoadMenu: PMenu;
+   VAR Tok: Byte; Item: PMenuItem; Last: ^PMenuItem; Menu: PMenu;
+   BEGIN
+     New(Menu);                                       { Create new menu }
+     Last := @Menu^.Items;                            { Start on first item }
+     Item := Nil;                                     { Clear pointer }
+     S.Read(Tok, 1);                                  { Read token }
+     While (Tok <> 0) Do Begin
+       New(Item);                                     { Create new item }
+       Last^ := Item;                                 { First part of chain }
+       If (Item <> Nil) Then Begin                    { Check item valid }
+         Last := @Item^.Next;                         { Complete chain }
+         With Item^ Do Begin
+           Name := S.ReadStr;                         { Read menu name }
+           S.Read(Command, 2);                        { Menu item command }
+           S.Read(Disabled, 1);                       { Menu item state }
+           S.Read(KeyCode, 2);                        { Menu item keycode }
+           S.Read(HelpCtx, 2);                        { Menu item help ctx }
+           If (Name <> Nil) Then
+             If Command = 0 Then
+               SubMenu := DoLoadMenu                  { Load submenu }
+                 Else Param := S.ReadStr;             { Read param string }
+         End;
+       End;
+       S.Read(Tok, 1);                                { Read token }
+     End;
+     Last^ := Nil;                                    { List complete }
+     Menu^.Default := Menu^.Items;                    { Set menu default }
+     DoLoadMenu := Menu;                              { Return menu }
+   End;
+
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   Menu := DoLoadMenu;                                { Load menu items }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  Execute -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TMenuView.Execute: Word;
+TYPE MenuAction = (DoNothing, DoSelect, DoReturn);
+VAR AutoSelect: Boolean; Action: MenuAction; Ch: Char; Res: Word; R: TRect;
+  ItemShown, P: PMenuItem; Target: PMenuView; E: TEvent; MouseActive: Boolean;
+
+   PROCEDURE TrackMouse;
+   VAR Mouse: TPoint; R: TRect;
+   BEGIN
+     Mouse.X := E.Where.X - RawOrigin.X;              { Local x position }
+     Mouse.Y := E.Where.Y - RawoRigin.Y;              { Local y position }
+     Current := Menu^.Items;                          { Start with current }
+     While (Current <> Nil) Do Begin
+       GetItemRect(Current, R);                       { Get item rectangle }
+       If R.Contains(Mouse) Then Begin                { Contains mouse }
+         MouseActive := True;                         { Return true }
+         Exit;                                        { Then exit }
+       End;
+       Current := Current^.Next;                      { Try next item }
+     End;
+   END;
+
+   PROCEDURE TrackKey (FindNext: Boolean);
+
+       PROCEDURE NextItem;
+       BEGIN
+         Current := Current^.Next;                    { Move to next item }
+         If (Current = Nil) Then
+           Current := Menu^.Items;                    { Return first menu }
+       END;
+
+       PROCEDURE PrevItem;
+       VAR P: PMenuItem;
+       BEGIN
+         P := Current;                                { Start on current }
+         If (P = Menu^.Items) Then P := Nil;          { Check if at start }
+         Repeat NextItem Until Current^.Next = P;     { Prev item found }
+       END;
+
+   BEGIN
+     If (Current <> Nil) Then                         { Current view valid }
+       Repeat
+         If FindNext Then NextItem Else PrevItem;     { Find next/prev item }
+       Until (Current^.Name <> Nil);                  { Until we have name }
+   END;
+
+   FUNCTION MouseInOwner: Boolean;
+   VAR Mouse: TPoint; R: TRect;
+   BEGIN
+     MouseInOwner := False;                           { Preset false }
+     If (ParentMenu <> Nil) AND (ParentMenu^.Size.Y = 1)
+     Then Begin                                       { Valid parent menu }
+       Mouse.X := E.Where.X - ParentMenu^.RawOrigin.X;{ Local x position }
+       Mouse.Y := E.Where.Y - ParentMenu^.RawOrigin.Y;{ Local y position }
+       ParentMenu^.GetItemRect(ParentMenu^.Current,R);{ Get item rect }
+       MouseInOwner := R.Contains(Mouse);             { Return result }
+     End;
+   END;
+
+   FUNCTION MouseInMenus: Boolean;
+   VAR P: PMenuView;
+   BEGIN
+     P := ParentMenu;                                 { Parent menu }
+     While (P <> Nil) AND NOT P^.MouseInView(E.Where)
+       Do P := P^.ParentMenu;                         { Check next menu }
+     MouseInMenus := (P <> Nil);                      { Return result }
+   END;
+
+   FUNCTION TopMenu: PMenuView;
+   VAR P: PMenuView;
+   BEGIN
+     P := @Self;                                      { Start with self }
+     While (P^.ParentMenu <> Nil) Do
+       P := P^.ParentMenu;                            { Check next menu }
+     TopMenu := P;                                    { Top menu }
+   END;
+
+BEGIN
+   AutoSelect := False;                               { Clear select flag }
+   MouseActive := False;                              { Clear mouse flag }
+   Res := 0;                                          { Clear result }
+   ItemShown := Nil;                                  { Clear item pointer }
+   If (Menu <> Nil) Then Current := Menu^.Default     { Set current item }
+     Else Current := Nil;                             { No menu = no current }
+   Repeat
+     Action := DoNothing;                             { Clear action flag }
+     GetEvent(E);                                     { Get next event }
+     Case E.What Of
+       evMouseDown: If MouseInView(E.Where)           { Mouse in us }
+         OR MouseInOwner Then Begin                   { Mouse in owner area }
+           TrackMouse;                                { Track the mouse }
+           If (Size.Y = 1) Then AutoSelect := True;   { Set select flag }
+         End Else Action := DoReturn;                 { Set return action }
+       evMouseUp: Begin
+           TrackMouse;                                { Track the mouse }
+           If MouseInOwner Then                       { Mouse in owner }
+             Current := Menu^.Default                 { Set as current }
+           Else If (Current <> Nil) AND
+           (Current^.Name <> Nil) Then
+             Action := DoSelect                       { Set select action }
+           Else If MouseActive OR MouseInView(E.Where)
+           Then Action := DoReturn                    { Set return action }
+           Else Begin
+             Current := Menu^.Default;                { Set current item }
+             If (Current = Nil) Then
+               Current := Menu^.Items;                { Select first item }
+             Action := DoNothing;                     { Do nothing action }
+           End;
+         End;
+       evMouseMove: If (E.Buttons <> 0) Then Begin    { Mouse moved }
+           TrackMouse;                                { Track the mouse }
+           If NOT (MouseInView(E.Where) OR MouseInOwner)
+           AND MouseInMenus Then Action := DoReturn;  { Set return action }
+         End;
+       evKeyDown:
+         Case CtrlToArrow(E.KeyCode) Of               { Check arrow keys }
+           kbUp, kbDown: If (Size.Y <> 1) Then
+             TrackKey(CtrlToArrow(E.KeyCode) = kbDown){ Track keyboard }
+             Else If (E.KeyCode = kbDown) Then        { Down arrow }
+             AutoSelect := True;                      { Select item }
+           kbLeft, kbRight: If (ParentMenu = Nil) Then
+             TrackKey(CtrlToArrow(E.KeyCode)=kbRight) { Track keyboard }
+             Else Action := DoReturn;                 { Set return action }
+           kbHome, kbEnd: If (Size.Y <> 1) Then Begin
+               Current := Menu^.Items;                { Set to first item }
+               If (E.KeyCode = kbEnd) Then            { If the 'end' key }
+                 TrackKey(False);                     { Move to last item }
+             End;
+           kbEnter: Begin
+               If Size.Y = 1 Then AutoSelect := True; { Select item }
+               Action := DoSelect;                    { Return the item }
+             End;
+           kbEsc: Begin
+               Action := DoReturn;                    { Set return action }
+               If (ParentMenu = Nil) OR
+               (ParentMenu^.Size.Y <> 1) Then         { Check parent }
+                 ClearEvent(E);                       { Kill the event }
+             End;
+           Else Target := @Self;                      { Set target as self }
+           Ch := GetAltChar(E.KeyCode);
+           If (Ch = #0) Then Ch := E.CharCode Else
+             Target := TopMenu;                       { Target is top menu }
+           P := Target^.FindItem(Ch);                 { Check for item }
+           If (P = Nil) Then Begin
+             P := TopMenu^.HotKey(E.KeyCode);         { Check for hot key }
+             If (P <> Nil) AND                        { Item valid }
+             CommandEnabled(P^.Command) Then Begin    { Command enabled }
+               Res := P^.Command;                     { Set return command }
+               Action := DoReturn;                    { Set return action }
+             End
+           End Else If Target = @Self Then Begin
+             If Size.Y = 1 Then AutoSelect := True;   { Set auto select }
+             Action := DoSelect;                      { Select item }
+             Current := P;                            { Set current item }
+           End Else If (ParentMenu <> Target) OR
+           (ParentMenu^.Current <> P) Then            { Item different }
+              Action := DoReturn;                     { Set return action }
+         End;
+       evCommand: If (E.Command = cmMenu) Then Begin  { Menu command }
+           AutoSelect := False;                       { Dont select item }
+           If (ParentMenu <> Nil) Then
+             Action := DoReturn;                      { Set return action }
+         End Else Action := DoReturn;                 { Set return action }
+     End;
+     If (ItemShown <> Current) Then Begin             { New current item }
+       OldItem := ItemShown;                          { Hold old item }
+       ItemShown := Current;                          { Hold new item }
+       SetDrawMask(vdFocus OR vdInner);               { Set the draw mask }
+       DrawView;                                      { Redraw the items }
+       OldItem := Nil;                                { Clear old item }
+     End;
+     If (Action = DoSelect) OR ((Action = DoNothing)
+     AND AutoSelect) Then                             { Item is selecting }
+       If (Current <> Nil) Then With Current^ Do      { Current item valid }
+         If (Name <> Nil) Then                        { Item has a name }
+           If (Command = 0) Then Begin                { Has no command }
+             If (E.What AND (evMouseDown+evMouseMove) <> 0)
+               Then PutEvent(E);                      { Put event on queue }
+             GetItemRect(Current, R);                 { Get area of item }
+             R.A.X := R.A.X DIV FontWidth + Origin.X; { Left start point }
+             R.A.Y := R.B.Y DIV FontHeight + Origin.Y;{ Top start point }
+             R.B.X := Owner^.Size.X;                  { X screen area left }
+             R.B.Y := Owner^.Size.Y;                  { Y screen area left }
+             Target := TopMenu^.NewSubView(R, SubMenu,
+               @Self);                                { Create drop menu }
+             Res := Owner^.ExecView(Target);          { Execute dropped view }
+             Dispose(Target, Done);                   { Dispose drop view }
+           End Else If Action = DoSelect Then
+             Res := Command;                          { Return result }
+     If (Res <> 0) AND CommandEnabled(Res)            { Check command }
+     Then Begin
+       Action := DoReturn;                            { Return command }
+       ClearEvent(E);                                 { Clear the event }
+     End Else Res := 0;                               { Clear result }
+   Until (Action = DoReturn);
+   If (E.What <> evNothing) Then
+     If (ParentMenu <> Nil) OR (E.What = evCommand)   { Check event type }
+       Then PutEvent(E);                              { Put event on queue }
+   If (Current <> Nil) Then Begin
+     Menu^.Default := Current;                        { Set new default }
+     Current := Nil;                                  { Clear current }
+     DrawView;                                        { Redraw the view }
+   End;
+   Execute := Res;                                    { Return result }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  GetHelpCtx -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TMenuView.GetHelpCtx: Word;
+VAR C: PMenuView;
+BEGIN
+   C := @Self;                                        { Start at self }
+   While (C <> Nil) AND ((C^.Current = Nil) OR
+   (C^.Current^.HelpCtx = hcNoContext) OR             { Has no context }
+   (C^.Current^.Name = Nil)) Do C := C^.ParentMenu;   { Parent menu context }
+   If (C<>Nil) Then GetHelpCtx := C^.Current^.HelpCtx { Current context }
+     Else GetHelpCtx := hcNoContext;                  { No help context }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TMenuView.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CMenuView;                          { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CMenuView)] = CMenuView;       { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  FindItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TMenuView.FindItem (Ch: Char): PMenuItem;
+VAR I: Integer; P: PMenuItem;
+BEGIN
+   Ch := UpCase(Ch);                                  { Upper case of char }
+   P := Menu^.Items;                                  { First menu item }
+   While (P <> Nil) Do Begin                          { While item valid }
+     If (P^.Name <> Nil) AND (NOT P^.Disabled)        { Valid enabled cmd }
+     Then Begin
+       I := Pos('~', P^.Name^);                       { Scan for highlight }
+       If (I <> 0) AND (Ch = UpCase(P^.Name^[I+1]))   { Hotkey char found }
+       Then Begin
+         FindItem := P;                               { Return item }
+         Exit;                                        { Now exit }
+       End;
+     End;
+     P := P^.Next;                                    { Next item }
+   End;
+   FindItem := Nil;                                   { No item found }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  HotKey -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB            }
+{---------------------------------------------------------------------------}
+FUNCTION TMenuView.HotKey (KeyCode: Word): PMenuItem;
+
+   FUNCTION FindHotKey (P: PMenuItem): PMenuItem;
+   VAR T: PMenuItem;
+   BEGIN
+     While (P <> Nil) Do Begin                        { While item valid }
+       If (P^.Name <> Nil) Then                       { If valid name }
+         If (P^.Command = 0) Then Begin               { Valid command }
+           T := FindHotKey(P^.SubMenu^.Items);        { Search for hot key }
+           If (T <> Nil) Then Begin
+             FindHotKey := T;                         { Return hotkey }
+             Exit;                                    { Now exit }
+           End;
+         End Else If NOT P^.Disabled AND              { Hotkey is enabled }
+         (P^.KeyCode <> kbNoKey) AND                  { Valid keycode }
+         (P^.KeyCode = KeyCode) Then Begin            { Key matches request }
+           FindHotKey := P;                           { Return hotkey code }
+           Exit;                                      { Exit }
+         End;
+         P := P^.Next;                                { Next item }
+     End;
+     FindHotKey := Nil;                               { No item found }
+   END;
+
+BEGIN
+   HotKey := FindHotKey(Menu^.Items);                 { Hot key function }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  NewSubView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TMenuView.NewSubView (Var Bounds: TRect; AMenu: PMenu;
+  AParentMenu: PMenuView): PMenuView;
+BEGIN
+   NewSubView := New(PMenuBox, Init(Bounds, AMenu,
+     AParentMenu));                                   { Create a menu box }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuView.Store (Var S: TStream);
+
+   PROCEDURE DoStoreMenu (Menu: PMenu);
+   VAR Item: PMenuItem; Tok: Byte;
+   BEGIN
+     Tok := $FF;                                      { Preset max count }
+     Item := Menu^.Items;                             { Start first item }
+     While (Item <> Nil) Do Begin
+       With Item^ Do Begin
+         S.Write(Tok, 1);                             { Write tok value }
+         S.WriteStr(Name);                            { Write item name }
+         S.Write(Command, 2);                         { Menu item command }
+         S.Write(Disabled, 1);                        { Menu item state }
+         S.Write(KeyCode, 2);                         { Menu item keycode }
+         S.Write(HelpCtx, 2);                         { Menu item help ctx }
+         If (Name <> Nil) Then
+           If Command = 0 Then DoStoreMenu(SubMenu)
+           Else S.WriteStr(Param);                    { Write parameter }
+       End;
+       Item := Item^.Next;                            { Next item }
+     End;
+     Tok := 0;                                        { Clear tok count }
+     S.Write(Tok, 1);                                 { Write tok value }
+   END;
+
+BEGIN
+   TView.Store(S);                                    { TView.Store called }
+   DoStoreMenu(Menu);                                 { Store menu items }
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuView.HandleEvent (Var Event: TEvent);
+VAR CallDraw: Boolean; P: PMenuItem;
+
+   PROCEDURE UpdateMenu (Menu: PMenu);
+   VAR P: PMenuItem; CommandState: Boolean;
+   BEGIN
+     P := Menu^.Items;                                { Start on first item }
+     While (P <> Nil) Do Begin
+       If (P^.Name <> Nil) Then                       { Valid name }
+       If (P^.Command = 0) Then UpdateMenu(P^.SubMenu){ Update menu }
+       Else Begin
+         CommandState := CommandEnabled(P^.Command);  { Menu item state }
+         If (P^.Disabled = CommandState) Then Begin
+           P^.Disabled := NOT CommandState;           { Disable item }
+           CallDraw := True;                          { Must draw }
+         End;
+       End;
+       P := P^.Next;                                  { Next item }
+     End;
+   END;
+
+   PROCEDURE DoSelect;
+   BEGIN
+     PutEvent(Event);                                 { Put event on queue }
+     Event.Command := Owner^.ExecView(@Self);         { Execute view }
+     If (Event.Command <> 0) AND
+     CommandEnabled(Event.Command) Then Begin
+       Event.What := evCommand;                       { Command event }
+       Event.InfoPtr := Nil;                          { Clear info ptr }
+       PutEvent(Event);                               { Put event on queue }
+     End;
+     ClearEvent(Event);                               { Clear the event }
+   END;
+
+BEGIN
+   If (Menu <> Nil) Then
+     Case Event.What Of
+       evMouseDown: DoSelect;                         { Select menu item }
+       evKeyDown:
+         If (FindItem(GetAltChar(Event.KeyCode)) <> Nil)
+         Then DoSelect Else Begin                     { Select menu item }
+           P := HotKey(Event.KeyCode);                { Check for hotkey }
+           If (P <> Nil) AND
+           (CommandEnabled(P^.Command)) Then Begin
+             Event.What := evCommand;                 { Command event }
+             Event.Command := P^.Command;             { Set command event }
+             Event.InfoPtr := Nil;                    { Clear info ptr }
+             PutEvent(Event);                         { Put event on queue }
+             ClearEvent(Event);                       { Clear the event }
+           End;
+         End;
+       evCommand:
+         If Event.Command = cmMenu Then DoSelect;     { Select menu item }
+       evBroadcast:
+         If (Event.Command = cmCommandSetChanged)     { Commands changed }
+         Then Begin
+           CallDraw := False;                         { Preset no redraw }
+           UpdateMenu(Menu);                          { Update menu }
+           If CallDraw Then DrawView;                 { Redraw if needed }
+         End;
+     End;
+END;
+
+{--TMenuView----------------------------------------------------------------}
+{  GetItemRect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuView.GetItemRect (Item: PMenuItem; Var R: TRect);
+BEGIN                                                 { Abstract method }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TMenuBar OBJECT METHODS                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TMenuBar-----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TMenuBar.Init (Var Bounds: TRect; AMenu: PMenu);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   GrowMode := gfGrowHiX;                             { Set grow mode }
+   Menu := AMenu;                                     { Hold menu item }
+   Options := Options OR ofPreProcess;                { Preprocessing view }
+END;
+
+{--TMenuBar-----------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TMenuBar.Done;
+BEGIN
+   If (Menu <> Nil) Then DisposeMenu(Menu);           { Dispose menu items }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TMenuBar-----------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuBar.Draw;
+VAR I, J, K, L, CNormal, CSelect, CNormDisabled, CSelDisabled, Color: Word;
+    P: PMenuItem; B: TDrawBuffer;
+BEGIN
+   CNormal := GetColor($0301);                        { Normal colour }
+   CSelect := GetColor($0604);                        { Select colour }
+   CNormDisabled := GetColor($0202);                  { Disabled colour }
+   CSelDisabled := GetColor($0505);                   { Select disabled }
+   If (Menu <> Nil) Then Begin                        { Valid menu }
+     I := 0;                                          { Set start position }
+     P := Menu^.Items;                                { First item }
+     While (P <> Nil) Do Begin
+       If (P^.Name <> Nil) Then Begin                 { Name valid }
+         J := CStrLen(P^.Name^) + 2;                  { Name string length }
+         If (P = OldItem) OR (P = Current) Then Begin { Matches a state }
+           If P^.Disabled Then Begin
+             If (P = Current) Then
+               Color := CSelDisabled                  { Select disabled }
+               Else Color := CNormDisabled            { Normal disabled }
+           End Else Begin
+             If (P = Current) Then Color := CSelect   { Select colour }
+               Else Color := CNormal;                 { Normal colour }
+           End;
+           MoveCStr(B, ' '+P^.Name^+' ', Color);      { Name to buffer }
+           WriteBuf(I, 0, J, 1, B);                   { Write the string }
+           K := I*FontWidth;                          { X start position }
+           L := K + TextWidth(' '+P^.Name^+' ');      { X end position }
+           If AdvancedMenus Then Begin
+             GraphLine(K, 0, L, 0, White);            { Redraw top line }
+             GraphLine(K, FontHeight-1, L,
+               FontHeight-1, DarkGray);               { Redraw lower line }
+           End;
+         End;
+         Inc(I, J);                                   { Advance position }
+       End;
+       P := P^.Next;                                  { Next item }
+     End;
+   End;
+END;
+
+{--TMenuBar-----------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuBar.DrawBackGround;
+VAR I, J, CNormal, CSelect, CNormDisabled, CSelDisabled, Color: Word;
+    P: PMenuItem; B: TDrawBuffer;
+BEGIN
+   Inherited DrawBackGround;                          { Call ancestor }
+   CNormal := GetColor($0301);                        { Normal colour }
+   CSelect := GetColor($0604);                        { Select colour }
+   CNormDisabled := GetColor($0202);                  { Disabled colour }
+   CSelDisabled := GetColor($0505);                   { Select disabled }
+   If (Menu <> Nil) Then Begin                        { Valid menu }
+     I := 0;                                          { Set start position }
+     P := Menu^.Items;                                { First item }
+     While (P <> Nil) Do Begin
+       If (P^.Name <> Nil) Then Begin                 { Name valid }
+         If P^.Disabled Then Begin
+           If (P = Current) Then Color := CSelDisabled{ Select disabled }
+             Else Color := CNormDisabled              { Normal disabled }
+         End Else Begin
+           If (P = Current) Then Color := CSelect     { Select colour }
+             Else Color := CNormal;                   { Normal colour }
+         End;
+         J := CStrLen(P^.Name^) + 2;                  { Length of string }
+         MoveCStr(B, ' '+P^.Name^+' ', Color);        { Name to buffer }
+         WriteBuf(I, 0, J, 1, B);                     { Write the string }
+         Inc(I, J);                                   { Advance position }
+       End;
+       P := P^.Next;                                  { Next item }
+     End;
+   End;
+   If AdvancedMenus Then BiColorRectangle(0, 0,
+     RawSize.X, RawSize.Y, White, DarkGray, False);   { Draw 3d effect }
+END;
+
+{--TMenuBar-----------------------------------------------------------------}
+{  GetItemRect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 08May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuBar.GetItemRect (Item: PMenuItem; Var R: TRect);
+VAR I: Integer; P: PMenuItem;
+BEGIN
+   I := 0;                                            { Preset to zero }
+   R.Assign(0, 0, 0, FontHeight);                     { Initial rect size }
+   P := Menu^.Items;                                  { First item }
+   While (P <> Nil) Do Begin                          { While valid item }
+     R.A.X := I*FontWidth;                            { Move area along }
+     If (P^.Name <> Nil) Then Begin                   { Valid name }
+       R.B.X := R.A.X+TextWidth(' ' + P^.Name^ + ' ');{ Add text width  }
+       I := I + CStrLen(P^.Name^) + 2;                { Add item length }
+     End Else R.B.X := R.A.X;
+     If (P = Item) Then Exit;                         { Requested item found }
+     P := P^.Next;                                    { Next item }
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TMenuBox OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TMenuBox-----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TMenuBox.Init (Var Bounds: TRect; AMenu: PMenu;
+  AParentMenu: PMenuView);
+VAR W, H, L: Integer; S: String; P: PMenuItem; R: TRect;
+BEGIN
+   W := 0;                                            { Clear initial width }
+   H := 2;                                            { Set initial height }
+   If (AMenu <> Nil) Then Begin                       { Valid menu }
+     P := AMenu^.Items;                               { Start on first item }
+     While (P <> Nil) Do Begin                        { If item valid }
+       If (P^.Name <> Nil) Then Begin                 { Check for name }
+         S := ' ' + P^.Name^ + ' ';                   { Transfer string }
+         If (P^.Command <> 0) AND (P^.Param <> Nil)
+           Then S := S + ' - ' + P^.Param^;           { Add any parameter }
+       End;
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+       HWindow := 0;                                  { Must zero handle }
+       Dc := 0;                                       { Must zero context }
+       {$ENDIF}
+       {$IFDEF OS_OS2}                                { OS2 CODE }
+       HWindow := 0;                                  { Must zero handle }
+       Ps := 0;                                       { Must zero pres space }
+       {$ENDIF}
+       L := TextWidth(S);                             { Width of string }
+       If (L > W) Then W := L;                        { Hold maximum }
+       Inc(H);                                        { Inc count of items }
+       P := P^.Next;                                  { Move to next item }
+     End;
+   End;
+   W := 5 + (W DIV FontWidth);                        { Longest text width }
+   R.Copy(Bounds);                                    { Copy the bounds }
+   If (R.A.X + W < R.B.X) Then R.B.X := R.A.X + W     { Shorten if possible }
+     Else R.A.X := R.B.X - W;                         { Insufficent space }
+   R.B.X := R.A.X + W;
+   If (R.A.Y + H < R.B.Y) Then R.B.Y := R.A.Y + H     { Shorten if possible }
+     Else R.A.Y := R.B.Y - H;                         { Insufficent height }
+   Inherited Init(R);                                 { Call ancestor }
+   State := State OR sfShadow;                        { Set shadow state }
+   Options := Options OR ofPreProcess;                { View pre processes }
+   Menu := AMenu;                                     { Hold menu }
+   ParentMenu := AParentMenu;                         { Hold parent }
+END;
+
+{--TMenuBox-----------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuBox.Draw;
+VAR CNormal, CSelect, CDisabled, Color: Word; Tx, Ty, Y: Integer;
+    S: String; P: PMenuItem; B: TDrawBuffer;
+BEGIN
+   CNormal := GetColor($0301);                        { Normal colour }
+   CSelect := GetColor($0604);                        { Selected colour }
+   CDisabled := GetColor($0202);                      { Disabled colour }
+   Y := 1;
+   If (Menu <> Nil) Then Begin                        { We have a menu }
+     P := Menu^.Items;                                { Start on first }
+     While (P <> Nil) Do Begin                        { Valid menu item }
+       Color := CNormal;                              { Normal colour }
+       If (P^.Name <> Nil) Then Begin                 { Item has text }
+         If P^.Disabled Then Color := CDisabled       { Is item disabled }
+         Else If (P = Current) Then Color := CSelect; { Select colour }
+         MoveChar(B, ' ', Color, Size.X-4);           { Clear buffer }
+         S := ' ' + P^.Name^ + ' ';                   { Menu string }
+         MoveCStr(B[0], S, Color);                    { Transfer string }
+         If (P^.Command <> 0) AND(P^.Param <> Nil)
+         Then Begin
+           MoveCStr(B[CStrLen(S)], ' - ' + P^.Param^,
+             Color);                                  { Add param chars }
+           S := S + ' - ' + P^.Param^;                { Add to string }
+         End;
+         If (OldItem = Nil) OR (OldItem = P) OR
+         (Current = P) Then Begin                     { We need to fix draw }
+           WriteBuf(2, Y, CStrLen(S), 1, B);          { Write the line }
+           If (P = Current) Then Begin                { Selected item }
+             Tx := 2 * FontWidth;                     { X offset }
+             Ty := Y * FontHeight;                    { Y offset }
+             BicolorRectangle(Tx, Ty, Tx + TextWidth(S)
+               - 1, Ty + FontHeight - 1, White,
+               DarkGray, False);                      { Draw higlight box }
+           End;
+         End;
+       End;
+       Inc(Y);                                        { Next line down }
+       P := P^.Next;                                  { fetch next item }
+     End;
+   End;
+END;
+
+{--TMenuBox-----------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuBox.DrawBackGround;
+VAR X, Y, Y2: Integer; P : PMenuItem;
+BEGIN
+   Y2 := FontHeight DIV 2;                            { Intra offset }
+   Y := FontHeight;                                   { Initial position }
+   X := 3*FontWidth;                                  { 2 offset }
+   Inherited DrawBackGround;                          { Call ancestor }
+   If (Menu <> Nil) Then Begin                        { We have a menu }
+     P := Menu^.Items;                                { Start on first }
+     While (P <> Nil) Do Begin
+       If (P^.Name = Nil) Then                        { Item has no string }
+         BiColorRectangle(X, Y+Y2, RawSize.X-X,
+           Y+Y2+1, White, DarkGray, True);            { Draw 3d line effect }
+       Inc(Y, FontHeight);                            { Down one line }
+       P := P^.Next;                                  { Next item now }
+     End;
+   End;
+   BiColorRectangle(3, 3, RawSize.X-3, RawSize.Y-3,
+     White, DarkGray, False);                         { Draw 3d effect }
+   BiColorRectangle(5, 5, RawSize.X-5, RawSize.Y-5,
+    White, DarkGray, True);                           { Draw 3d effect }
+   BiColorRectangle(0, 0, RawSize.X, RawSize.Y,
+     White, DarkGray, False);                         { Draw 3d effect }
+END;
+
+{--TMenuBox-----------------------------------------------------------------}
+{  GetItemRect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuBox.GetItemRect (Item: PMenuItem; Var R: TRect);
+VAR X, Y: Integer; P: PMenuItem;
+BEGIN
+   Y := FontHeight;                                   { Initial y position }
+   P := Menu^.Items;                                  { Initial item }
+   While (P <> Item) Do Begin                         { Valid item }
+     Inc(Y, FontHeight);                              { Inc position }
+     P := P^.Next;                                    { Next item }
+   End;
+   X := 2 * FontWidth;                                { Left/Right margin }
+   R.Assign(X, Y, RawSize.X - X, Y + FontHeight);     { Assign area }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TMenuPopUp OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TMenuPopUp---------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TMenuPopup.Init (Var Bounds: TRect; AMenu: PMenu);
+BEGIN
+   Inherited Init(Bounds, AMenu, Nil);                { Call ancestor }
+END;
+
+{--TMenuPopUp---------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TMenuPopup.Done;
+BEGIN
+   If (Menu <> Nil) Then DisposeMenu(Menu);           { Dispose menu items }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TMenuPopUp---------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TMenuPopup.HandleEvent (Var Event: TEvent);
+VAR P: PMenuItem;
+BEGIN
+   Case Event.What Of
+     evKeyDown: Begin
+         P := FindItem(GetCtrlChar(Event.KeyCode));   { Find the item }
+         If (P = Nil) Then P := HotKey(Event.KeyCode);{ Try hot key }
+         If (P <> Nil) AND (CommandEnabled(P^.Command))
+         Then Begin                                   { Command valid }
+           Event.What := evCommand;                   { Command event }
+           Event.Command := P^.Command;               { Set command value }
+           Event.InfoPtr := Nil;                      { Clear info ptr }
+           PutEvent(Event);                           { Put event on queue }
+           ClearEvent(Event);                         { Clear the event }
+         End Else If (GetAltChar(Event.KeyCode) <> #0)
+           Then ClearEvent(Event);                    { Clear the event }
+       End;
+   End;
+   Inherited HandleEvent(Event);                      { Call ancestor }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TStatusLine OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TStatusLine--------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TStatusLine.Init (Var Bounds: TRect; ADefs: PStatusDef);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   Options := Options OR ofPreProcess;                { Pre processing view }
+   EventMask := EventMask OR evBroadcast;             { See broadcasts }
+   GrowMode := gfGrowLoY + gfGrowHiX + gfGrowHiY;     { Set grow modes }
+   Defs := ADefs;                                     { Set default items }
+   FindItems;                                         { Find the items }
+END;
+
+{--TStatusLine--------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TStatusLine.Load (Var S: TStream);
+
+   FUNCTION DoLoadStatusItems: PStatusItem;
+   VAR Count: Integer; Cur, First: PStatusItem; Last: ^PStatusItem;
+   BEGIN
+     Cur := Nil;                                      { Preset nil }
+     Last := @First;                                  { Start on first item }
+     S.Read(Count, 2);                                { Read count }
+     While (Count > 0) Do Begin
+       New(Cur);                                      { New status item }
+       Last^ := Cur;                                  { First chain part }
+       If (Cur <> Nil) Then Begin                     { Check pointer valid }
+         Last := @Cur^.Next;                          { Chain complete }
+         Cur^.Text := S.ReadStr;                      { Read item text }
+         S.Read(Cur^.KeyCode, 2);                     { Keycode of item }
+         S.Read(Cur^.Command, 2);                     { Command of item }
+       End;
+       Dec(Count);                                    { One item loaded }
+     End;
+     Last^ := Nil;                                    { Now chain end }
+     DoLoadStatusItems := First;                      { Return the list }
+   END;
+
+   FUNCTION DoLoadStatusDefs: PStatusDef;
+   VAR Count: Integer; Cur, First: PStatusDef; Last: ^PStatusDef;
+   BEGIN
+     Last := @First;                                  { Start on first }
+     S.Read(Count, 2);                                { Read item count }
+     While (Count > 0) Do Begin
+       New(Cur);                                      { New status def }
+       Last^ := Cur;                                  { First part of chain }
+       If (Cur <> Nil) Then Begin                     { Check pointer valid }
+         Last := @Cur^.Next;                          { Chain complete }
+         S.Read(Cur^.Min, 2);                         { Read min data }
+         S.Read(Cur^.Max, 2);                         { Read max data }
+         Cur^.Items := DoLoadStatusItems;             { Set pointer }
+       End;
+       Dec(Count);                                    { One item loaded }
+     End;
+     Last^ := Nil;                                    { Now chain ends }
+     DoLoadStatusDefs := First;                       { Return item list }
+   END;
+
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   Defs := DoLoadStatusDefs;                          { Retreive items }
+   FindItems;                                         { Find the items }
+END;
+
+{--TStatusLine--------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TStatusLine.Done;
+VAR T: PStatusDef;
+
+   PROCEDURE DisposeItems (Item: PStatusItem);
+   VAR T: PStatusItem;
+   BEGIN
+     While (Item <> Nil) Do Begin                     { Item to dispose }
+       T := Item;                                     { Hold pointer }
+       Item := Item^.Next;                            { Move down chain }
+       DisposeStr(T^.Text);                           { Dispose string }
+       Dispose(T);                                    { Dispose item }
+     End;
+   END;
+
+BEGIN
+   While (Defs <> Nil) Do Begin
+     T := Defs;                                       { Hold pointer }
+     Defs := Defs^.Next;                              { Move down chain }
+     DisposeItems(T^.Items);                          { Dispose the item }
+     Dispose(T);                                      { Dispose status item }
+   End;
+   Inherited Done;                                    { Call ancestor }
+END;
+
+
+{--TStatusLine--------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TStatusLine.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CStatusLine;                        { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CStatusLine)] = CStatusLine;   { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{--TStatusLine--------------------------------------------------------------}
+{  Hint -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION TStatusLine.Hint (AHelpCtx: Word): String;
+BEGIN
+   Hint := '';                                        { Return nothing }
+END;
+
+{--TStatusLine--------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TStatusLine.Draw;
+BEGIN
+   DrawSelect(Nil);                                   { Call draw select }
+END;
+
+{--TStatusLine--------------------------------------------------------------}
+{  Update -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TStatusLine.Update;
+VAR H: Word; P: PView;
+BEGIN
+   P := TopView;                                      { Get topmost view }
+   If (P <> Nil) Then H := P^.GetHelpCtx Else         { Top views context }
+     H := hcNoContext;                                { No context }
+   If (HelpCtx <> H) Then Begin                       { Differs from last }
+     HelpCtx := H;                                    { Hold new context }
+     FindItems;                                       { Find the item }
+     DrawView;                                        { Redraw the view }
+   End;
+END;
+
+{--TStatusLine--------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TStatusLine.Store (Var S: TStream);
+
+   PROCEDURE DoStoreStatusItems (Cur: PStatusItem);
+   VAR Count: Integer; T: PStatusItem;
+   BEGIN
+     Count := 0;                                      { Clear count }
+     T := Cur;                                        { Start on current }
+     While (T <> Nil) Do Begin
+       Inc(Count);                                    { Count items }
+       T := T^.Next;                                  { Next item }
+     End;
+     S.Write(Count, 2);                               { Write item count }
+     While (Cur <> Nil) Do Begin
+       S.WriteStr(Cur^.Text);                         { Store item text }
+       S.Write(Cur^.KeyCode, 2);                      { Keycode of item }
+       S.Write(Cur^.Command, 2);                      { Command of item }
+       Cur := Cur^.Next;                              { Move to next item }
+     End;
+   END;
+
+   PROCEDURE DoStoreStatusDefs (Cur: PStatusDef);
+   VAR Count: Integer; T: PStatusDef;
+   BEGIN
+     Count := 0;                                      { Clear count }
+     T := Cur;                                        { Current status item }
+     While (T <> Nil) Do Begin
+       Inc(Count);                                    { Count items }
+       T := T^.Next                                   { Next item }
+     End;
+     S.Write(Count, 2);                               { Write item count }
+     While (Cur <> Nil) Do Begin
+       With Cur^ Do Begin
+         S.Write(Cur^.Min, 2);                        { Write min data }
+         S.Write(Cur^.Max, 2);                        { Write max data }
+         DoStoreStatusItems(Items);                   { Store the items }
+       End;
+       Cur := Cur^.Next;                              { Next status item }
+     End;
+   END;
+
+BEGIN
+   TView.Store(S);                                    { TView.Store called }
+   DoStoreStatusDefs(Defs);                           { Store status items }
+END;
+
+{--TStatusLine--------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TStatusLine.HandleEvent (Var Event: TEvent);
+VAR Mouse: TPoint; T, Tt: PStatusItem;
+
+   FUNCTION ItemMouseIsIn: PStatusItem;
+   VAR X, Xi: Word; T: PStatusItem;
+   BEGIN
+     ItemMouseIsIn := Nil;                            { Preset fail }
+     If (Mouse.Y < 0) OR (Mouse.Y > FontHeight)       { Outside view height }
+       Then Exit;                                     { Not in view exit }
+     X := 0;                                          { Zero x position }
+     T := Items;                                      { Start at first item }
+     While (T <> Nil) Do Begin                        { While item valid }
+       If (T^.Text <> Nil) Then Begin                 { Check valid text }
+         Xi := X;                                     { Hold initial x value }
+         X := Xi + TextWidth(' ' + T^.Text^ + ' ');   { Add text width }
+         If (Mouse.X >= Xi) AND (Mouse.X < X)
+         Then Begin
+           ItemMouseIsIn := T;                        { Selected item }
+           Exit;                                      { Now exit }
+         End;
+       End;
+       T := T^.Next;                                  { Next item }
+     End;
+   END;
+
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   Case Event.What Of
+     evMouseDown: Begin
+         T := Nil;                                    { Preset ptr to nil }
+         Repeat
+           Mouse.X := Event.Where.X - RawOrigin.X;    { Local x position }
+           Mouse.Y := Event.Where.Y - RawOrigin.Y;    { Local y position }
+           Tt := ItemMouseIsIn;                       { Find selected item }
+           If (T <> Tt) Then                          { Item has changed }
+             DrawSelect(Tt);                          { Draw new item }
+           T := Tt                                    { Transfer item }
+         Until NOT MouseEvent(Event, evMouseMove);    { Mouse stopped moving }
+         If (T <> Nil) AND CommandEnabled(T^.Command) { Check cmd enabled }
+         Then Begin
+           Event.What := evCommand;                   { Command event }
+           Event.Command := T^.Command;               { Set command value }
+           Event.InfoPtr := Nil;                      { No info ptr }
+           PutEvent(Event);                           { Put event on queue }
+         End;
+         ClearEvent(Event);                           { Clear the event }
+         DrawSelect(Nil);                             { Clear the highlight }
+       End;
+     evKeyDown: Begin                                 { Key down event }
+         T := Items;                                  { Start on first item }
+         While (T <> Nil) Do Begin                    { For each valid item }
+           If (Event.KeyCode = T^.KeyCode) AND        { Check for hot key }
+           CommandEnabled(T^.Command) Then Begin      { Check cmd enabled }
+             Event.What := evCommand;                 { Change to command }
+             Event.Command := T^.Command;             { Set command value }
+             Event.InfoPtr := Nil;                    { Clear info ptr }
+             Exit;                                    { Now exit }
+           End;
+           T := T^.Next;                              { Next item }
+         End;
+       End;
+     evBroadcast:
+       If (Event.Command = cmCommandSetChanged) Then  { Command set change }
+         DrawView;                                    { Redraw view }
+   End;
+END;
+
+{***************************************************************************}
+{                    TStatusLine OBJECT PRIVATE METHODS                     }
+{***************************************************************************}
+
+{--TStatusLine--------------------------------------------------------------}
+{  FindItems -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TStatusLine.FindItems;
+VAR P: PStatusDef;
+BEGIN
+   P := Defs;                                         { First status item }
+   While (P <> Nil) AND ((HelpCtx < P^.Min) OR
+   (HelpCtx > P^.Max)) Do P := P^.Next;               { Find status item }
+   If (P = Nil) Then Items := Nil Else
+     Items := P^.Items;                               { Return found item }
+END;
+
+{--TStatusLine--------------------------------------------------------------}
+{  DrawSelect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11May98 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TStatusLine.DrawSelect (Selected: PStatusItem);
+VAR I, L: Integer; Color, CSelect, CNormal, CSelDisabled, CNormDisabled: Word;
+    HintBuf: String; B: TDrawBuffer; T: PStatusItem;
+BEGIN
+   CNormal := GetColor($0301);                        { Normal colour }
+   CSelect := GetColor($0604);                        { Select colour }
+   CNormDisabled := GetColor($0202);                  { Disabled colour }
+   CSelDisabled := GetColor($0505);                   { Select disabled }
+   MoveChar(B, ' ', Byte(CNormal), 80);               { Clear the buffer }
+   T := Items;                                        { First item }
+   I := 0;                                            { Clear the count }
+   L := 0;
+   While (T <> Nil) Do Begin                          { While valid item }
+     If (T^.Text <> Nil) Then Begin                   { While valid text }
+       L := CStrLen(' '+T^.Text^+' ');                { Text length }
+       If CommandEnabled(T^.Command) Then Begin       { Command enabled }
+         If T = Selected Then Color := CSelect        { Selected colour }
+           Else Color := CNormal                      { Normal colour }
+       End Else
+         If T = Selected Then Color := CSelDisabled   { Selected disabled }
+           Else Color := CNormDisabled;               { Disabled colour }
+       MoveCStr(B[I], ' '+T^.Text^+' ', Color);       { Move text to buf }
+       Inc(I, L);                                     { Advance position }
+     End;
+     T := T^.Next;                                    { Next item }
+   End;
+   HintBuf := Hint(HelpCtx);                          { Get hint string }
+   If (HintBuf <> '') Then Begin                      { Hint present }
+     {$IFNDEF OS_WINDOWS}
+     MoveChar(B[I], #179, Byte(CNormal), 1);          { '|' char to buffer }
+     {$ELSE}
+     MoveChar(B[I], #166, Byte(CNormal), 1);          { '|' char to buffer }
+     {$ENDIF}
+     Inc(I, 2);                                       { Move along }
+     MoveStr(B[I], HintBuf, Byte(CNormal));           { Move hint to buffer }
+     I := I + Length(HintBuf);                        { Hint length }
+   End;
+   WriteLine(0, 0, I, 1, B);                          { Write the buffer }
+   If AdvancedMenus Then BicolorRectangle(0, 0,
+     RawSize.X, RawSize.Y, White, DarkGray, False);   { Add 3d effect }
+END;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           MENU INTERFACE ROUTINES                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  NewMenu -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION NewMenu (Items: PMenuItem): PMenu;
+VAR P: PMenu;
+BEGIN
+   New(P);                                            { Create new menu }
+   If (P <> Nil) Then Begin                           { Check valid pointer }
+     P^.Items := Items;                               { Hold item list }
+     P^.Default := Items;                             { Set default item }
+   End;
+   NewMenu := P;                                      { Return menu }
+END;
+
+{---------------------------------------------------------------------------}
+{  DisposeMenu -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE DisposeMenu (Menu: PMenu);
+VAR P, Q: PMenuItem;
+BEGIN
+   If (Menu <> Nil) Then Begin                        { Valid menu item }
+     P := Menu^.Items;                                { First item in list }
+     While (P <> Nil) Do Begin                        { Item is valid }
+       If (P^.Name <> Nil) Then Begin                 { Valid name pointer }
+         DisposeStr(P^.Name);                         { Dispose of name }
+         If (P^.Command <> 0) Then
+           DisposeStr(P^.Param) Else                  { Dispose parameter }
+           DisposeMenu(P^.SubMenu);                   { Dispose submenu }
+       End;
+       Q := P;                                        { Hold pointer }
+       P := P^.Next;                                  { Move to next item }
+       Dispose(Q);                                    { Dispose of item }
+     End;
+     Dispose(Menu);                                   { Dispose of menu }
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                             MENU ITEM ROUTINES                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  NewLine -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION NewLine (Next: PMenuItem): PMenuItem;
+VAR P: PMenuItem;
+BEGIN
+   New(P);                                            { Allocate memory }
+   If (P <> Nil) Then Begin                           { Check valid pointer }
+     P^.Next := Next;                                 { Hold next menu item }
+     P^.Name := Nil;                                  { Clear name ptr }
+     P^.HelpCtx := hcNoContext;                       { Clear help context }
+   End;
+   NewLine := P;                                      { Return new line }
+END;
+
+{---------------------------------------------------------------------------}
+{  NewItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION NewItem (Name, Param: TMenuStr; KeyCode: Word; Command: Word;
+  AHelpCtx: Word; Next: PMenuItem): PMenuItem;
+VAR P: PMenuItem; R: TRect; T: PView;
+BEGIN
+   If (Name <> '') AND (Command <> 0) Then Begin
+     New(P);                                          { Allocate memory }
+     If (P <> Nil) Then Begin                         { Check valid pointer }
+       P^.Next := Next;                               { Hold next item }
+       P^.Name := NewStr(Name);                       { Hold item name }
+       P^.Command := Command;                         { Hold item command }
+       R.Assign(1, 1, 10, 10);                        { Random assignment }
+       T := New(PView, Init(R));                      { Create a view }
+       If (T <> Nil) Then Begin
+         P^.Disabled := NOT T^.CommandEnabled(Command);
+         Dispose(T, Done);                            { Dispose of view }
+       End Else P^.Disabled := True;
+       P^.KeyCode := KeyCode;                         { Hold item keycode }
+       P^.HelpCtx := AHelpCtx;                        { Hold help context }
+       P^.Param := NewStr(Param);                     { Hold parameter }
+     End;
+     NewItem := P;                                    { Return item }
+   End Else NewItem := Next;                          { Move forward }
+END;
+
+{---------------------------------------------------------------------------}
+{  NewSubMenu -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 14May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION NewSubMenu (Name: TMenuStr; AHelpCtx: Word; SubMenu: PMenu;
+  Next: PMenuItem): PMenuItem;
+VAR P: PMenuItem;
+BEGIN
+   If (Name <> '') AND (SubMenu <> Nil) Then Begin
+     New(P);                                          { Allocate memory }
+     If (P <> Nil) Then Begin                         { Check valid pointer }
+       P^.Next := Next;                               { Hold next item }
+       P^.Name := NewStr(Name);                       { Hold submenu name }
+       P^.Command := 0;                               { Clear item command }
+       P^.Disabled := False;                          { Item not disabled }
+       P^.HelpCtx := AHelpCtx;                        { Set help context }
+       P^.SubMenu := SubMenu;                         { Hold next submenu }
+     End;
+     NewSubMenu := P;                                 { Return submenu }
+   End Else NewSubMenu := Next;                       { Return next item }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          STATUS INTERFACE ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  NewStatusDef -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION NewStatusDef (AMin, AMax: Word; AItems: PStatusItem;
+ANext:PStatusDef): PStatusDef;
+VAR T: PStatusDef;
+BEGIN
+   New(T);                                            { Allocate memory }
+   If (T <> Nil) Then Begin                           { Check valid pointer }
+     T^.Next := ANext;                                { Set next item }
+     T^.Min := AMin;                                  { Hold min value }
+     T^.Max := AMax;                                  { Hold max value }
+     T^.Items := AItems;                              { Hold item list }
+   End;
+   NewStatusDef := T;                                 { Return status }
+END;
+
+{---------------------------------------------------------------------------}
+{  NewStatusKey -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION NewStatusKey (AText: String; AKeyCode: Word; ACommand: Word;
+  ANext: PStatusItem): PStatusItem;
+VAR T: PStatusItem;
+BEGIN
+   New(T);                                            { Allocate memory }
+   If (T <> Nil) Then Begin                           { Check valid pointer }
+     T^.Text := NewStr(AText);                        { Hold text string }
+     T^.KeyCode := AKeyCode;                          { Hold keycode }
+     T^.Command := ACommand;                          { Hold command }
+     T^.Next := ANext;                                { Pointer to next }
+   End;
+   NewStatusKey := T;                                 { Return status item }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           OBJECT REGISTER ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  RegisterMenus -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE RegisterMenus;
+BEGIN
+   RegisterType(RMenuBar);                            { Register bar menu }
+   RegisterType(RMenuBox);                            { Register menu box }
+   RegisterType(RStatusLine);                         { Register status line }
+   RegisterType(RMenuPopup);                          { Register popup menu }
+END;
+
+END.

+ 262 - 0
fv/msgbox.pas

@@ -0,0 +1,262 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{   System independent GRAPHICAL clone of MSGBOX.PAS       }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail addr           }
+{   [email protected] - backup e-mail addr            }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     12 Jun 96   Initial DOS/DPMI code released.    }
+{  1.10     18 Oct 97   Code converted to GUI & TEXT mode. }
+{  1.20     18 Jul 97   Windows conversion added.          }
+{  1.30     29 Aug 97   Platform.inc sort added.           }
+{  1.40     22 Oct 97   Delphi3 32 bit code added.         }
+{  1.50     05 May 98   Virtual pascal 2.0 code added.     }
+{  1.60     30 Sep 99   Complete recheck preformed         }
+{**********************************************************}
+
+UNIT MsgBox;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F-} { Near calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES Objects;                                         { Standard GFV unit }
+
+{***************************************************************************}
+{                              PUBLIC CONSTANTS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                             MESSAGE BOX CLASSES                           }
+{---------------------------------------------------------------------------}
+CONST
+   mfWarning      = $0000;                            { Display a Warning box }
+   mfError        = $0001;                            { Dispaly a Error box }
+   mfInformation  = $0002;                            { Display an Information Box }
+   mfConfirmation = $0003;                            { Display a Confirmation Box }
+
+   mfInsertInApp  = $0080;                            { Insert message box into }
+                                                      { app instead of the Desktop }
+{---------------------------------------------------------------------------}
+{                          MESSAGE BOX BUTTON FLAGS                         }
+{---------------------------------------------------------------------------}
+CONST
+   mfYesButton    = $0100;                            { Yes button into the dialog }
+   mfNoButton     = $0200;                            { No button into the dialog }
+   mfOKButton     = $0400;                            { OK button into the dialog }
+   mfCancelButton = $0800;                            { Cancel button into the dialog }
+
+   mfYesNoCancel  = mfYesButton + mfNoButton + mfCancelButton;
+                                                      { Yes, No, Cancel dialog }
+   mfOKCancel     = mfOKButton + mfCancelButton;
+                                                      { Standard OK, Cancel dialog }
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{-MessageBox---------------------------------------------------------
+MessageBox displays the given string in a standard sized dialog box.
+Before the dialog is displayed the Msg and Params are passed to FormatStr.
+The resulting string is displayed as a TStaticText view in the dialog.
+30Sep99 LdB
+---------------------------------------------------------------------}
+FUNCTION MessageBox (Const Msg: String; Params: Pointer;
+  AOptions: Word): Word;
+
+{-MessageBoxRect-----------------------------------------------------
+MessageBoxRec allows the specification of a TRect for the message box
+to occupy.
+30Sep99 LdB
+---------------------------------------------------------------------}
+FUNCTION MessageBoxRect (Var R: TRect; Const Msg: String; Params: Pointer;
+  AOptions: Word): Word;
+
+{-InputBox-----------------------------------------------------------
+InputBox displays a simple dialog that allows user to type in a string
+30Sep99 LdB
+---------------------------------------------------------------------}
+FUNCTION InputBox (Const Title, ALabel: String; Var S: String;
+  Limit: Byte): Word;
+
+{-InputBoxRect-------------------------------------------------------
+InputBoxRect is like InputBox but allows the specification of a rectangle.
+30Sep99 LdB
+---------------------------------------------------------------------}
+FUNCTION InputBoxRect (Var Bounds: TRect; Const Title, ALabel: String;
+  Var S: String; Limit: Byte): Word;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+USES Drivers, Views, App, Dialogs;                    { Standard GFV units }
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{  MessageBox -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION MessageBox(Const Msg: String; Params: Pointer; AOptions: Word): Word;
+VAR R: TRect;
+BEGIN
+   R.Assign(0, 0, 40, 9);                             { Assign area }
+   If (AOptions AND mfInsertInApp = 0) Then           { Non app insert }
+     R.Move((Desktop^.Size.X - R.B.X) DIV 2,
+       (Desktop^.Size.Y - R.B.Y) DIV 2) Else          { Calculate position }
+     R.Move((Application^.Size.X - R.B.X) DIV 2,
+       (Application^.Size.Y - R.B.Y) DIV 2);          { Calculate position }
+   MessageBox := MessageBoxRect(R, Msg, Params,
+     AOptions);                                       { Create message box }
+END;
+
+{---------------------------------------------------------------------------}
+{  MessageBoxRect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB    }
+{---------------------------------------------------------------------------}
+FUNCTION MessageBoxRect(Var R: TRect; Const Msg: String; Params: Pointer;
+  AOptions: Word): Word;
+CONST ButtonName: Array[0..3] Of String[6] = ('~Y~es', '~N~o', 'O~K~', 'Cancel');
+      Commands: Array[0..3] Of Word = (cmYes, cmNo, cmOK, cmCancel);
+      Titles: Array[0..3] Of String[11] = ('Warning','Error','Information','Confirm');
+VAR I, X, ButtonCount: Integer; S: String; Dialog: PDialog; Control: PView;
+    ButtonList: Array[0..4] Of PView;
+BEGIN
+   Dialog := New(PDialog, Init(R, Titles[AOptions
+     AND $3]));                                       { Create dialog }
+   With Dialog^ Do Begin
+     R.Assign(3, 2, Size.X - 2, Size.Y - 3);          { Assign screen area }
+     FormatStr(S, Msg, Params^);                      { Format the message }
+     Control := New(PStaticText, Init(R, S));         { Create static text }
+     Insert(Control);                                 { Insert the text }
+     X := -2;                                         { Set initial value }
+     ButtonCount := 0;                                { Clear button count }
+     For I := 0 To 3 Do
+       If (AOptions AND ($0100 SHL I) <> 0) Then Begin
+         R.Assign(0, 0, 10, 2);                       { Assign screen area }
+         Control := New(PButton, Init(R, ButtonName[I],
+           Commands[i], bfNormal));                   { Create button }
+         Inc(X, Control^.Size.X + 2);                 { Adjust position }
+         ButtonList[ButtonCount] := Control;          { Add to button list }
+         Inc(ButtonCount);                            { Inc button count }
+       End;
+     X := (Size.X - X) SHR 1;                         { Calc x position }
+     If (ButtonCount > 0) Then
+       For I := 0 To ButtonCount - 1 Do Begin         { For each button }
+        Control := ButtonList[I];                     { Transfer button }
+        Insert(Control);                              { Insert button }
+        Control^.MoveTo(X, Size.Y - 3);               { Position button }
+        Inc(X, Control^.Size.X + 2);                  { Adjust position }
+       End;
+     SelectNext(False);                               { Select first button }
+   End;
+   If (AOptions AND mfInsertInApp = 0) Then
+     MessageBoxRect := DeskTop^.ExecView(Dialog) Else { Execute dialog }
+     MessageBoxRect := Application^.ExecView(Dialog); { Execute dialog }
+   Dispose(Dialog, Done);                             { Dispose of dialog }
+END;
+
+{---------------------------------------------------------------------------}
+{  InputBox -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION InputBox(Const Title, ALabel: String; Var S: String;
+  Limit: Byte): Word;
+VAR R: TRect;
+BEGIN
+   R.Assign(0, 0, 60, 8);                             { Assign screen area }
+   R.Move((Desktop^.Size.X - R.B.X) DIV 2,
+     (Desktop^.Size.Y - R.B.Y) DIV 2);                { Position area }
+   InputBox := InputBoxRect(R, Title, ALabel, S,
+     Limit);                                          { Create input box }
+END;
+
+{---------------------------------------------------------------------------}
+{  InputBoxRect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Sep99 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION InputBoxRect(Var Bounds: TRect; Const Title, ALabel: String;
+  Var S: String; Limit: Byte): Word;
+VAR C: Word; R: TRect; Control: PView; Dialog: PDialog;
+BEGIN
+   Dialog := New(PDialog, Init(Bounds, Title));       { Create dialog }
+   With Dialog^ Do Begin
+     R.Assign(4 + CStrLen(ALabel), 2, Size.X - 3, 3); { Assign screen area }
+     Control := New(PInputLine, Init(R, Limit));      { Create input line }
+     Insert(Control);                                 { Insert input line }
+     R.Assign(2, 2, 3 + CStrLen(ALabel), 3);          { Assign screen area }
+     Insert(New(PLabel, Init(R, ALabel, Control)));   { Insert label }
+     R.Assign(Size.X - 24, Size.Y - 4, Size.X - 14,
+       Size.Y - 2);                                   { Assign screen area }
+     Insert(New(PButton, Init(R, 'O~K~', cmOk,
+       bfDefault)));                                  { Insert okay button }
+     Inc(R.A.X, 12);                                  { New start x position }
+     Inc(R.B.X, 12);                                  { New end x position }
+     Insert(New(PButton, Init(R, 'Cancel', cmCancel,
+       bfNormal)));                                   { Insert cancel button }
+     Inc(R.A.X, 12);                                  { New start x position }
+     Inc(R.B.X, 12);                                  { New end x position }
+     SelectNext(False);                               { Select first button }
+   End;
+   Dialog^.SetData(S);                                { Set data in dialog }
+   C := DeskTop^.ExecView(Dialog);                    { Execute the dialog }
+   If (C <> cmCancel) Then Dialog^.GetData(S);        { Get data from dialog }
+   Dispose(Dialog, Done);                             { Dispose of dialog }
+   InputBoxRect := C;                                 { Return execute result }
+END;
+
+END.

+ 342 - 0
fv/platform.inc

@@ -0,0 +1,342 @@
+{***************[ PLATFORM INCLUDE UNIT ]******************}
+{                                                          }
+{    System independent INCLUDE file to sort PLATFORMS     }
+{                                                          }
+{    Parts Copyright (c) 1997 by Balazs Scheidler          }
+{    [email protected]                                     }
+{                                                          }
+{    Parts Copyright (c) 1999 by Leon de Boer              }
+{    [email protected]  - primary e-mail address       }
+{    [email protected] - backup e-mail address        }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                 - C'T patch to BP         (16 Bit)       }
+{        LINUX    - FPC 0.9912+             (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date      Who    Fix                           }
+{  -------  --------  ---    ----------------------------  }
+{  0.1     02 Jul 97  Bazsi  Initial implementation        }
+{  0.2     28 Aug 97  LdB    Fixed OS2 platform sort       }
+{  0.3     29 Aug 97  LdB    Added assembler type changes  }
+{  0.4     29 Aug 97  LdB    OS_DOS removed from WINDOWS   }
+{  0.5     23 Oct 97  LdB    Delphi & speed compilers      }
+{  0.6     05 May 98  LdB    Virtual Pascal 2.0 added      }
+{  0.7     19 May 98  LdB    Delphi 2/3 definitions added  }
+{  0.8     06 Aug 98  CEC    FPC only support fixed WIN32  }
+{  0.9     10 Aug 98  LdB    BP_VMTLink def/Undef added    }
+{  1.0     27 Aug 98  LdB    Atari, Mac etc not undef dos  }
+{  1.1     25 Oct 98  PfV    Delphi 4 definitions added    }
+{  1.2     06 Jun 99  LdB    Sybil 2.0 support added       }
+{  1.3     13 Jun 99  LdB    Sybil 2.0 undef BP_VMT link   }
+{  1.31    03 Nov 99  LdB    FPC windows defines WIN32     }
+{  1.32    04 Nov 99  LdB    Delphi 5 definitions added    }
+{**********************************************************}
+
+{ ****************************************************************************
+
+   This include file defines some conditional defines to allow us to select
+   the compiler/platform/target in a consequent way.
+
+    OS_XXXX         The operating system used (XXXX may be one of:
+                       DOS, OS2, Linux, Windows, Go32)
+    PPC_XXXX        The compiler used: BP, FPK, Virtual, Speed
+    BIT_XX          The number of bits of the target platform: 16 or 32
+    PROC_XXXX       The mode of the target processor (Real or Protected)
+                    This shouldn't be used, except for i386 specific parts.
+    ASM_XXXX        This is the assembler type: BP, ISO-ANSI, FPK
+
+ ****************************************************************************
+
+    This is how the IFDEF and UNDEF statements below should translate.
+
+
+ PLATFORM  SYSTEM    COMPILER  COMP ID      CPU MODE        BITS    ASSEMBLER
+ --------  ------    --------  -------      --------        ----    ---------
+
+ DOS      OS_DOS      BP/TP7   PPC_BP       PROC_Real       BIT_16  ASM_BP
+
+ DPMI     OS_DOS      BP/TP7   PPC_BP       PROC_Protected  BIT_16  ASM_BP
+                      FPC      PPC_FPC      PROC_Protected  BIT_32  ASM_FPC
+
+ LINUX    OS_LINUX    FPC      PPC_FPC      PROC_Protected  BIT_32  ASM_FPC
+
+ WINDOWS  OS_WINDOWS  BP/TP7   PPC_BP       PROC_Protected  BIT_16  ASM_BP
+                      DELPHI   PPC_DELPHI   PROC_Protected  BIT_16  ASM_BP
+                      DELPHI2  PPC_DELPHI2  PROC_Protected  BIT_16  ASM_BP
+
+ WIN95/NT OS_WINDOWS  DELPHI2  PPC_DELPHI2  PROC_Protected  BIT_32  ASM_BP
+                      DELPHI3  PPC_DELPHI3  PROC_Protected  BIT_32  ASM_BP
+                      DELPHI4  PPC_DELPHI3  PROC_Protected  BIT_32  ASM_BP
+                      DELPHI5  PPC_DELPHI3  PROC_Protected  BIT_32  ASM_BP
+                      VIRTUAL  PPC_VIRTUAL  PROC_Protected  BIT 32  ASM_BP
+                      SYBIL2   PPC_SPEED    PROC_Protected  BIT_32  ASM_BP
+                      FPC      PPC_FPC      PROC_Protected  BIT_32  ASM_FPC
+
+ OS2      OS_OS2      BPOS2    PPC_BPOS2    PROC_Protected  BIT_16  ASM_BP
+                      VIRTUAL  PPC_VIRTUAL  PROC_Protected  BIT_32  ASM_BP
+                      SPEED    PPC_SPEED    PROC_Protected  BIT_32  ASM_BP
+                      SYBIL2   PPC_SPEED    PROC_Protected  BIT_32  ASM_BP
+                      FPC      PPC_FPC      PROC_Protected  BIT_32  ASM_FPC
+ ****************************************************************************}
+{****************************************************************************
+
+FOR ALL COMPILERS BP_VMTLink defined but FPC and Delphi3/Delphi4 undefine it
+
+ ****************************************************************************}
+{****************************************************************************
+
+FOR FPC THESE ARE THE TRANSLATIONS
+
+  PLATFORM  SYSTEM    COMPILER  HANDLE SIZE      ASM          CPU
+ --------  ------    --------  -----------      ----         ---
+
+ DOS      OS_DOS,OS_GO32 FPC     32-bit         AT&T         CPU86
+
+ WIN32    OS_WINDOWS   FPC     32-bit           AT&T         ----
+
+ LINUX    OS_LINUX     FPC     32-bit           AT&T         ----
+
+ OS2      OS_OS2       FPC     ?????            AT&T         CPU86
+
+ ATARI    OS_ATARI     FPC     32-bit           Internal     CPU68
+
+ MACOS    OS_MAC       FPC     ?????            Internal     CPU68
+
+ AMIGA    OS_AMIGA     FPC     32-bit           Internal     CPU68
+
+ ****************************************************************************}
+
+{---------------------------------------------------------------------------}
+{  Initial assume BORLAND 16 BIT DOS COMPILER - Updated 27Aug98 LdB         }
+{---------------------------------------------------------------------------}
+{$DEFINE OS_DOS}
+{$DEFINE PROC_Real}
+{$DEFINE BIT_16}
+{$DEFINE PPC_BP}
+{$DEFINE ASM_BP}
+{$DEFINE BP_VMTLink}
+{$DEFINE CPU86}
+
+{---------------------------------------------------------------------------}
+{  BORLAND 16 BIT DPMI changes protected mode - Updated 27Aug98 LdB         }
+{---------------------------------------------------------------------------}
+{$IFDEF DPMI}
+  {$UNDEF PROC_Real}
+  {$DEFINE PROC_Protected}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FPC 32 BIT COMPILER changes ASM, 32 bits etc - Updated 27Aug98 LdB       }
+{---------------------------------------------------------------------------}
+{$IFDEF FPC}
+  {$UNDEF PROC_Real}
+  {$DEFINE PROC_Protected}
+  {$UNDEF BIT_16}
+  {$DEFINE BIT_32}
+  {$UNDEF PPC_BP}
+  {$DEFINE PPC_FPC}
+  {$UNDEF ASM_BP}
+  {$DEFINE ASM_FPC}
+  {$UNDEF BP_VMTLink}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FPC LINUX COMPILER changes operating system - Updated 27Aug98 LdB        }
+{  Note: Other linux compilers would need to change other details           }
+{---------------------------------------------------------------------------}
+{$IFDEF LINUX}
+  {$UNDEF OS_DOS}
+  {$DEFINE OS_LINUX}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FPC GO32V2 COMPILER changes operating system - Updated 27Aug98 LdB       }
+{---------------------------------------------------------------------------}
+{$IFDEF GO32V2}
+  {$DEFINE OS_GO32}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  32 BIT WINDOWS COMPILERS changes bit size - Updated 27Aug98 LdB          }
+{---------------------------------------------------------------------------}
+{$IFDEF WIN32}
+  {$IFNDEF WINDOWS}
+    {$DEFINE WINDOWS}
+  {$ENDIF}
+  {$UNDEF BIT_16}
+  {$DEFINE BIT_32}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  WINDOWS COMPILERS change op system and proc mode - Updated 03Nov99 LdB   }
+{---------------------------------------------------------------------------}
+{$IFDEF WINDOWS}
+  {$UNDEF OS_DOS}
+  {$DEFINE OS_WINDOWS}
+  {$UNDEF PROC_Real}
+  {$DEFINE PROC_Protected}
+  {$IFDEF FPC}
+    {$DEFINE WIN32}
+  {$ENDIF}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  DELPHI1 COMPILER changes compiler type - Updated 27Aug98 LdB             }
+{---------------------------------------------------------------------------}
+{$IFDEF VER80}
+  {$UNDEF PPC_BP}
+  {$DEFINE PPC_DELPHI}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  DELPHI2 COMPILER changes compiler type - Updated 27Aug98 LdB             }
+{---------------------------------------------------------------------------}
+{$IFDEF VER90}
+  {$UNDEF PPC_BP}
+  {$DEFINE PPC_DELPHI}
+  {$DEFINE PPC_DELPHI2}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  DELPHI3 COMPILER changes compiler type - Updated 27Aug98 LdB             }
+{---------------------------------------------------------------------------}
+{$IFDEF VER100}
+  {$UNDEF PPC_BP}
+  {$DEFINE PPC_DELPHI}
+  {$DEFINE PPC_DELPHI3}
+  {$UNDEF BP_VMTLink}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  DELPHI4 COMPILER changes compiler type - Updated 25Oct98 pfv             }
+{---------------------------------------------------------------------------}
+{$IFDEF VER120}
+  {$UNDEF PPC_BP}
+  {$DEFINE PPC_DELPHI}
+  {$DEFINE PPC_DELPHI3}
+  {$DEFINE PPC_DELPHI4}
+  {$UNDEF BP_VMTLink}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  DELPHI5 COMPILER changes compiler type - Updated 04Nov99 pfv             }
+{---------------------------------------------------------------------------}
+{$IFDEF VER130}
+  {$UNDEF PPC_BP}
+  {$DEFINE PPC_DELPHI}
+  {$DEFINE PPC_DELPHI3}
+  {$DEFINE PPC_DELPHI4}
+  {$DEFINE PPC_DELPHI5}
+  {$UNDEF BP_VMTLink}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  OS2 COMPILERS change compiler type and mode - Updated 27Aug98 LdB        }
+{  Note: Assumes BPOS2 16BIT OS2 patch except for FPC which undefines this  }
+{---------------------------------------------------------------------------}
+{$IFDEF OS2}
+  {$UNDEF OS_DOS}
+  {$DEFINE OS_OS2}
+  {$UNDEF PROC_Real}
+  {$DEFINE PROC_Protected}
+  {$UNDEF PPC_BP}
+  {$DEFINE PPC_BPOS2}
+  {$IFDEF FPC}
+    {$UNDEF PPC_BPOS2}
+  {$ENDIF}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  VIRTUAL PASCAL changes compiler type/32 bit - Updated 27Aug98 LdB        }
+{  Note: VP2 can compile win 32 code so changes op system as needed         }
+{---------------------------------------------------------------------------}
+{$IFDEF VirtualPascal}
+  {$UNDEF BIT_16}
+  {$DEFINE BIT_32}
+  {$IFDEF PPC_BPOS2}
+    {$UNDEF PPC_BPOS2}
+  {$ENDIF}
+  {$DEFINE PPC_VIRTUAL}
+  {$IFDEF WIN32}
+    {$UNDEF PPC_BP}
+    {$UNDEF OS_OS2}
+    {$DEFINE OS_WINDOWS}
+  {$ENDIF}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  SPEED COMPILER changes compiler type/32 bit  - Updated 27Aug98 LdB       }
+{---------------------------------------------------------------------------}
+{$IFDEF Speed}
+  {$UNDEF BIT_16}
+  {$DEFINE BIT_32}
+  {$UNDEF PPC_BPOS2}
+  {$DEFINE PPC_SPEED}
+  {$UNDEF BP_VMTLink}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FPC AMIGA COMPILER changes op system and CPU type - Updated 27Aug98 LdB  }
+{---------------------------------------------------------------------------}
+{$IFDEF AMIGA}
+  {$UNDEF OS_DOS}
+  {$DEFINE OS_AMIGA}
+  {$IFDEF CPU86}
+    {$UNDEF CPU86}
+  {$ENDIF}
+  {$IFNDEF CPU68}
+    {$DEFINE CPU68}
+  {$ENDIF}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FPC ATARI COMPILER changes op system and CPU type - Updated 27Aug98 LdB  }
+{---------------------------------------------------------------------------}
+{$IFDEF ATARI}
+  {$UNDEF OS_DOS}
+  {$DEFINE OS_ATARI}
+  {$IFDEF CPU86}
+    {$UNDEF CPU86}
+  {$ENDIF}
+  {$IFNDEF CPU68}
+    {$DEFINE CPU68}
+  {$ENDIF}
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  FPC MAC COMPILER changes op system and CPU type - Updated 27Aug98 LdB    }
+{---------------------------------------------------------------------------}
+{$IFDEF MACOS}
+  {$UNDEF OS_DOS}
+  {$DEFINE OS_MAC}
+  {$IFDEF CPU86}
+    {$UNDEF CPU86}
+  {$ENDIF}
+  {$IFNDEF CPU68}
+    {$DEFINE CPU68}
+  {$ENDIF}
+{$ENDIF}
+

+ 422 - 0
fv/time.pas

@@ -0,0 +1,422 @@
+{*********************[ TIME UNIT ]************************}
+{                                                          }
+{             System independent TIME unit                 }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail address        }
+{   [email protected] - backup e-mail address         }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                 - Speed Pascal 1.0+       (32 Bit)       }
+{                 - C'T patch to BP         (16 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     06 Dec 96   First multi platform release.      }
+{  1.10     06 Jul 97   New functiions added.              }
+{  1.20     22 Jul 97   FPC pascal compiler added.         }
+{  1.30     29 Aug 97   Platform.inc sort added.           }
+{  1.40     13 Oct 97   Delphi 2/3 32 bit code added.      }
+{  1.50     06 Nov 97   Speed pascal code added.           }
+{  1.60     05 May 98   Virtual pascal 2.0 compiler added. }
+{  1.61     07 Jul 99   Speedsoft SYBIL 2.0 code added.    }
+{**********************************************************}
+
+UNIT Time;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC} { FPC doesn't support these switches }
+   {$F-} { Short calls are okay }
+   {$A+} { Word Align Data }
+   {$B-} { Allow short circuit boolean evaluations }
+   {$O+} { This unit may be overlaid }
+   {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+   {$E+} {  Emulation is on }
+   {$N-} {  No 80x87 code generation }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{-CurrentMinuteOfDay-------------------------------------------------
+Returns the number of minutes since midnight of a current system time.
+19Jun97 LdB               (Range: 0 - 1439)
+---------------------------------------------------------------------}
+FUNCTION CurrentMinuteOfDay: Word;
+
+{-CurrentSecondOfDay-------------------------------------------------
+Returns the number of seconds since midnight of current system time.
+24Jun97 LdB               (Range: 0 - 86399)
+---------------------------------------------------------------------}
+FUNCTION CurrentSecondOfDay: LongInt;
+
+{-CurrentSec100OfDay-------------------------------------------------
+Returns the 1/100ths of a second since midnight of current system time.
+24Jun97 LdB               (Range: 0 - 8639999)
+---------------------------------------------------------------------}
+FUNCTION CurrentSec100OfDay: LongInt;
+
+{-MinuteOfDay--------------------------------------------------------
+Returns the number of minutes since midnight of a valid given time.
+19Jun97 LdB               (Range: 0 - 1439)
+---------------------------------------------------------------------}
+FUNCTION MinuteOfDay (Hour24, Minute: Word): Word;
+
+{-SecondOfDay--------------------------------------------------------
+Returns the number of seconds since midnight of a valid given time.
+19Jun97 LdB               (Range: 0 - 86399)
+---------------------------------------------------------------------}
+FUNCTION SecondOfDay (Hour24, Minute, Second: Word): LongInt;
+
+{-SetTime------------------------------------------------------------
+Set the operating systems time clock to the given values. If values
+are invalid this function will fail without notification.
+06Nov97 LdB
+---------------------------------------------------------------------}
+PROCEDURE SetTime (Hour, Minute, Second, Sec100: Word);
+
+{-GetTime------------------------------------------------------------
+Returns the current time settings of the operating system.
+06Nov97 LdB
+---------------------------------------------------------------------}
+PROCEDURE GetTime (Var Hour, Minute, Second, Sec100: Word);
+
+{-MinutesToTime------------------------------------------------------
+Returns the time in hours and minutes of a given number of minutes.
+19Jun97 LdB
+---------------------------------------------------------------------}
+PROCEDURE MinutesToTime (Md: LongInt; Var Hour24, Minute: Word);
+
+{-SecondsToTime------------------------------------------------------
+Returns the time in hours, mins and secs of a given number of seconds.
+19Jun97 LdB
+---------------------------------------------------------------------}
+PROCEDURE SecondsToTime (Sd: LongInt; Var Hour24, Minute, Second: Word);
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+
+  {$IFNDEF PPC_SPEED}                                 { NON SPEED COMPILER }
+    {$IFDEF PPC_FPC}                                  { FPC WINDOWS COMPILER }
+    USEs Windows;                                     { Standard unit }
+    {$ELSE}                                           { OTHER COMPILERS }
+    USES WinTypes, WinProcs;                          { Standard units }
+    {$ENDIF}
+  {$ELSE}                                             { SPEEDSOFT COMPILER }
+  USES WinBase;                                       { Standard unit }
+  TYPE TSystemTime = SystemTime;                      { Type fix up }
+  {$ENDIF}
+
+{$ENDIF}
+
+{$IFDEF OS_OS2}                                       { OS2 COMPILERS }
+
+  {$IFDEF PPC_VIRTUAL}                                { VIRTUAL PASCAL }
+  USES OS2Base;                                       { Standard unit }
+  {$ENDIF}
+
+  {$IFDEF PPC_SPEED}                                  { SPEED PASCAL }
+  USES BseDos, Os2Def;                                { Standard unit }
+  {$ENDIF}
+
+  {$IFDEF PPC_BPOS2}                                  { C'T PATCH TO BP CODE }
+  USES DosTypes, DosProcs;                            { Standard unit }
+
+  TYPE DateTime = TDateTime;                          { Type correction }
+  {$ENDIF}
+
+{$ENDIF}
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{  CurrentMinuteOfDay -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24Jun97 LdB}
+{---------------------------------------------------------------------------}
+FUNCTION CurrentMinuteOfDay: Word;
+VAR Hour, Minute, Second, Sec100: Word;
+BEGIN
+   GetTime(Hour, Minute, Second, Sec100);             { Get current time }
+   CurrentMinuteOfDay := (Hour * 60) + Minute;        { Minute from midnight }
+END;
+
+{---------------------------------------------------------------------------}
+{  CurrentSecondOfDay -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24Jun97 LdB}
+{---------------------------------------------------------------------------}
+FUNCTION CurrentSecondOfDay: LongInt;
+VAR Hour, Minute, Second, Sec100: Word;
+BEGIN
+   GetTime(Hour, Minute, Second, Sec100);             { Get current time }
+   CurrentSecondOfDay := (LongInt(Hour) * 3600) +
+     (Minute * 60) + Second;                          { Second from midnight }
+END;
+
+{---------------------------------------------------------------------------}
+{  CurrentSec100OfDay -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24Jun97 LdB}
+{---------------------------------------------------------------------------}
+FUNCTION CurrentSec100OfDay: LongInt;
+VAR Hour, Minute, Second, Sec100: Word;
+BEGIN
+   GetTime(Hour, Minute, Second, Sec100);             { Get current time }
+   CurrentSec100OfDay := (LongInt(Hour) * 360000) +
+     (LongInt(Minute) * 6000) + (Second*100)+ Sec100; { Sec100 from midnight }
+END;
+
+{---------------------------------------------------------------------------}
+{  MinuteOfDay -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19Jun97 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION MinuteOfDay (Hour24, Minute: Word): Word;
+BEGIN
+   MinuteOfDay := (Hour24 * 60) + Minute;             { Minute from midnight }
+END;
+
+{---------------------------------------------------------------------------}
+{  SecondOfDay -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19Jun97 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION SecondOfDay (Hour24, Minute, Second: Word): LongInt;
+BEGIN
+   SecondOfDay := (LongInt(Hour24) * 3600) +
+     (Minute * 60) + Second;                          { Second from midnight }
+END;
+
+{---------------------------------------------------------------------------}
+{  SetTime -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Nov97 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE SetTime (Hour, Minute, Second, Sec100: Word);
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOV CH, BYTE PTR Hour;                           { Fetch hour }
+     MOV CL, BYTE PTR Minute;                         { Fetch minute }
+     MOV DH, BYTE PTR Second;                         { Fetch second }
+     MOV DL, BYTE PTR Sec100;                         { Fetch hundredths }
+     MOV AX, $2D00;                                   { Set function id }
+     PUSH BP;                                         { Safety save register }
+     INT $21;                                         { Set the time }
+     POP BP;                                          { Restore register }
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   BEGIN
+   ASM
+     MOVB Hour, %CH;                                  { Fetch hour }
+     MOVB Minute, %CL;                                { Fetch minute }
+     MOVB Second, %DH;                                { Fetch second }
+     MOVB Sec100, %DL;                                { Fetch hundredths }
+     MOVW $0x2D00H, %AX;                              { Set function id }
+     PUSHL %EBP;                                      { Save register }
+     INT $0x21H;                                      { BIOS set time }
+     POPL %EBP;                                       { Restore register }
+   END;
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOWS CODE }
+   ASSEMBLER;
+   ASM
+     MOV CH, BYTE PTR Hour;                           { Fetch hour }
+     MOV CL, BYTE PTR Minute;                         { Fetch minute }
+     MOV DH, BYTE PTR Second;                         { Fetch second }
+     MOV DL, BYTE PTR Sec100;                         { Fetch hundredths }
+     MOV AX, $2D00;                                   { Set function id }
+     PUSH BP;                                         { Safety save register }
+     INT $21;                                         { Set the time }
+     POP BP;                                          { Restore register }
+   END;
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   VAR DT: TSystemTime;
+   BEGIN
+     {$IFDEF PPC_FPC}                                 { FPC WINDOWS COMPILER }
+     GetSystemTime(@DT);                              { Get the date/time }
+     {$ELSE}                                          { OTHER COMPILERS }
+     GetSystemTime(DT);                               { Get the date/time }
+     {$ENDIF}
+     DT.wHour := Hour;                                { Transfer hour }
+     DT.wMinute := Minute;                            { Transfer minute }
+     DT.wSecond := Second;                            { Transfer seconds }
+     DT.wMilliseconds := Sec100 * 10;                 { Transfer millisecs }
+     SetSystemTime(DT);                               { Set the date/time }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+VAR DT: DateTime;
+BEGIN
+   DosGetDateTime(DT);                                { Get the date/time }
+   DT.Hours := Hour;                                  { Transfer hour }
+   DT.Minutes := Minute;                              { Transfer minute }
+   DT.Seconds := Second;                              { Transfer seconds }
+   DT.Hundredths := Sec100;                           { Transfer hundredths }
+   DosSetDateTime(DT);                                { Set the time }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  GetTime -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Nov97 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE GetTime (Var Hour, Minute, Second, Sec100: Word);
+{$IFDEF OS_DOS}                                       { DOS/DPMI CODE }
+   {$IFDEF ASM_BP}                                    { BP COMPATABLE ASM }
+   ASSEMBLER;
+   ASM
+     MOV AX, $2C00;                                   { Set function id }
+     PUSH BP;                                         { Safety save register }
+     INT $21;                                         { System get time }
+     POP BP;                                          { Restore register }
+     XOR AH, AH;                                      { Clear register }
+     CLD;                                             { Strings go forward }
+     MOV AL, DL;                                      { Transfer register }
+     LES DI, Sec100;                                  { ES:DI -> hundredths }
+     STOSW;                                           { Return hundredths }
+     MOV AL, DH;                                      { Transfer register }
+     LES DI, Second;                                  { ES:DI -> seconds }
+     STOSW;                                           { Return seconds }
+     MOV AL, CL;                                      { Transfer register }
+     LES DI, Minute;                                  { ES:DI -> minutes }
+     STOSW;                                           { Return minutes }
+     MOV AL, CH;                                      { Transfer register }
+     LES DI, Hour;                                    { ES:DI -> hours }
+     STOSW;                                           { Return hours }
+   END;
+   {$ENDIF}
+   {$IFDEF ASM_FPC}                                   { FPC COMPATABLE ASM }
+   BEGIN
+   ASM
+     MOVW $0x2C00H, %AX;                              { Set function id }
+     PUSHL %EBP;                                      { Save register }
+     INT $0x21H;                                      { System get time }
+     POPL %EBP;                                       { Restore register }
+     XORB %AH, %AH;                                   { Clear register }
+     MOVB %DL, %AL;                                   { Transfer register }
+     MOVL Sec100, %EDI;                               { EDI -> Sec100 }
+     MOVW %AX, (%EDI);                                { Return Sec100 }
+     MOVB %DH, %AL;                                   { Transfer register }
+     MOVL Second, %EDI;                               { EDI -> Second }
+     MOVW %AX, (%EDI);                                { Return Second }
+     MOVB %CL, %AL;                                   { Transfer register }
+     MOVL Minute, %EDI;                               { EDI -> Minute }
+     MOVW %AX, (%EDI);                                { Return minute }
+     MOVB %CH, %AL;                                   { Transfer register }
+     MOVL Hour, %EDI;                                 { EDI -> Hour }
+     MOVW %AX, (%EDI);                                { Return hour }
+   END;
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOWS CODE }
+   ASSEMBLER;
+   ASM
+     MOV AX, $2C00;                                   { Set function id }
+     PUSH BP;                                         { Safety save register }
+     INT $21;                                         { System get time }
+     POP BP;                                          { Restore register }
+     XOR AH, AH;                                      { Clear register }
+     CLD;                                             { Strings go forward }
+     MOV AL, DL;                                      { Transfer register }
+     LES DI, Sec100;                                  { ES:DI -> hundredths }
+     STOSW;                                           { Return hundredths }
+     MOV AL, DH;                                      { Transfer register }
+     LES DI, Second;                                  { ES:DI -> seconds }
+     STOSW;                                           { Return seconds }
+     MOV AL, CL;                                      { Transfer register }
+     LES DI, Minute;                                  { ES:DI -> minutes }
+     STOSW;                                           { Return minutes }
+     MOV AL, CH;                                      { Transfer register }
+     LES DI, Hour;                                    { ES:DI -> hours }
+     STOSW;                                           { Return hours }
+   END;
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   VAR DT: TSystemTime;
+   BEGIN
+     {$IFDEF PPC_FPC}                                 { FPC WINDOWS COMPILER }
+     GetSystemTime(@DT);                              { Get the date/time }
+     {$ELSE}                                          { OTHER COMPILERS }
+     GetSystemTime(DT);                               { Get the date/time }
+     {$ENDIF}
+     Hour := DT.wHour;                                { Transfer hour }
+     Minute := DT.wMinute;                            { Transfer minute }
+     Second := DT.wSecond;                            { Transfer seconds }
+     Sec100 := DT.wMilliseconds DIV 10;               { Transfer hundredths }
+   END;
+   {$ENDIF}
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+VAR DT: DateTime;
+BEGIN
+   DosGetDateTime(DT);                                { Get the date/time }
+   Hour   := DT.Hours;                                { Transfer hour }
+   Minute := DT.Minutes;                              { Transfer minute }
+   Second := DT.Seconds;                              { Transfer seconds }
+   Sec100 := DT.Hundredths;                           { Transfer hundredths }
+END;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{  MinutesToTime -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19Jun97 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE MinutesToTime (Md: LongInt; Var Hour24, Minute: Word);
+BEGIN
+   Hour24 := Md DIV 60;                               { Hours of time }
+   Minute := Md MOD 60;                               { Minutes of time }
+END;
+
+{---------------------------------------------------------------------------}
+{  SecondsToTime -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19Jun97 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE SecondsToTime (Sd: LongInt; Var Hour24, Minute, Second: Word);
+BEGIN
+   Hour24 := Sd DIV 3600;                             { Hours of time }
+   Minute := Sd MOD 3600 DIV 60;                      { Minutes of time }
+   Second := Sd MOD 60;                               { Seconds of time }
+END;
+
+END.

+ 1056 - 0
fv/validate.pas

@@ -0,0 +1,1056 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{   System independent GRAPHICAL clone of VALIDATE.PAS     }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]                                        }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     12 Jun 96   Initial DOS/DPMI code released.    }
+{  1.10     29 Aug 97   Platform.inc sort added.           }
+{  1.20     13 Oct 97   Delphi3 32 bit code added.         }
+{  1.30     11 May 98   Virtual pascal 2.0 code added.     }
+{  1.40     10 Jul 99   Sybil 2.0 code added               }
+{  1.41     03 Nov 99   FPC windows code added             }
+{**********************************************************}
+
+UNIT Validate;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F-} { Short calls are okay }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES Common, Objects;                                 { GFV standard units }
+
+{***************************************************************************}
+{                              PUBLIC CONSTANTS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                         VALIDATOR STATUS CONSTANTS                        }
+{---------------------------------------------------------------------------}
+CONST
+   vsOk     = 0;                                      { Validator ok }
+   vsSyntax = 1;                                      { Validator sytax err }
+
+{---------------------------------------------------------------------------}
+{                           VALIDATOR OPTION MASKS                          }
+{---------------------------------------------------------------------------}
+CONST
+   voFill     = $0001;                                { Validator fill }
+   voTransfer = $0002;                                { Validator transfer }
+   voOnAppend = $0004;                                { Validator append }
+   voReserved = $00F8;                                { Clear above flags }
+
+{***************************************************************************}
+{                            RECORD DEFINITIONS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                        VALIDATOR TRANSFER CONSTANTS                       }
+{---------------------------------------------------------------------------}
+TYPE
+   TVTransfer = (vtDataSize, vtSetData, vtGetData);   { Transfer states }
+
+{---------------------------------------------------------------------------}
+{                    PICTURE VALIDATOR RESULT CONSTANTS                     }
+{---------------------------------------------------------------------------}
+TYPE
+   TPicResult = (prComplete, prIncomplete, prEmpty, prError, prSyntax,
+     prAmbiguous, prIncompNoFill);
+
+{***************************************************************************}
+{                            OBJECT DEFINITIONS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                TValidator OBJECT - VALIDATOR ANCESTOR OBJECT              }
+{---------------------------------------------------------------------------}
+TYPE
+   TValidator = OBJECT (TObject)
+         Status : Word;                               { Validator status }
+         Options: Word;                               { Validator options }
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION Valid(CONST S: String): Boolean;
+      FUNCTION IsValid (CONST S: String): Boolean; Virtual;
+      FUNCTION IsValidInput (Var S: String;
+        SuppressFill: Boolean): Boolean; Virtual;
+      FUNCTION Transfer (Var S: String; Buffer: Pointer;
+        Flag: TVTransfer): Word; Virtual;
+      PROCEDURE Error; Virtual;
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PValidator = ^TValidator;
+
+{---------------------------------------------------------------------------}
+{           TPictureValidator OBJECT - PICTURE VALIDATOR OBJECT             }
+{---------------------------------------------------------------------------}
+TYPE
+   TPXPictureValidator = OBJECT (TValidator)
+         Pic: PString;                                { Picture filename }
+      CONSTRUCTOR Init (Const APic: String; AutoFill: Boolean);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION IsValid (Const S: String): Boolean; Virtual;
+      FUNCTION IsValidInput (Var S: String;
+        SuppressFill: Boolean): Boolean; Virtual;
+      FUNCTION Picture (Var Input: String;
+        AutoFill: Boolean): TPicResult; Virtual;
+      PROCEDURE Error; Virtual;
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PPXPictureValidator = ^TPXPictureValidator;
+
+TYPE CharSet = TCharSet;
+
+{---------------------------------------------------------------------------}
+{            TFilterValidator OBJECT - FILTER VALIDATOR OBJECT              }
+{---------------------------------------------------------------------------}
+TYPE
+   TFilterValidator = OBJECT (TValidator)
+         ValidChars: CharSet;                         { Valid char set }
+      CONSTRUCTOR Init (AValidChars: CharSet);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION IsValid (CONST S: String): Boolean; Virtual;
+      FUNCTION IsValidInput (Var S: String;
+        SuppressFill: Boolean): Boolean; Virtual;
+      PROCEDURE Error; Virtual;
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PFilterValidator = ^TFilterValidator;
+
+{---------------------------------------------------------------------------}
+{             TRangeValidator OBJECT - RANGE VALIDATOR OBJECT               }
+{---------------------------------------------------------------------------}
+TYPE
+   TRangeValidator = OBJECT (TFilterValidator)
+         Min: LongInt;                                { Min valid value }
+         Max: LongInt;                                { Max valid value }
+      CONSTRUCTOR Init(AMin, AMax: LongInt);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION IsValid (Const S: String): Boolean; Virtual;
+      FUNCTION Transfer (Var S: String; Buffer: Pointer;
+        Flag: TVTransfer): Word; Virtual;
+      PROCEDURE Error; Virtual;
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PRangeValidator = ^TRangeValidator;
+
+{---------------------------------------------------------------------------}
+{            TLookUpValidator OBJECT - LOOKUP VALIDATOR OBJECT              }
+{---------------------------------------------------------------------------}
+TYPE
+   TLookupValidator = OBJECT (TValidator)
+      FUNCTION IsValid (Const S: String): Boolean;                   Virtual;
+      FUNCTION Lookup (Const S: String): Boolean;                    Virtual;
+   END;
+   PLookupValidator = ^TLookupValidator;
+
+{---------------------------------------------------------------------------}
+{      TStringLookUpValidator OBJECT - STRING LOOKUP VALIDATOR OBJECT       }
+{---------------------------------------------------------------------------}
+TYPE
+   TStringLookupValidator = OBJECT (TLookupValidator)
+         Strings: PStringCollection;
+      CONSTRUCTOR Init (AStrings: PStringCollection);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done;                                               Virtual;
+      FUNCTION Lookup (Const S: String): Boolean;                    Virtual;
+      PROCEDURE Error;                                               Virtual;
+      PROCEDURE NewStringList (AStrings: PStringCollection);
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PStringLookupValidator = ^TStringLookupValidator;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           OBJECT REGISTER ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{-RegisterValidate---------------------------------------------------
+Calls RegisterType for each of the object types defined in this unit.
+18May98 LdB
+---------------------------------------------------------------------}
+PROCEDURE RegisterValidate;
+
+{***************************************************************************}
+{                           OBJECT REGISTRATION                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                 TPXPictureValidator STREAM REGISTRATION                   }
+{---------------------------------------------------------------------------}
+CONST
+   RPXPictureValidator: TStreamRec = (
+     ObjType: 80;                                     { Register id = 80 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TPXPictureValidator)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TPXPictureValidator);
+     {$ENDIF}
+     Load: @TPXPictureValidator.Load;                 { Object load method }
+     Store: @TPXPictureValidator.Store                { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                  TFilterValidator STREAM REGISTRATION                     }
+{---------------------------------------------------------------------------}
+CONST
+   RFilterValidator: TStreamRec = (
+     ObjType: 81;                                     { Register id = 81 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TFilterValidator)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TFilterValidator);
+     {$ENDIF}
+     Load: @TFilterValidator.Load;                    { Object load method }
+     Store: @TFilterValidator.Store                   { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                   TRangeValidator STREAM REGISTRATION                     }
+{---------------------------------------------------------------------------}
+CONST
+   RRangeValidator: TStreamRec = (
+     ObjType: 82;                                     { Register id = 82 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TRangeValidator)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TRangeValidator);
+     {$ENDIF}
+     Load: @TRangeValidator.Load;                     { Object load method }
+     Store: @TRangeValidator.Store                    { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                TStringLookupValidator STREAM REGISTRATION                 }
+{---------------------------------------------------------------------------}
+CONST
+   RStringLookupValidator: TStreamRec = (
+     ObjType: 83;                                     { Register id = 83 }
+     {$IFDEF BP_VMTLink}                              { BP style VMT link }
+     VmtLink: Ofs(TypeOf(TStringLookupValidator)^);
+     {$ELSE}                                          { Alt style VMT link }
+     VmtLink: TypeOf(TStringLookupValidator);
+     {$ENDIF}
+     Load: @TStringLookupValidator.Load;              { Object load method }
+     Store: @TStringLookupValidator.Store             { Object store method }
+   );
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+USES MsgBox;                                          { GFV standard unit }
+
+{***************************************************************************}
+{                              PRIVATE ROUTINES                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{  IsNumber -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION IsNumber (Chr: Char): Boolean;
+BEGIN
+   If (Chr >= '0') AND (Chr <= '9') Then              { Check if '0..9' }
+     IsNumber := True Else IsNumber := False;         { Return result }
+END;
+
+{---------------------------------------------------------------------------}
+{  IsLetter -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION IsLetter (Chr: Char): Boolean;
+BEGIN
+   Chr := Char(Ord(Chr) AND $DF);                     { Lower to upper case }
+   If (Chr >= 'A') AND (Chr <='Z') Then               { Check if A..Z }
+     IsLetter := True Else IsLetter := False;         { Return result }
+END;
+
+{---------------------------------------------------------------------------}
+{  IsComplete -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION IsComplete (Rslt: TPicResult): Boolean;
+BEGIN
+   IsComplete := Rslt IN [prComplete, prAmbiguous];   { Return if complete }
+END;
+
+{---------------------------------------------------------------------------}
+{  IsInComplete -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION IsIncomplete (Rslt: TPicResult): Boolean;
+BEGIN
+   IsIncomplete := Rslt IN
+     [prIncomplete, prIncompNoFill];                  { Return if incomplete }
+END;
+
+{---------------------------------------------------------------------------}
+{  NumChar -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION NumChar (Chr: Char; Const S: String): Byte;
+VAR I, Total: Byte;
+BEGIN
+   Total := 0;                                        { Zero total }
+   For I := 1 To Length(S) Do                         { For entire string }
+     If (S[I] = Chr) Then Inc(Total);                 { Count matches of Chr }
+   NumChar := Total;                                  { Return char count }
+END;
+
+{---------------------------------------------------------------------------}
+{  IsSpecial -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION IsSpecial (Chr: Char; Const Special: String): Boolean;
+VAR Rslt: Boolean; I: Byte;
+BEGIN
+   Rslt := False;                                     { Preset false result }
+   For I := 1 To Length(Special) Do
+     If (Special[I] = Chr) Then Rslt := True;         { Character found }
+   IsSpecial := Rslt;                                 { Return result }
+END;
+
+{***************************************************************************}
+{                               OBJECT METHODS                              }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                         TValidator OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TValidator---------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TValidator.Load (Var S:TStream);
+BEGIN
+   Inherited Init;                                    { Call ancestor }
+   S.Read(Options, 2);                                { Read option masks }
+END;
+
+{--TValidator---------------------------------------------------------------}
+{  Valid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION TValidator.Valid (Const S: String): Boolean;
+BEGIN
+   Valid := False;                                    { Preset false result }
+   If Not IsValid(S) Then Error                       { Check for error }
+     Else Valid := True;                              { Return valid result }
+END;
+
+{--TValidator---------------------------------------------------------------}
+{  IsValid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TValidator.IsValid (Const S: String): Boolean;
+BEGIN
+   IsValid := True;                                   { Default return valid }
+END;
+
+{--TValidator---------------------------------------------------------------}
+{  IsValidInput -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION TValidator.IsValidInput (Var S: String; SuppressFill: Boolean): Boolean;
+BEGIN
+   IsValidInput := True;                              { Default return true }
+END;
+
+{--TValidator---------------------------------------------------------------}
+{  Transfer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TValidator.Transfer (Var S: String; Buffer: Pointer;
+  Flag: TVTransfer): Word;
+BEGIN
+   Transfer := 0;                                     { Default return zero }
+END;
+
+{--TValidator---------------------------------------------------------------}
+{  Error -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TValidator.Error;
+BEGIN                                                 { Abstract method }
+END;
+
+{--TValidator---------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TValidator.Store (Var S: TStream);
+BEGIN
+   S.Write(Options, 2);                               { Write options }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                    TPXPictureValidator OBJECT METHODS                     }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TPXPictureValidator------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TPXPictureValidator.Init (Const APic: String; AutoFill: Boolean);
+VAR S: String;
+BEGIN
+   Inherited Init;                                    { Call ancestor }
+   Pic := NewStr(APic);                               { Hold filename }
+   Options := voOnAppend;                             { Preset option mask }
+   If AutoFill Then Options := Options OR voFill;     { Check/set fill mask }
+   S := '';                                           { Create empty string }
+   If (Picture(S, False) <> prEmpty) Then             { Check for empty }
+     Status := vsSyntax;                              { Set error mask }
+END;
+
+{--TPXPictureValidator------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TPXPictureValidator.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   Pic := S.ReadStr;                                  { Read filename }
+END;
+
+{--TPXPictureValidator------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TPXPictureValidator.Done;
+BEGIN
+   If (Pic <> Nil) Then DisposeStr(Pic);              { Dispose of filename }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TPXPictureValidator------------------------------------------------------}
+{  IsValid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TPXPictureValidator.IsValid (Const S: String): Boolean;
+VAR Str: String; Rslt: TPicResult;
+BEGIN
+   Str := S;                                          { Transfer string }
+   Rslt := Picture(Str, False);                       { Check for picture }
+   IsValid := (Pic = nil) OR (Rslt = prComplete) OR
+     (Rslt = prEmpty);                                { Return result }
+END;
+
+{--TPXPictureValidator------------------------------------------------------}
+{  IsValidInput -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION TPXPictureValidator.IsValidInput (Var S: String;
+  SuppressFill: Boolean): Boolean;
+BEGIN
+   IsValidInput := (Pic = Nil) OR (Picture(S,
+    (Options AND voFill <> 0)  AND NOT SuppressFill)
+     <> prError);                                     { Return input result }
+END;
+
+{--TPXPictureValidator------------------------------------------------------}
+{  Picture -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TPXPictureValidator.Picture (Var Input: String; AutoFill: Boolean): TPicResult;
+VAR I, J: Byte; Rslt: TPicResult; Reprocess: Boolean;
+
+   FUNCTION Process (TermCh: Byte): TPicResult;
+   VAR Rslt: TPicResult; Incomp: Boolean; OldI, OldJ, IncompJ, IncompI: Byte;
+
+     PROCEDURE Consume (Ch: Char);
+     BEGIN
+       Input[J] := Ch;                                { Return character }
+       Inc(J);                                        { Inc count J }
+       Inc(I);                                        { Inc count I }
+     END;
+
+     PROCEDURE ToGroupEnd (Var I: Byte);
+     VAR BrkLevel, BrcLevel: Integer;
+     BEGIN
+       BrkLevel := 0;                                 { Zero bracket level }
+       BrcLevel := 0;                                 { Zero bracket level }
+       Repeat
+         If (I <> TermCh) Then Begin                  { Not end }
+           Case Pic^[I] Of
+             '[': Inc(BrkLevel);                      { Inc bracket level }
+             ']': Dec(BrkLevel);                      { Dec bracket level }
+             '{': Inc(BrcLevel);                      { Inc bracket level }
+             '}': Dec(BrcLevel);                      { Dec bracket level }
+             ';': Inc(I);                             { Next character }
+             '*': Begin
+                 Inc(I);                              { Next character }
+                 While IsNumber(Pic^[I]) Do Inc(I);   { Search for text }
+                 ToGroupEnd(I);                       { Move to group end }
+                 Continue;                            { Now continue }
+               End;
+           End;
+           Inc(I);                                    { Next character }
+         End;
+       Until ((BrkLevel = 0) AND (BrcLevel = 0)) OR   { Both levels must be 0 }
+       (I = TermCh);                                  { Terminal character }
+     END;
+
+     FUNCTION SkipToComma: Boolean;
+     BEGIN
+       Repeat
+         ToGroupEnd(I);                               { Find group end }
+       Until (I = TermCh) OR (Pic^[I] = ',');         { Terminator found }
+       If (Pic^[I] = ',') Then Inc(I);                { Comma so continue }
+       SkipToComma := (I < TermCh);                   { Return result }
+     END;
+
+     FUNCTION CalcTerm: Byte;
+     VAR K: Byte;
+     BEGIN
+       K := I;                                        { Hold count }
+       ToGroupEnd(K);                                 { Find group end }
+       CalcTerm := K;                                 { Return count }
+     END;
+
+     FUNCTION Iteration: TPicResult;
+     VAR Itr, K, L: Byte; Rslt: TPicResult; NewTermCh: Byte;
+     BEGIN
+       Itr := 0;                                      { Zero iteration }
+       Iteration := prError;                          { Preset error result }
+       Inc(I);                                        { Skip '*' character }
+       While (IsNumber(Pic^[I])) Do Begin             { Entry is a number }
+         Itr := Itr * 10 + Byte(Pic^[I]) - Byte('0'); { Convert to number }
+         Inc(I);                                      { Next character }
+       End;
+       If (I <= TermCh) Then Begin                    { Not end of name }
+         K := I;                                      { Hold count }
+         NewTermCh := CalcTerm;                       { Calc next terminator }
+         If (Itr <> 0) Then Begin
+           For L := 1 To Itr Do Begin                 { For each character }
+             I := K;                                  { Reset count }
+             Rslt := Process(NewTermCh);              { Process new entry }
+             If (NOT IsComplete(Rslt)) Then Begin     { Not empty }
+               If (Rslt = prEmpty) Then               { Check result }
+                 Rslt := prIncomplete;                { Return incomplete }
+               Iteration := Rslt;                     { Return result }
+               Exit;                                  { Now exit }
+             End;
+           End;
+         End Else Begin
+           Repeat
+             I := K;                                  { Hold count }
+             Rslt := Process(NewTermCh);              { Process new entry }
+           Until (NOT IsComplete(Rslt));              { Until complete }
+           If (Rslt = prEmpty) OR (Rslt = prError)    { Check for any error }
+           Then Begin
+             Inc(I);                                  { Next character }
+             Rslt := prAmbiguous;                     { Return result }
+           End;
+         End;
+         I := NewTermCh;                              { Find next name }
+       End Else Rslt := prSyntax;                     { Completed }
+       Iteration := Rslt;                             { Return result }
+     END;
+
+     FUNCTION Group: TPicResult;
+     VAR Rslt: TPicResult; TermCh: Byte;
+     BEGIN
+       TermCh := CalcTerm;                            { Calc new term }
+       Inc(I);                                        { Next character }
+       Rslt := Process(TermCh - 1);                   { Process the name }
+       If (NOT IsIncomplete(Rslt)) Then I := TermCh;  { Did not complete }
+       Group := Rslt;                                 { Return result }
+     END;
+
+     FUNCTION CheckComplete (Rslt: TPicResult): TPicResult;
+     VAR J: Byte;
+     BEGIN
+       J := I;                                        { Hold count }
+       If IsIncomplete(Rslt) Then Begin               { Check if complete }
+         While True Do
+           Case Pic^[J] Of
+             '[': ToGroupEnd(J);                      { Find name end }
+             '*': If (IsNumber(Pic^[J + 1]) = False)
+               Then Begin
+                 Inc(J);                              { Next name }
+                 ToGroupEnd(J);                       { Find name end }
+               End Else Break;
+             Else Break;
+           End;
+         If (J = TermCh) Then Rslt := prAmbiguous;    { End of name }
+       End;
+       CheckComplete := Rslt;                         { Return result }
+     END;
+
+     FUNCTION Scan: TPicResult;
+     VAR Ch: Char; Rslt: TPicResult;
+     BEGIN
+       Scan := prError;                               { Preset return error }
+       Rslt := prEmpty;                               { Preset empty result }
+       While (I <> TermCh) AND (Pic^[I] <> ',')       { For each entry }
+       Do Begin
+         If (J > Length(Input)) Then Begin            { Move beyond length }
+           Scan := CheckComplete(Rslt);               { Return result }
+           Exit;                                      { Now exit }
+         End;
+         Ch := Input[J];                              { Fetch character }
+         Case Pic^[I] of
+           '#': If (NOT IsNumber(Ch)) Then Exit       { Check is a number }
+               Else Consume(Ch);                      { Transfer number }
+           '?': If (NOT IsLetter(Ch)) Then Exit       { Check is a letter }
+               Else Consume(Ch);                      { Transfer character }
+           '&': If (NOT IsLetter(Ch)) Then Exit       { Check is a letter }
+               Else Consume(UpCase(Ch));              { Transfer character }
+           '!': Consume(UpCase(Ch));                  { Transfer character }
+           '@': Consume(Ch);                          { Transfer character }
+           '*': Begin
+             Rslt := Iteration;                       { Now re-iterate }
+             If (NOT IsComplete(Rslt)) Then Begin     { Check not complete }
+               Scan := Rslt;                          { Return result }
+               Exit;                                  { Now exit }
+             End;
+             If (Rslt = prError) Then                 { Check for error }
+               Rslt := prAmbiguous;                   { Return ambiguous }
+           End;
+           '{': Begin
+             Rslt := Group;                           { Return group }
+             If (NOT IsComplete(Rslt)) Then Begin     { Not incomplete check }
+               Scan := Rslt;                          { Return result }
+               Exit;                                  { Now exit }
+             End;
+           End;
+           '[': Begin
+             Rslt := Group;                           { Return group }
+             If IsIncomplete(Rslt) Then Begin         { Incomplete check }
+               Scan := Rslt;                          { Return result }
+               Exit;                                  { Now exit }
+             End;
+             If (Rslt = prError) Then                 { Check for error }
+               Rslt := prAmbiguous;                   { Return ambiguous }
+           End;
+           Else If Pic^[I] = ';' Then Inc(I);         { Move fwd for follow }
+           If (UpCase(Pic^[I]) <> UpCase(Ch)) Then    { Characters differ }
+             If (Ch = ' ') Then Ch := Pic^[I]         { Ignore space }
+             Else Exit;
+           Consume(Pic^[I]);                          { Consume character }
+         End; { Case }
+         If (Rslt = prAmbiguous) Then                 { If ambiguous result }
+           Rslt := prIncompNoFill                     { Set incomplete fill }
+           Else Rslt := prIncomplete;                 { Set incomplete }
+       End;{ While}
+       If (Rslt = prIncompNoFill) Then                { Check incomp fill }
+         Scan := prAmbiguous Else                     { Return ambiguous }
+         Scan := prComplete;                          { Return completed }
+     END;
+
+   BEGIN
+     Incomp := False;                                 { Clear incomplete }
+     OldI := I;                                       { Hold I count }
+     OldJ := J;                                       { Hold J count }
+     Repeat
+       Rslt := Scan;                                  { Scan names }
+       If (Rslt IN [prComplete, prAmbiguous]) AND
+       Incomp AND (J < IncompJ) Then Begin            { Check if complete }
+         Rslt := prIncomplete;                        { Return result }
+         J := IncompJ;                                { Return position }
+       End;
+       If ((Rslt = prError) OR (Rslt = prIncomplete)) { Check no errors }
+       Then Begin
+         Process := Rslt;                             { Hold result }
+         If ((NOT Incomp) AND (Rslt = prIncomplete))  { Check complete }
+         Then Begin
+           Incomp := True;                            { Set incomplete }
+           IncompI := I;                              { Set current position }
+           IncompJ := J;                              { Set current position }
+         End;
+         I := OldI;                                   { Restore held value }
+         J := OldJ;                                   { Restore held value }
+         If (NOT SkipToComma) Then Begin              { Check not comma }
+           If Incomp Then Begin                       { Check incomplete }
+             Process := prIncomplete;                 { Set incomplete mask }
+             I := IncompI;                            { Hold incomp position }
+             J := IncompJ;                            { Hold incomp position }
+           End;
+           Exit;                                      { Now exit }
+         End;
+         OldI := I;                                   { Hold position }
+       End;
+     Until (Rslt <> prError) AND                      { Check for error }
+       (Rslt <> prIncomplete);                        { Incomplete load }
+     If (Rslt = prComplete) AND Incomp Then           { Complete load }
+       Process := prAmbiguous Else                    { Return completed }
+       Process := Rslt;                               { Return result }
+   END;
+
+   FUNCTION SyntaxCheck: Boolean;
+   VAR I, BrkLevel, BrcLevel: Integer;
+   Begin
+     SyntaxCheck := False;                            { Preset false result }
+     If (Pic^ <> '') AND (Pic^[Length(Pic^)] <> ';')  { Name is valid }
+     AND ((Pic^[Length(Pic^)] = '*') AND
+     (Pic^[Length(Pic^) - 1] <> ';') = False)         { Not wildcard list }
+     Then Begin
+       I := 1;                                        { Set count to 1 }
+       BrkLevel := 0;                                 { Zero bracket level }
+       BrcLevel := 0;                                 { Zero bracket level }
+       While (I <= Length(Pic^)) Do Begin             { For each character }
+         Case Pic^[I] Of
+           '[': Inc(BrkLevel);                        { Inc bracket level }
+           ']': Dec(BrkLevel);                        { Dec bracket level }
+           '{': Inc(BrcLevel);                        { Inc bracket level }
+           '}': Dec(BrcLevel);                        { Dec bracket level }
+           ';': Inc(I);                               { Next character }
+         End;
+         Inc(I);                                      { Next character }
+       End;
+       If (BrkLevel = 0) AND (BrcLevel = 0) Then      { Check both levels 0 }
+         SyntaxCheck := True;                         { Return true syntax }
+     End;
+   End;
+
+BEGIN
+   Picture := prSyntax;                               { Preset error default }
+   If SyntaxCheck Then Begin                          { Check syntax }
+     Picture := prEmpty;                              { Preset picture empty }
+     If (Input <> '') Then Begin                      { We have an input }
+       J := 1;                                        { Set J count to 1 }
+       I := 1;                                        { Set I count to 1 }
+       Rslt := Process(Length(Pic^) + 1);             { Set end of name }
+       If (Rslt <> prError) AND (Rslt <> prSyntax) AND
+        (J <= Length(Input)) Then Rslt := prError;    { Check for any error }
+       If (Rslt = prIncomplete) AND AutoFill          { Check autofill flags }
+       Then Begin
+         Reprocess := False;                          { Set reprocess false }
+         while (I <= Length(Pic^)) AND (NOT           { Not at end of name }
+         IsSpecial(Pic^[I], '#?&!@*{}[],'#0))         { No special chars }
+         DO Begin
+           If Pic^[I] = ';' Then Inc(I);              { Check for next mark }
+           Input := Input + Pic^[I];                  { Move to that name }
+           Inc(I);                                    { Inc count }
+           Reprocess := True;                         { Set reprocess flag }
+         End;
+         J := 1;                                      { Set J count to 1 }
+         I := 1;                                      { Set I count to 1 }
+         If Reprocess Then                            { Check for reprocess }
+           Rslt := Process(Length(Pic^) + 1);         { Move to next name }
+       End;
+       If (Rslt = prAmbiguous) Then                   { Result ambiguous }
+         Picture := prComplete Else                   { Return completed }
+         If (Rslt = prInCompNoFill) Then              { Result incomplete }
+           Picture := prIncomplete Else               { Return incomplete }
+             Picture := Rslt;                         { Return result }
+     End;
+   End;
+END;
+
+{--TPXPictureValidator------------------------------------------------------}
+{  Error -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TPXPictureValidator.Error;
+CONST PXErrMsg = 'Input does not conform to picture:';
+VAR S: String;
+BEGIN
+   If (Pic <> Nil) Then S := Pic^ Else S := 'No name';{ Transfer filename }
+   MessageBox(PxErrMsg + #13' %s', @S,  mfError OR
+     mfOKButton);                                     { Message box }
+END;
+
+{--TPXPictureValidator------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TPXPictureValidator.Store (Var S: TStream);
+BEGIN
+  TValidator.Store(S);                                { TValidator.store call }
+  S.WriteStr(Pic);                                    { Write filename }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                     TFilterValidator OBJECT METHODS                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TFilterValidator---------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TFilterValidator.Init (AValidChars: CharSet);
+BEGIN
+   Inherited Init;                                    { Call ancestor }
+   ValidChars := AValidChars;                         { Hold valid char set }
+END;
+
+{--TFilterValidator---------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TFilterValidator.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(ValidChars, SizeOf(TCharSet));              { Read valid char set }
+END;
+
+{--TFilterValidator---------------------------------------------------------}
+{  IsValid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TFilterValidator.IsValid (Const S: String): Boolean;
+VAR I: Integer;
+BEGIN
+   I := 1;                                            { Start at position 1 }
+   While S[I] In ValidChars Do Inc(I);                { Check each char }
+   If (I > Length(S)) Then IsValid := True Else       { All characters valid }
+     IsValid := False;                                { Invalid characters }
+END;
+
+{--TFilterValidator---------------------------------------------------------}
+{  IsValidInput -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION TFilterValidator.IsValidInput (Var S: String; SuppressFill: Boolean): Boolean;
+VAR I: Integer;
+BEGIN
+   I := 1;                                            { Start at position 1 }
+   While S[I] In ValidChars Do Inc(I);                { Check each char }
+   If (I > Length(S)) Then IsValidInput := True       { All characters valid }
+     Else IsValidInput := False;                      { Invalid characters }
+END;
+
+{--TFilterValidator---------------------------------------------------------}
+{  Error -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TFilterValidator.Error;
+CONST PXErrMsg = 'Invalid character in input';
+BEGIN
+   MessageBox(PXErrMsg, Nil, mfError OR mfOKButton);  { Show error message }
+END;
+
+{--TFilterValidator---------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TFilterValidator.Store (Var S: TStream);
+BEGIN
+   TValidator.Store(S);                               { TValidator.Store call }
+   S.Write(ValidChars, SizeOf(TCharSet));             { Write valid char set }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                      TRangeValidator OBJECT METHODS                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TRangeValidator----------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TRangeValidator.Init (AMin, AMax: LongInt);
+BEGIN
+   Inherited Init(['0'..'9','+','-']);                { Call ancestor }
+   If (AMin >= 0) Then                                { Check min value > 0 }
+     ValidChars := ValidChars - ['-'];                { Is so no negatives }
+   Min := AMin;                                       { Hold min value }
+   Max := AMax;                                       { Hold max value }
+END;
+
+{--TRangeValidator----------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TRangeValidator.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(Min, 4);                                    { Read min value }
+   S.Read(Max, 4);                                    { Read max value }
+END;
+
+{--TRangeValidator----------------------------------------------------------}
+{  IsValid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TRangeValidator.IsValid (Const S: String): Boolean;
+VAR Value: LongInt; Code: Sw_Integer;
+BEGIN
+   IsValid := False;                                  { Preset false result }
+   If Inherited IsValid(S) Then Begin                 { Call ancestor }
+     Val(S, Value, Code);                             { Convert to number }
+     If (Value >= Min) AND (Value <= Max)             { With valid range }
+       AND (Code = 0) Then IsValid := True;           { No illegal chars }
+   End;
+END;
+
+{--TRangeValidator----------------------------------------------------------}
+{  Transfer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TRangeValidator.Transfer (Var S: String; Buffer: Pointer; Flag: TVTransfer): Word;
+VAR Value: LongInt; Code: Sw_Integer;
+BEGIN
+   If (Options AND voTransfer <> 0) Then Begin        { Tranfer mask set }
+     Transfer := SizeOf(Value);                       { Transfer a longint }
+     Case Flag Of
+       vtGetData: Begin
+         Val(S, Value, Code);                         { Convert s to number }
+         LongInt(Buffer^) := Value;                   { Transfer result }
+       End;
+       vtSetData: Str(LongInt(Buffer^), S);           { Convert to string s }
+     End;
+   End Else Transfer := 0;                            { No transfer = zero }
+END;
+
+{--TRangeValidator----------------------------------------------------------}
+{  Error -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TRangeValidator.Error;
+CONST PXErrMsg = 'Value not in the range';
+VAR Params: Array[0..1] Of Longint;
+BEGIN
+   Params[0] := Min;                                  { Transfer min value }
+   Params[1] := Max;                                  { Transfer max value }
+   MessageBox(PXErrMsg+' %d to %d', @Params,
+     mfError OR mfOKButton);                          { Display message }
+END;
+
+{--TRangeValidator----------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TRangeValidator.Store (Var S: TStream);
+BEGIN
+   TFilterValidator.Store(S);                         { TFilterValidator.Store }
+   S.Write(Min, 4);                                   { Write min value }
+   S.Write(Max, 4);                                   { Write max value }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                      TLookUpValidator OBJECT METHODS                      }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TLookUpValidator---------------------------------------------------------}
+{  IsValid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TLookUpValidator.IsValid (Const S: String): Boolean;
+BEGIN
+   IsValid := LookUp(S);                              { Check for string }
+END;
+
+{--TLookUpValidator---------------------------------------------------------}
+{  LookUp -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB            }
+{---------------------------------------------------------------------------}
+FUNCTION TLookupValidator.Lookup (Const S: String): Boolean;
+BEGIN
+   Lookup := True;                                    { Default return true }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                   TStringLookUpValidator OBJECT METHODS                   }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TStringLookUpValidator---------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TStringLookUpValidator.Init (AStrings: PStringCollection);
+BEGIN
+   Inherited Init;                                    { Call ancestor }
+   Strings := AStrings;                               { Hold string list }
+END;
+
+{--TStringLookUpValidator---------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TStringLookUpValidator.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   Strings := PStringCollection(S.Get);               { Fecth string list }
+END;
+
+{--TStringLookUpValidator---------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TStringLookUpValidator.Done;
+BEGIN
+   NewStringList(Nil);                                { Dispsoe string list }
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TStringLookUpValidator---------------------------------------------------}
+{  Lookup -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB            }
+{---------------------------------------------------------------------------}
+FUNCTION TStringLookUpValidator.Lookup (Const S: String): Boolean;
+VAR Index: Integer;
+BEGIN
+   Lookup := False;                                   { Preset false return }
+   If (Strings <> Nil) Then
+     Lookup := Strings^.Search(@S, Index);            { Search for string }
+END;
+
+{--TStringLookUpValidator---------------------------------------------------}
+{  Error -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TStringLookUpValidator.Error;
+CONST PXErrMsg = 'Input not in valid-list';
+BEGIN
+   MessageBox(PXErrMsg, Nil, mfError OR mfOKButton);  { Display message }
+END;
+
+{--TStringLookUpValidator---------------------------------------------------}
+{  NewStringList -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE TStringLookUpValidator.NewStringList (AStrings: PStringCollection);
+BEGIN
+   If (Strings <> Nil) Then Dispose(Strings, Done);   { Free old string list }
+   Strings := AStrings;                               { Hold new string list }
+END;
+
+{--TStringLookUpValidator---------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TStringLookUpValidator.Store (Var S: TStream);
+BEGIN
+   TLookupValidator.Store(S);                         { TlookupValidator call }
+   S.Put(Strings);                                    { Now store strings }
+END;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           OBJECT REGISTER ROUTINES                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  RegisterValidate -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 18May98 LdB  }
+{---------------------------------------------------------------------------}
+PROCEDURE RegisterValidate;
+BEGIN
+   RegisterType(RPXPictureValidator);                 { Register viewer }
+   RegisterType(RFilterValidator);                    { Register filter }
+   RegisterType(RRangeValidator);                     { Register validator }
+   RegisterType(RStringLookupValidator);              { Register str lookup }
+END;
+
+END.

+ 6626 - 0
fv/views.pas

@@ -0,0 +1,6626 @@
+{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
+{                                                          }
+{   System independent GRAPHICAL clone of VIEWS.PAS        }
+{                                                          }
+{   Interface Copyright (c) 1992 Borland International     }
+{                                                          }
+{   Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer   }
+{   [email protected]  - primary e-mail address        }
+{   [email protected] - backup e-mail address         }
+{                                                          }
+{****************[ THIS CODE IS FREEWARE ]*****************}
+{                                                          }
+{     This sourcecode is released for the purpose to       }
+{   promote the pascal language on all platforms. You may  }
+{   redistribute it and/or modify with the following       }
+{   DISCLAIMER.                                            }
+{                                                          }
+{     This SOURCE CODE is distributed "AS IS" WITHOUT      }
+{   WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR     }
+{   ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED.     }
+{                                                          }
+{*****************[ SUPPORTED PLATFORMS ]******************}
+{     16 and 32 Bit compilers                              }
+{        DOS      - Turbo Pascal 7.0 +      (16 Bit)       }
+{        DPMI     - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - FPC 0.9912+ (GO32V2)    (32 Bit)       }
+{        WINDOWS  - Turbo Pascal 7.0 +      (16 Bit)       }
+{                 - Delphi 1.0+             (16 Bit)       }
+{        WIN95/NT - Delphi 2.0+             (32 Bit)       }
+{                 - Virtual Pascal 2.0+     (32 Bit)       }
+{                 - Speedsoft Sybil 2.0+    (32 Bit)       }
+{                 - FPC 0.9912+             (32 Bit)       }
+{        OS2      - Virtual Pascal 1.0+     (32 Bit)       }
+{                                                          }
+{******************[ REVISION HISTORY ]********************}
+{  Version  Date        Fix                                }
+{  -------  ---------   ---------------------------------  }
+{  1.00     10 Nov 96   First multi platform release       }
+{  1.10     29 Aug 97   Platform.inc sort added.           }
+{  1.20     12 Sep 97   FPK pascal 0.92 conversion added.  }
+{  1.30     10 Jun 98   Virtual pascal 2.0 code added.     }
+{  1.40     10 Jul 99   Sybil 2.0 code added               }
+{  1.41     03 Nov 99   FPC Windows support added.         }
+{  1.50     26 Nov 99   Graphics stuff moved to GFVGraph   }
+{**********************************************************}
+
+UNIT Views;
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                                  INTERFACE
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{====Include file to sort compiler platform out =====================}
+{$I Platform.inc}
+{====================================================================}
+
+{==== Compiler directives ===========================================}
+
+{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
+  {$F+} { Force far calls - Used because of the FirstThat, ForNext ... }
+  {$A+} { Word Align Data }
+  {$B-} { Allow short circuit boolean evaluations }
+  {$O+} { This unit may be overlaid }
+  {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
+  {$P-} { Normal string variables }
+  {$N-} { No 80x87 code generation }
+  {$E+} { Emulation is on }
+{$ENDIF}
+
+{$X+} { Extended syntax is ok }
+{$R-} { Disable range checking }
+{$S-} { Disable Stack Checking }
+{$I-} { Disable IO Checking }
+{$Q-} { Disable Overflow Checking }
+{$V-} { Turn off strict VAR strings }
+{====================================================================}
+
+USES
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     {$IFNDEF PPC_SPEED}                              { NON SPEEDSOFT SYBIL2+ }
+       {$IFDEF PPC_FPC}                               { FPC WINDOWS COMPILER }
+         Windows,                                     { Standard unit }
+       {$ELSE}                                        { OTHER COMPILERS }
+         WinTypes, WinProcs,                          { Stardard units }
+       {$ENDIF}
+       {$IFDEF PPC_BP} Win31, {$ENDIF}                { Standard 3.1 unit }
+       {$IFDEF PPC_DELPHI} Messages, {$ENDIF}         { Delphi3+ unit }
+     {$ELSE}                                          { SPEEDSOFT SYBIL2+ }
+       WinBase, WinDef, WinUser, WinGDI,              { Standard unit }
+     {$ENDIF}
+   {$ENDIF}
+
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+     OS2Def, OS2Base, OS2PMAPI,                       { Standard units }
+   {$ENDIF}
+
+   Common, GFVGraph, Objects, Drivers;                { GFV standard units }
+
+{***************************************************************************}
+{                              PUBLIC CONSTANTS                             }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                              TView STATE MASKS                            }
+{---------------------------------------------------------------------------}
+CONST
+   sfVisible   = $0001;                               { View visible mask }
+   sfCursorVis = $0002;                               { Cursor visible }
+   sfCursorIns = $0004;                               { Cursor insert mode }
+   sfShadow    = $0008;                               { View has shadow }
+   sfActive    = $0010;                               { View is active }
+   sfSelected  = $0020;                               { View is selected }
+   sfFocused   = $0040;                               { View is focused }
+   sfDragging  = $0080;                               { View is dragging }
+   sfDisabled  = $0100;                               { View is disabled }
+   sfModal     = $0200;                               { View is modal }
+   sfDefault   = $0400;                               { View is default }
+   sfExposed   = $0800;                               { View is exposed }
+   sfIconised  = $1000;                               { View is iconised }
+
+{---------------------------------------------------------------------------}
+{                             TView OPTION MASKS                            }
+{---------------------------------------------------------------------------}
+CONST
+   ofSelectable  = $0001;                             { View selectable }
+   ofTopSelect   = $0002;                             { Top selectable }
+   ofFirstClick  = $0004;                             { First click react }
+   ofFramed      = $0008;                             { View is framed }
+   ofPreProcess  = $0010;                             { Pre processes }
+   ofPostProcess = $0020;                             { Post processes }
+   ofBuffered    = $0040;                             { View is buffered }
+   ofTileable    = $0080;                             { View is tileable }
+   ofCenterX     = $0100;                             { View centred on x }
+   ofCenterY     = $0200;                             { View centred on y }
+   ofCentered    = $0300;                             { View x,y centred }
+   ofValidate    = $0400;                             { View validates }
+   ofVersion     = $3000;                             { View TV version }
+   ofVersion10   = $0000;                             { TV version 1 view }
+   ofVersion20   = $1000;                             { TV version 2 view }
+   ofGFVModeView = $4000;                             { View is in GFV mode }
+
+{---------------------------------------------------------------------------}
+{                            TView GROW MODE MASKS                          }
+{---------------------------------------------------------------------------}
+CONST
+   gfGrowLoX = $01;                                   { Left side grow }
+   gfGrowLoY = $02;                                   { Top side grow  }
+   gfGrowHiX = $04;                                   { Right side grow }
+   gfGrowHiY = $08;                                   { Bottom side grow }
+   gfGrowAll = $0F;                                   { Grow on all sides }
+   gfGrowRel = $10;                                   { Grow relative }
+
+{---------------------------------------------------------------------------}
+{                           TView DRAG MODE MASKS                           }
+{---------------------------------------------------------------------------}
+CONST
+   dmDragMove = $01;                                  { Move view }
+   dmDragGrow = $02;                                  { Grow view }
+   dmLimitLoX = $10;                                  { Limit left side }
+   dmLimitLoY = $20;                                  { Limit top side }
+   dmLimitHiX = $40;                                  { Limit right side }
+   dmLimitHiY = $80;                                  { Limit bottom side }
+   dmLimitAll = $F0;                                  { Limit all sides }
+
+{---------------------------------------------------------------------------}
+{                      >> NEW << TView OPTION MASKS                         }
+{---------------------------------------------------------------------------}
+CONST
+   goThickFramed = $0001;                             { Thick framed mask }
+   goDrawFocus   = $0002;                             { Draw focus mask }
+   goTitled      = $0004;                             { Draw titled mask }
+   goTabSelect   = $0008;                             { Tab selectable }
+   goEveryKey    = $0020;                             { Report every key }
+   goEndModal    = $0040;                             { End modal }
+   goGraphView   = $1000;                             { Raw graphic view }
+
+   goGraphical   = $2000;                             { Graphical view }
+   goNativeClass = $4000;                             { Native class window }
+   goNoDrawView  = $8000;                             { View does not draw }
+
+{---------------------------------------------------------------------------}
+{                       >> NEW << TAB OPTION MASKS                          }
+{---------------------------------------------------------------------------}
+CONST
+   tmTab      = $01;                                  { Tab move mask }
+   tmShiftTab = $02;                                  { Shift+tab move mask }
+   tmEnter    = $04;                                  { Enter move mask }
+   tmLeft     = $08;                                  { Left arrow move mask }
+   tmRight    = $10;                                  { Right arrow move mask }
+   tmUp       = $20;                                  { Up arrow move mask }
+   tmDown     = $40;                                  { Down arrow move mask }
+
+{---------------------------------------------------------------------------}
+{                        >> NEW << VIEW DRAW MASKS                          }
+{---------------------------------------------------------------------------}
+CONST
+   vdBackGnd = $01;                                   { Draw backgound }
+   vdInner   = $02;                                   { Draw inner detail }
+   vdCursor  = $04;                                   { Draw cursor }
+   vdBorder  = $08;                                   { Draw view border }
+   vdFocus   = $10;                                   { Draw focus state }
+   vdNoChild = $20;                                   { Draw no children }
+
+{---------------------------------------------------------------------------}
+{                            TView HELP CONTEXTS                            }
+{---------------------------------------------------------------------------}
+CONST
+   hcNoContext = 0;                                   { No view context }
+   hcDragging  = 1;                                   { No drag context }
+
+{---------------------------------------------------------------------------}
+{                             TWindow FLAG MASKS                            }
+{---------------------------------------------------------------------------}
+CONST
+   wfMove  = $01;                                     { Window can move }
+   wfGrow  = $02;                                     { Window can grow }
+   wfClose = $04;                                     { Window can close }
+   wfZoom  = $08;                                     { Window can zoom }
+
+{---------------------------------------------------------------------------}
+{                              TWindow PALETTES                             }
+{---------------------------------------------------------------------------}
+CONST
+   wpBlueWindow = 0;                                  { Blue palette }
+   wpCyanWindow = 1;                                  { Cyan palette }
+   wpGrayWindow = 2;                                  { Gray palette }
+
+{---------------------------------------------------------------------------}
+{                              COLOUR PALETTES                              }
+{---------------------------------------------------------------------------}
+CONST
+   CFrame      = #1#1#2#2#3;                          { Frame palette }
+   CScrollBar  = #4#5#5;                              { Scrollbar palette }
+   CScroller   = #6#7;                                { Scroller palette }
+   CListViewer = #26#26#27#28#29;                     { Listviewer palette }
+
+   CBlueWindow = #8#9#10#11#12#13#14#15;              { Blue window palette }
+   CCyanWindow = #16#17#18#19#20#21#22#23;            { Cyan window palette }
+   CGrayWindow = #24#25#26#27#28#29#30#31;            { Grey window palette }
+
+{---------------------------------------------------------------------------}
+{                           TScrollBar PART CODES                           }
+{---------------------------------------------------------------------------}
+CONST
+   sbLeftArrow  = 0;                                  { Left arrow part }
+   sbRightArrow = 1;                                  { Right arrow part }
+   sbPageLeft   = 2;                                  { Page left part }
+   sbPageRight  = 3;                                  { Page right part }
+   sbUpArrow    = 4;                                  { Up arrow part }
+   sbDownArrow  = 5;                                  { Down arrow part }
+   sbPageUp     = 6;                                  { Page up part }
+   sbPageDown   = 7;                                  { Page down part }
+   sbIndicator  = 8;                                  { Indicator part }
+
+{---------------------------------------------------------------------------}
+{              TScrollBar OPTIONS FOR TWindow.StandardScrollBar             }
+{---------------------------------------------------------------------------}
+CONST
+   sbHorizontal     = $0000;                          { Horz scrollbar }
+   sbVertical       = $0001;                          { Vert scrollbar }
+   sbHandleKeyboard = $0002;                          { Handle keyboard }
+
+{---------------------------------------------------------------------------}
+{                            STANDARD COMMAND CODES                         }
+{---------------------------------------------------------------------------}
+CONST
+   cmValid   = 0;                                     { Valid command }
+   cmQuit    = 1;                                     { Quit command }
+   cmError   = 2;                                     { Error command }
+   cmMenu    = 3;                                     { Menu command }
+   cmClose   = 4;                                     { Close command }
+   cmZoom    = 5;                                     { Zoom command }
+   cmResize  = 6;                                     { Resize command }
+   cmNext    = 7;                                     { Next view command }
+   cmPrev    = 8;                                     { Prev view command }
+   cmHelp    = 9;                                     { Help command }
+   cmOK      = 10;                                    { Okay command }
+   cmCancel  = 11;                                    { Cancel command }
+   cmYes     = 12;                                    { Yes command }
+   cmNo      = 13;                                    { No command }
+   cmDefault = 14;                                    { Default command }
+   cmCut     = 20;                                    { Clipboard cut cmd }
+   cmCopy    = 21;                                    { Clipboard copy cmd }
+   cmPaste   = 22;                                    { Clipboard paste cmd }
+   cmUndo    = 23;                                    { Clipboard undo cmd }
+   cmClear   = 24;                                    { Clipboard clear cmd }
+   cmTile    = 25;                                    { Tile subviews cmd }
+   cmCascade = 26;                                    { Cascade subviews cmd }
+   cmReceivedFocus     = 50;                          { Received focus }
+   cmReleasedFocus     = 51;                          { Released focus }
+   cmCommandSetChanged = 52;                          { Commands changed }
+   cmScrollBarChanged  = 53;                          { Scrollbar changed }
+   cmScrollBarClicked  = 54;                          { Scrollbar clicked on }
+   cmSelectWindowNum   = 55;                          { Select window }
+   cmListItemSelected  = 56;                          { Listview item select }
+
+   cmNotify = 27;
+   cmIdCommunicate     = 28;                          { Communicate via id }
+   cmIdSelect          = 29;                          { Select via id }
+
+{---------------------------------------------------------------------------}
+{                          TWindow NUMBER CONSTANTS                         }
+{---------------------------------------------------------------------------}
+CONST
+   wnNoNumber = 0;                                    { Window has no num }
+   MaxViewWidth = 132;                                { Max view width }
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+
+{$IFDEF BIT_16}                                       { WINDOWS 16 BIT CODE }
+{---------------------------------------------------------------------------}
+{              WIN16 LABEL CONSTANTS FOR WINDOW PROPERTY CALLS              }
+{---------------------------------------------------------------------------}
+CONST
+   ViewSeg = 'TVWINSEG'+#0;                           { View segment label }
+   ViewOfs = 'TVWINOFS'+#0;                           { View offset label }
+{$ENDIF}
+
+{$IFDEF BIT_32}                                       { WINDOWS 32 BIT CODE }
+{---------------------------------------------------------------------------}
+{             WIN32/NT LABEL CONSTANTS FOR WINDOW PROPERTY CALLS            }
+{---------------------------------------------------------------------------}
+CONST
+   ViewPtr = 'TVWINPTR'+#0;                           { View ptr label }
+{$ENDIF}
+
+{$ENDIF}
+
+{***************************************************************************}
+{                          PUBLIC TYPE DEFINITIONS                          }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                            TWindow Title string                           }
+{---------------------------------------------------------------------------}
+TYPE
+   TTitleStr = String[80];                            { Window title string }
+
+{---------------------------------------------------------------------------}
+{                            COMMAND SET RECORD                             }
+{---------------------------------------------------------------------------}
+TYPE
+   TCommandSet = SET OF Byte;                         { Command set record }
+   PCommandSet = ^TCommandSet;                        { Ptr to command set }
+
+{---------------------------------------------------------------------------}
+{                              PALETTE RECORD                               }
+{---------------------------------------------------------------------------}
+TYPE
+   TPalette = String;                                 { Palette record }
+   PPalette = ^TPalette;                              { Pointer to palette }
+
+{---------------------------------------------------------------------------}
+{                            TDrawBuffer RECORD                             }
+{---------------------------------------------------------------------------}
+TYPE
+   TDrawBuffer = Array [0..MaxViewWidth - 1] Of Word; { Draw buffer record }
+   PDrawBuffer = ^TDrawBuffer;                        { Ptr to draw buffer }
+
+{---------------------------------------------------------------------------}
+{                           TVideoBuffer RECORD                             }
+{---------------------------------------------------------------------------}
+TYPE
+   TVideoBuf = ARRAY [0..3999] of Word;               { Video buffer }
+   PVideoBuf = ^TVideoBuf;                            { Pointer to buffer }
+
+{---------------------------------------------------------------------------}
+{                            TComplexArea RECORD                            }
+{---------------------------------------------------------------------------}
+TYPE
+   PComplexArea = ^TComplexArea;                      { Complex area }
+   TComplexArea = PACKED RECORD
+      X1, Y1  : Integer;                              { Top left corner }
+      X2, Y2  : Integer;                              { Lower right corner }
+      NextArea: PComplexArea;                         { Next area pointer }
+   END;
+
+{***************************************************************************}
+{                        PUBLIC OBJECT DEFINITIONS                          }
+{***************************************************************************}
+
+TYPE
+   PGroup = ^TGroup;                                  { Pointer to group }
+
+{---------------------------------------------------------------------------}
+{                    TView OBJECT - ANCESTOR VIEW OBJECT                    }
+{---------------------------------------------------------------------------}
+   PView = ^TView;
+   TView = OBJECT (TObject)
+         GrowMode  : Byte;                            { View grow mode }
+         DragMode  : Byte;                            { View drag mode }
+         DrawMask  : Byte;                            { Draw masks }
+         TabMask   : Byte;                            { Tab move masks }
+         ColourOfs : Integer;                         { View palette offset }
+         HelpCtx   : Word;                            { View help context }
+         State     : Word;                            { View state masks }
+         Options   : Word;                            { View options masks }
+         EventMask : Word;                            { View event masks }
+         GOptions  : Word;                            { Graphics options }
+         Origin    : TPoint;                          { View origin }
+         Size      : TPoint;                          { View size }
+         Cursor    : TPoint;                          { Cursor position }
+         RawOrigin : TPoint;                          { View raw origin }
+         RawSize   : TPoint;                          { View raw size }
+         Next      : PView;                           { Next peerview }
+         Owner     : PGroup;                          { Owner group }
+         HoldLimit : PComplexArea;                    { Hold limit values }
+         {$IFDEF OS_WINDOWS}                          { WIN/NT DATA ONLY }
+         ExStyle   : LongInt;                         { Extended style }
+         Dc        : HDc;                             { Device context }
+         {$ENDIF}
+         {$IFDEF OS_OS2}                              { OS2 DATA ONLY }
+         lStyle    : LongInt;                         { Style }
+         Client    : HWnd;                            { Client handle }
+         Ps        : HPs;                             { Paint structure }
+         {$ENDIF}
+         {$IFNDEF OS_DOS}                             { WIN/NT/OS2 DATA ONLY }
+         FrameSize : Integer;                         { Frame size (X) }
+         CaptSize  : Integer;                         { Caption size (Y) }
+         HWindow   : HWnd;                            { Window handle }
+         {$ENDIF}
+      CONSTRUCTOR Init (Var Bounds: TRect);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION Prev: PView;
+      FUNCTION Execute: Word; Virtual;
+      FUNCTION Focus: Boolean;
+      FUNCTION DataSize: Word; Virtual;
+      FUNCTION TopView: PView;
+      FUNCTION PrevView: PView;
+      FUNCTION NextView: PView;
+      FUNCTION GetHelpCtx: Word; Virtual;
+      FUNCTION EventAvail: Boolean;
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION GetColor (Color: Word): Word;
+      FUNCTION Valid (Command: Word): Boolean; Virtual;
+      FUNCTION GetState (AState: Word): Boolean;
+      FUNCTION TextWidth (Txt: String): Integer;
+      FUNCTION MouseInView (Point: TPoint): Boolean;
+      FUNCTION CommandEnabled (Command: Word): Boolean;
+      FUNCTION OverLapsArea (X1, Y1, X2, Y2: Integer): Boolean;
+      FUNCTION MouseEvent (Var Event: TEvent; Mask: Word): Boolean;
+      PROCEDURE Hide;
+      PROCEDURE Show;
+      PROCEDURE Draw; Virtual;
+      PROCEDURE Select;
+      PROCEDURE Awaken; Virtual;
+      PROCEDURE DrawView;
+      PROCEDURE MakeFirst;
+      PROCEDURE DrawFocus; Virtual;
+      PROCEDURE DrawCursor; Virtual;
+      PROCEDURE DrawBorder; Virtual;
+      PROCEDURE HideCursor;
+      PROCEDURE ShowCursor;
+      PROCEDURE BlockCursor;
+      PROCEDURE NormalCursor;
+      PROCEDURE FocusFromTop; Virtual;
+      PROCEDURE SetViewLimits;
+      PROCEDURE DrawBackGround; Virtual;
+      PROCEDURE ReleaseViewLimits;
+      PROCEDURE MoveTo (X, Y: Integer);
+      PROCEDURE GrowTo (X, Y: Integer);
+      PROCEDURE SetDrawMask (Mask: Byte);
+      PROCEDURE EndModal (Command: Word); Virtual;
+      PROCEDURE SetCursor (X, Y: Integer);
+      PROCEDURE PutInFrontOf (Target: PView);
+      PROCEDURE DisplaceBy (Dx, Dy: Integer); Virtual;
+      PROCEDURE SetCommands (Commands: TCommandSet);
+      PROCEDURE ReDrawArea (X1, Y1, X2, Y2: Integer);
+      PROCEDURE EnableCommands (Commands: TCommandSet);
+      PROCEDURE DisableCommands (Commands: TCommandSet);
+      PROCEDURE SetState (AState: Word; Enable: Boolean); Virtual;
+      PROCEDURE SetCmdState (Commands: TCommandSet; Enable: Boolean);
+      PROCEDURE GetData (Var Rec); Virtual;
+      PROCEDURE SetData (Var Rec); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE Locate (Var Bounds: TRect);
+      PROCEDURE KeyEvent (Var Event: TEvent);
+      PROCEDURE GetEvent (Var Event: TEvent); Virtual;
+      PROCEDURE PutEvent (Var Event: TEvent); Virtual;
+      PROCEDURE GetExtent (Var Extent: TRect);
+      PROCEDURE GetBounds (Var Bounds: TRect);
+      PROCEDURE SetBounds (Var Bounds: TRect);
+      PROCEDURE GetClipRect (Var Clip: TRect);
+      PROCEDURE ClearEvent (Var Event: TEvent);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PROCEDURE ChangeBounds (Var Bounds: TRect); Virtual;
+      PROCEDURE SizeLimits (Var Min, Max: TPoint); Virtual;
+      PROCEDURE GetCommands (Var Commands: TCommandSet);
+      PROCEDURE GetPeerViewPtr (Var S: TStream; Var P);
+      PROCEDURE PutPeerViewPtr (Var S: TStream; P: PView);
+      PROCEDURE CalcBounds (Var Bounds: TRect; Delta: TPoint); Virtual;
+      {$IFNDEF OS_DOS}                                { WIN/NT/OS2 CODE }
+      FUNCTION GetClassId: LongInt; Virtual;
+      FUNCTION GetClassName: String; Virtual;
+      FUNCTION GetClassText: String; Virtual;
+      FUNCTION GetClassAttr: LongInt; Virtual;
+      FUNCTION GetNotifyCmd: LongInt; Virtual;
+      FUNCTION GetMsgHandler: Pointer; Virtual;
+      {$ENDIF}
+
+
+
+      FUNCTION Exposed: Boolean;   { This needs help!!!!! }
+      PROCEDURE GraphLine (X1, Y1, X2, Y2: Integer; Colour: Byte);
+      PROCEDURE GraphRectangle (X1, Y1, X2, Y2: Integer; Colour: Byte);
+      PROCEDURE ClearArea (X1, Y1, X2, Y2: Integer; Colour: Byte);
+      PROCEDURE GraphArc (Xc, Yc: Integer; Sa, Ea: Real; XRad, YRad: Integer;
+        Colour: Byte);
+      PROCEDURE FilletArc (Xc, Yc: Integer; Sa, Ea: Real; XRad, YRad, Ht: Integer;
+        Colour: Byte);
+      PROCEDURE BicolorRectangle (X1, Y1, X2, Y2: Integer; Light, Dark: Byte;
+        Down: Boolean);
+      PROCEDURE WriteBuf (X, Y, W, H: Integer; Var Buf);
+      PROCEDURE WriteLine (X, Y, W, H: Integer; Var Buf);
+      PROCEDURE MakeLocal (Source: TPoint; Var Dest: TPoint);
+      PROCEDURE MakeGlobal (Source: TPoint; Var Dest: TPoint);
+      PROCEDURE WriteStr (X, Y: Integer; Str: String; Color: Byte);
+      PROCEDURE WriteChar (X, Y: Integer; C: Char; Color: Byte;
+        Count: Integer);
+      PROCEDURE DragView (Event: TEvent; Mode: Byte; Var Limits: TRect;
+        MinSize, MaxSize: TPoint);
+
+
+      FUNCTION FontWidth: Integer;
+      FUNCTION Fontheight: Integer;
+
+      {$IFNDEF OS_DOS}                                { WIN/NT/OS2 CODE }
+      PROCEDURE CreateWindowNow (CmdShow: Integer);                  Virtual;
+      {$ENDIF}
+   END;
+
+   SelectMode = (NormalSelect, EnterSelect, LeaveSelect);
+
+{---------------------------------------------------------------------------}
+{                  TGroup OBJECT - GROUP OBJECT ANCESTOR                    }
+{---------------------------------------------------------------------------}
+   TGroup = OBJECT (TView)
+         Phase   : (phFocused, phPreProcess, phPostProcess);
+         EndState: Word;                              { Modal result }
+         Current : PView;                             { Selected subview }
+         Last    : PView;                             { 1st view inserted }
+         Buffer  : PVideoBuf;                         { Speed up buffer }
+      CONSTRUCTOR Init (Var Bounds: TRect);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION First: PView;
+      FUNCTION Execute: Word; Virtual;
+      FUNCTION GetHelpCtx: Word; Virtual;
+      FUNCTION DataSize: Word; Virtual;
+      FUNCTION ExecView (P: PView): Word; Virtual;
+      FUNCTION FirstThat (P: Pointer): PView;
+      FUNCTION Valid (Command: Word): Boolean; Virtual;
+      FUNCTION FocusNext (Forwards: Boolean): Boolean;
+      PROCEDURE Draw; Virtual;
+      PROCEDURE Lock;
+      PROCEDURE UnLock;
+      PROCEDURE Awaken; Virtual;
+      PROCEDURE ReDraw;
+      PROCEDURE SelectDefaultView;
+      PROCEDURE Insert (P: PView);
+      PROCEDURE Delete (P: PView);
+      PROCEDURE ForEach (P: Pointer); Virtual;
+      PROCEDURE EndModal (Command: Word); Virtual;
+      PROCEDURE DisplaceBy (Dx, Dy: Integer); Virtual;
+      PROCEDURE SelectNext (Forwards: Boolean);
+      PROCEDURE InsertBefore (P, Target: PView);
+      PROCEDURE SetState (AState: Word; Enable: Boolean); Virtual;
+      PROCEDURE GetData (Var Rec); Virtual;
+      PROCEDURE SetData (Var Rec); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE EventError (Var Event: TEvent); Virtual;
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PROCEDURE ChangeBounds (Var Bounds: TRect); Virtual;
+      PROCEDURE GetSubViewPtr (Var S: TStream; Var P);
+      PROCEDURE PutSubViewPtr (Var S: TStream; P: PView);
+      {$IFNDEF OS_DOS}                                { WIN/NT/OS2 CODE }
+      PROCEDURE CreateWindowNow (CmdShow: Integer); Virtual;
+      {$ENDIF}
+
+      PRIVATE
+         LockFlag: Byte;
+         Clip    : TRect;
+      FUNCTION IndexOf (P: PView): Integer;
+      FUNCTION FindNext (Forwards: Boolean): PView;
+      FUNCTION FirstMatch (AState: Word; AOptions: Word): PView;
+      PROCEDURE ResetCurrent;
+      PROCEDURE RemoveView (P: PView);
+      PROCEDURE InsertView (P, Target: PView);
+      PROCEDURE SetCurrent (P: PView; Mode: SelectMode);
+   END;
+
+{---------------------------------------------------------------------------}
+{                    TFrame OBJECT - FRAME VIEW OBJECT                      }
+{---------------------------------------------------------------------------}
+TYPE
+   TFrame = OBJECT (TView)
+      CONSTRUCTOR Init (Var Bounds: TRect);
+      FUNCTION GetPalette: PPalette; Virtual;
+   END;
+   PFrame = ^TFrame;
+
+{---------------------------------------------------------------------------}
+{                   TScrollBar OBJECT - SCROLL BAR OBJECT                   }
+{---------------------------------------------------------------------------}
+TYPE
+   TScrollChars = Array [0..4] of Char;
+
+   TScrollBar = OBJECT (TView)
+         Value : Integer;                             { Scrollbar value }
+         Min   : Integer;                             { Scrollbar minimum }
+         Max   : Integer;                             { Scrollbar maximum }
+         PgStep: Integer;                             { One page step }
+         ArStep: Integer;                             { One range step }
+         Id    : Integer;                             { Scrollbar ID }
+      CONSTRUCTOR Init (Var Bounds: TRect);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION ScrollStep (Part: Integer): Integer; Virtual;
+      PROCEDURE Draw; Virtual;
+      PROCEDURE ScrollDraw;                                          Virtual;
+      PROCEDURE DrawBackGround;                                      Virtual;
+      PROCEDURE SetValue (AValue: Integer);
+      PROCEDURE SetRange (AMin, AMax: Integer);
+      PROCEDURE SetStep (APgStep, AArStep: Integer);
+      PROCEDURE SetParams (AValue, AMin, AMax, APgStep, AArStep: Integer);
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      {$IFNDEF OS_DOS}                                { WIN/NT/OS2 CODE }
+      FUNCTION GetClassName: String; Virtual;
+      FUNCTION GetClassAttr: LongInt; Virtual;
+      PROCEDURE CreateWindowNow (CmdShow: Integer);                  Virtual;
+      {$ENDIF}
+      PRIVATE
+         Chars: TScrollChars;                         { Scrollbar chars }
+      FUNCTION GetPos: Integer;
+      FUNCTION GetSize: Integer;
+      PROCEDURE DrawPos (Pos: Integer);
+      PROCEDURE ClearPos (Pos: Integer);
+   END;
+   PScrollBar = ^TScrollBar;
+
+{---------------------------------------------------------------------------}
+{                 TScroller OBJECT - SCROLLING VIEW ANCESTOR                }
+{---------------------------------------------------------------------------}
+TYPE
+   TScroller = OBJECT (TView)
+         Delta     : TPoint;
+         Limit     : TPoint;
+         HScrollBar: PScrollBar;                      { Horz scroll bar }
+         VScrollBar: PScrollBar;                      { Vert scroll bar }
+      CONSTRUCTOR Init (Var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION GetPalette: PPalette; Virtual;
+      PROCEDURE ScrollDraw;                                          Virtual;
+      PROCEDURE SetLimit (X, Y: Integer);
+      PROCEDURE ScrollTo (X, Y: Integer);
+      PROCEDURE SetState (AState: Word; Enable: Boolean); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PROCEDURE ChangeBounds (Var Bounds: TRect); Virtual;
+        PRIVATE
+         DrawFlag: Boolean;
+         DrawLock: Byte;
+      PROCEDURE CheckDraw;
+   END;
+   PScroller = ^TScroller;
+
+{---------------------------------------------------------------------------}
+{                  TListViewer OBJECT - LIST VIEWER OBJECT                  }
+{---------------------------------------------------------------------------}
+TYPE
+   TListViewer = OBJECT (TView)
+         NumCols   : Integer;                         { Number of columns }
+         TopItem   : Integer;                         { Top most item }
+         Focused   : Integer;                         { Focused item }
+         Range     : Integer;                         { Range of listview }
+         HScrollBar: PScrollBar;                      { Horz scrollbar }
+         VScrollBar: PScrollBar;                      { Vert scrollbar }
+      CONSTRUCTOR Init (Var Bounds: TRect; ANumCols: Word; AHScrollBar,
+        AVScrollBar: PScrollBar);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION IsSelected (Item: Integer): Boolean; Virtual;
+      FUNCTION GetText (Item: Integer; MaxLen: Integer): String; Virtual;
+      PROCEDURE DrawFocus; Virtual;
+      PROCEDURE DrawBackGround; Virtual;
+      PROCEDURE FocusItem (Item: Integer); Virtual;
+      PROCEDURE SetTopItem (Item: Integer);
+      PROCEDURE SetRange (ARange: Integer);
+      PROCEDURE SelectItem (Item: Integer); Virtual;
+      PROCEDURE SetState (AState: Word; Enable: Boolean); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PROCEDURE ChangeBounds (Var Bounds: TRect); Virtual;
+      {$IFDEF OS_WINDOWS}                             { WIN/NT CODE }
+      FUNCTION GetNotifyCmd: LongInt; Virtual;
+      FUNCTION GetClassName: String; Virtual;
+      FUNCTION GetClassAttr: LongInt; Virtual;
+      PROCEDURE CreateWindowNow (CmdShow: Integer); Virtual;
+      {$ENDIF}
+      PRIVATE
+      PROCEDURE FocusItemNum (Item: Integer); Virtual;
+   END;
+   PListViewer = ^TListViewer;
+
+{---------------------------------------------------------------------------}
+{                  TWindow OBJECT - WINDOW OBJECT ANCESTOR                  }
+{---------------------------------------------------------------------------}
+TYPE
+   TWindow = OBJECT (TGroup)
+         Flags   : Byte;                              { Window flags }
+         Number  : Integer;                           { Window number }
+         Palette : Integer;                           { Window palette }
+         ZoomRect: TRect;                             { Zoom rectangle }
+         Frame   : PFrame;                            { Frame view object }
+         Title   : PString;                           { Title string }
+      CONSTRUCTOR Init (Var Bounds: TRect; ATitle: TTitleStr; ANumber: Integer);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION GetPalette: PPalette; Virtual;
+      FUNCTION GetTitle (MaxSize: Integer): TTitleStr; Virtual;
+      FUNCTION StandardScrollBar (AOptions: Word): PScrollBar;
+      PROCEDURE Zoom; Virtual;
+      PROCEDURE Close; Virtual;
+      PROCEDURE InitFrame; Virtual;
+      PROCEDURE DrawBorder;                                          Virtual;
+      PROCEDURE SetState (AState: Word; Enable: Boolean); Virtual;
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE HandleEvent (Var Event: TEvent); Virtual;
+      PROCEDURE SizeLimits (Var Min, Max: TPoint); Virtual;
+      {$IFNDEF OS_DOS}                                { WIN/NT/OS2 CODE }
+      FUNCTION GetClassText: String; Virtual;
+      FUNCTION GetClassAttr: LongInt; Virtual;
+      {$ENDIF}
+   END;
+   PWindow = ^TWindow;
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                         WINDOW MESSAGE ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-Message------------------------------------------------------------
+Message sets up an event record and calls Receiver^.HandleEvent to
+handle the event. Message returns nil if Receiver is nil, or if
+the event is not handled successfully.
+12Sep97 LdB
+---------------------------------------------------------------------}
+FUNCTION Message (Receiver: PView; What, Command: Word;
+  InfoPtr: Pointer): Pointer;
+
+{-NewMessage---------------------------------------------------------
+NewMessage sets up an event record including the new fields and calls
+Receiver^.HandleEvent to handle the event. Message returns nil if
+Receiver is nil, or if the event is not handled successfully.
+19Sep97 LdB
+---------------------------------------------------------------------}
+FUNCTION NewMessage (P: PView; What, Command: Word; Id: Integer; Data: Real;
+  InfoPtr: Pointer): Pointer;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                     VIEW OBJECT REGISTRATION ROUTINES                     }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{-RegisterViews------------------------------------------------------
+This registers all the view type objects used in this unit.
+11Aug99 LdB
+---------------------------------------------------------------------}
+PROCEDURE RegisterViews;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                            NEW VIEW ROUTINES                              }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{-CreateIdScrollBar--------------------------------------------------
+Creates and scrollbar object of the given size and direction and sets
+the scrollbar id number.
+22Sep97 LdB
+---------------------------------------------------------------------}
+FUNCTION CreateIdScrollBar (X, Y, Size, Id: Integer; Horz: Boolean): PScrollBar;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{             NEW WIN/NT/OS2 VERSION SPECIFIC INTERFACE ROUTINES            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+{-TvViewMsgHandler---------------------------------------------------
+This is the default WIN/NT handler for TView objects. Descendant
+objects may need to call back to this handler so it must be provided
+on the interface.
+11Aug99 LdB
+---------------------------------------------------------------------}
+FUNCTION TvViewMsgHandler (Wnd: hWnd; iMessage, wParam: Sw_Word;
+lParam: LongInt): LongInt;
+{$IFDEF BIT_16} EXPORT; {$ENDIF}
+{$IFDEF BIT_32} {$IFDEF PPC_SPEED} CDECL; {$ELSE} STDCALL; {$ENDIF} {$ENDIF}
+
+{$ENDIF}
+
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+{-TvViewMsgHandler---------------------------------------------------
+This is the default OS2 handler for TView objects. Descendant objects
+may need to call back to this handler so it must be provided on the
+interface.
+11Aug99 LdB
+---------------------------------------------------------------------}
+FUNCTION TvViewMsgHandler(Wnd: HWnd; Msg: ULong; Mp1, Mp2: MParam): MResult;
+CDECL; EXPORT;
+{$ENDIF}
+
+{***************************************************************************}
+{                        INITIALIZED PUBLIC VARIABLES                       }
+{***************************************************************************}
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+
+{$IFDEF PPC_FPC}                                      { FPC WINDOWS COMPILER }
+TYPE TColorRef = LongInt;                             { TColorRef defined }
+{$ENDIF}
+
+{$IFDEF PPC_SPEED}                                    { SPEEDSOFT SYBIL2+ }
+TYPE TColorRef = LongInt;                             { TColorRef defined }
+     TPaintStruct = PaintStruct;
+     TWindowPos = WindowPos;
+     TSize = Size;
+     TWndClass = WndClass;
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                        INITIALIZED WIN/NT VARIABLES                       }
+{---------------------------------------------------------------------------}
+CONST
+   ColRef: Array [0..15] Of TColorRef =               { Standard colour refs }
+     (rgb_Black, rgb_Blue, rgb_Green, rgb_Cyan,
+      rgb_Red, rgb_Magenta, rgb_Brown, rgb_LightGray,
+      rgb_DarkGray, rgb_LightBlue, rgb_LightGreen,
+      rgb_LightCyan, rgb_LightRed, rgb_LightMagenta,
+      rgb_Yellow, rgb_White);
+   ColBrush: Array [0..15] Of HBrush =
+     (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+   ColPen: Array [0..15] Of HPen =
+     (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+{$ENDIF}
+
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+{---------------------------------------------------------------------------}
+{                          INITIALIZED OS2 VARIABLES                        }
+{---------------------------------------------------------------------------}
+CONST
+   ColRef: Array [0..15] Of LongInt =
+     (clr_Black, clr_DarkBlue, clr_DarkGreen, clr_DarkCyan,
+      clr_DarkRed, clr_DarkPink, clr_Brown, clr_PaleGray,
+      clr_DarkGray, clr_Blue, clr_Green, clr_Cyan,
+      clr_Red, clr_Pink, clr_Yellow, clr_White);
+{$ENDIF}
+
+{---------------------------------------------------------------------------}
+{                 INITIALIZED DOS/DPMI/WIN/NT/OS2 VARIABLES                 }
+{---------------------------------------------------------------------------}
+CONST
+   UseNativeClasses: Boolean = True;                  { Native class modes }
+   CommandSetChanged: Boolean = False;                { Command change flag }
+   ShowMarkers: Boolean = False;                      { Show marker state }
+   ErrorAttr: Byte = $CF;                             { Error colours }
+   PositionalEvents: Word = evMouse;                  { Positional defined }
+   FocusedEvents: Word = evKeyboard + evCommand;      { Focus defined }
+   MinWinSize: TPoint = (X: 16; Y: 6);                { Minimum window size }
+   ShadowSize: TPoint = (X: 2; Y: 1);                 { Shadow sizes }
+   ShadowAttr: Byte = $08;                            { Shadow attribute }
+
+{ Characters used for drawing selected and default items in  }
+{ monochrome color sets                                      }
+   SpecialChars: Array [0..5] Of Char = (#175, #174, #26, #27, ' ', ' ');
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        STREAM REGISTRATION RECORDS                        }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{                         TView STREAM REGISTRATION                         }
+{---------------------------------------------------------------------------}
+CONST
+   RView: TStreamRec = (
+     ObjType: 1;                                      { Register id = 1 }
+     {$IFDEF BP_VMTLink}
+     VmtLink: Ofs(TypeOf(TView)^);                    { BP style VMT link }
+     {$ELSE}
+     VmtLink: TypeOf(TView);                          { Alt style VMT link }
+     {$ENDIF}
+     Load:    @TView.Load;                            { Object load method }
+     Store:   @TView.Store                            { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                        TFrame STREAM REGISTRATION                         }
+{---------------------------------------------------------------------------}
+CONST
+   RFrame: TStreamRec = (
+     ObjType: 2;                                      { Register id = 2 }
+     {$IFDEF BP_VMTLink}
+     VmtLink: Ofs(TypeOf(TFrame)^);                   { BP style VMT link }
+     {$ELSE}
+     VmtLink: TypeOf(TFrame);                         { Alt style VMT link }
+     {$ENDIF}
+     Load:    @TFrame.Load;                           { Frame load method }
+     Store:   @TFrame.Store                           { Frame store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                      TScrollBar STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RScrollBar: TStreamRec = (
+     ObjType: 3;                                      { Register id = 3 }
+     {$IFDEF BP_VMTLink}
+     VmtLink: Ofs(TypeOf(TScrollBar)^);               { BP style VMT link }
+     {$ELSE}
+     VmtLink: TypeOf(TScrollBar);                     { Alt style VMT link }
+     {$ENDIF}
+     Load:    @TScrollBar.Load;                       { Object load method }
+     Store:   @TScrollBar.Store                       { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                       TScroller STREAM REGISTRATION                       }
+{---------------------------------------------------------------------------}
+CONST
+   RScroller: TStreamRec = (
+     ObjType: 4;                                      { Register id = 4 }
+     {$IFDEF BP_VMTLink}
+     VmtLink: Ofs(TypeOf(TScroller)^);                { BP style VMT link }
+     {$ELSE}
+     VmtLink: TypeOf(TScroller);                      { Alt style VMT link }
+     {$ENDIF}
+     Load:    @TScroller.Load;                        { Object load method }
+     Store:   @TScroller.Store                        { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                      TListViewer STREAM REGISTRATION                      }
+{---------------------------------------------------------------------------}
+CONST
+   RListViewer: TStreamRec = (
+     ObjType: 5;                                      { Register id = 5 }
+     {$IFDEF BP_VMTLink}
+     VmtLink: Ofs(TypeOf(TListViewer)^);              { BP style VMT link }
+     {$ELSE}
+     VmtLink: TypeOf(TListViewer);                    { Alt style VMT link }
+     {$ENDIF}
+     Load:    @TListViewer.Load;                      { Object load method }
+     Store:   @TLIstViewer.Store                      { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                        TGroup STREAM REGISTRATION                         }
+{---------------------------------------------------------------------------}
+CONST
+   RGroup: TStreamRec = (
+     ObjType: 6;                                      { Register id = 6 }
+     {$IFDEF BP_VMTLink}
+     VmtLink: Ofs(TypeOf(TGroup)^);                   { BP style VMT link }
+     {$ELSE}
+     VmtLink: TypeOf(TGroup);                         { Alt style VMT link }
+     {$ENDIF}
+     Load:    @TGroup.Load;                           { Object load method }
+     Store:   @TGroup.Store                           { Object store method }
+   );
+
+{---------------------------------------------------------------------------}
+{                        TWindow STREAM REGISTRATION                        }
+{---------------------------------------------------------------------------}
+CONST
+   RWindow: TStreamRec = (
+     ObjType: 7;                                      { Register id = 7 }
+     {$IFDEF BP_VMTLink}
+     VmtLink: Ofs(TypeOf(TWindow)^);                  { BP style VMT link }
+     {$ELSE}
+     VmtLink: TypeOf(TWindow);                        { Alt style VMT link }
+     {$ENDIF}
+     Load:    @TWindow.Load;                          { Object load method }
+     Store:   @TWindow.Store                          { Object store method }
+   );
+
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+                             IMPLEMENTATION
+{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
+
+{***************************************************************************}
+{                     PRIVATE CONSTANT DEFINITIONS                          }
+{***************************************************************************}
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+{$IFDEF PPC_SPEED}                                    { SPEEDSOFT SYBIL2+ }
+CONST WM_Notify = $004E;                              { Value was left out }
+{$ENDIF}
+{$ENDIF}
+
+{***************************************************************************}
+{                       PRIVATE TYPE DEFINITIONS                            }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{                         TFixupList DEFINITION                             }
+{---------------------------------------------------------------------------}
+TYPE
+   TFixupList = ARRAY [1..4096] Of Pointer;           { Fix up ptr array }
+   PFixupList = ^TFixupList;                          { Ptr to fix up list }
+
+{***************************************************************************}
+{                      PRIVATE INITIALIZED VARIABLES                        }
+{***************************************************************************}
+
+{---------------------------------------------------------------------------}
+{            INITIALIZED DOS/DPMI/WIN/NT/OS2 PRIVATE VARIABLES              }
+{---------------------------------------------------------------------------}
+CONST
+   TheTopView  : PView = Nil;                         { Top focused view }
+   LimitsLocked: PView = Nil;                         { View locking limits }
+   OwnerGroup  : PGroup = Nil;                        { Used for loading }
+   FixupList   : PFixupList = Nil;                    { Used for loading }
+   CurCommandSet: TCommandSet = ([0..255] -
+     [cmZoom, cmClose, cmResize, cmNext, cmPrev]);    { All active but these }
+
+{***************************************************************************}
+{                          PRIVATE INTERNAL ROUTINES                        }
+{***************************************************************************}
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+{---------------------------------------------------------------------------}
+{  TvViewMsgHandler -> Platforms WIN/NT - Updated 09Aug99 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TvViewMsgHandler (Wnd: hWnd; iMessage, wParam: Sw_Word;
+lParam: LongInt): LongInt; {$IFDEF PPC_FPC} STDCALL; {$ENDIF}
+VAR Bc: Byte; I: LongInt; W: Word; Event: TEvent; P, Tp: PView;
+    Q: PScrollBar; Ps: TPaintStruct; Wp: ^TWindowPos;
+BEGIN
+   {$IFDEF BIT_16}                                    { 16 BIT WINDOWS CODE }
+   PtrRec(P).Seg := GetProp(Wnd, ViewSeg);            { Fetch seg property }
+   PtrRec(P).Ofs := GetProp(Wnd, ViewOfs);            { Fetch ofs property }
+   {$ENDIF}
+   {$IFDEF BIT_32}                                    { 32 BIT WINDOWS CODE }
+   LongInt(P) := GetProp(Wnd, ViewPtr);               { Fetch view pointer }
+   {$ENDIF}
+   If (P <> Nil) Then Begin                           { Valid view pointer }
+     TvViewMsgHandler := 0;                           { Preset return zero }
+     Event.What := evNothing;                         { Preset no event }
+     Case iMessage Of
+       WM_Close: Begin                                { CLOSE COMMAND }
+         If (P^.GetState(sfFocused) = False) Then
+           P^.FocusFromTop;                           { Focus if behind }
+         Event.What := evCommand;                     { Command event }
+         Event.Command := cmClose;                    { Quit command }
+         Event.InfoPtr := P;                          { Pointer to view }
+       End;
+       WM_LButtonDown: Begin                          { LEFT MOUSE DOWN }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons OR mbLeftButton;{ Set button mask }
+       End;
+       WM_LButtonUp: Begin                            { LEFT MOUSE UP }
+         Event.What := evMouseUp;                     { Mouse up event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons AND NOT
+           mbLeftButton;                              { Clear button mask }
+       End;
+       WM_LButtonDBLClk: Begin                        { LEFT MOUSE DBL CLK }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := True;                        { Double click }
+         MouseButtons := MouseButtons OR mbLeftButton;{ Set button mask }
+       End;
+       WM_RButtonDown: Begin                          { RIGHT MOUSE DOWN }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons OR
+           mbRightButton;                             { Set button mask }
+       End;
+       WM_RButtonUp: Begin                            { RIGHT MOUSE UP }
+         Event.What := evMouseUp;                     { Mouse up event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons AND NOT
+           mbRightButton;                             { Clear button mask }
+       End;
+       WM_RButtonDBLClk: Begin                        { RIGHT MOUSE DBL CLK }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := True;                        { Double click }
+         MouseButtons := MouseButtons OR
+           mbLeftButton;                              { Set button mask }
+       End;
+       WM_MButtonDown: Begin                          { MIDDLE MOUSE DOWN }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons OR
+           mbMiddleButton;                            { Set button mask }
+       End;
+       WM_MButtonUp: Begin                            { MIDDLE MOUSE UP }
+         Event.What := evMouseUp;                     { Mouse up event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons AND NOT
+           mbMiddleButton;                            { Clear button mask }
+       End;
+       WM_MButtonDBLClk: Begin                        { MIDDLE MOUSE DBL CLK }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := True;                        { Double click }
+         MouseButtons := MouseButtons OR
+           mbMiddleButton;                            { Set button mask }
+       End;
+       WM_MouseMove: Begin                            { MOUSE MOVEMENT }
+         Event.What := evMouseMove;                   { Mouse move event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := 0;                           { Preset clear buttons }
+         If (wParam AND mk_LButton <> 0) Then
+           MouseButtons := MouseButtons OR
+             mbLeftButton;                            { Left button mask }
+         If (wParam AND mk_MButton <> 0) Then
+           MouseButtons := MouseButtons OR
+             mbLeftButton;                            { Middle button mask }
+         If (wParam AND mk_RButton <> 0) Then
+           MouseButtons := MouseButtons OR
+             mbRightButton;                           { Set right button mask }
+       End;
+       {$IFDEF BIT_32}
+       WM_Notify: Begin
+         I := 0;
+       End;
+       {$ENDIF}
+       WM_EraseBkGnd: TvViewMsgHandler := 1;          { BACKGROUND MESSAGE }
+       WM_Paint: If (P^.Dc = 0) Then Begin            { PAINT MESSAGE }
+         P^.Dc := BeginPaint(Wnd, Ps);                { Fetch structure }
+         SelectObject(ps.hDC, DefGFVFont);            { Select default font }
+         P^.DrawMask := P^.DrawMask OR vdNoChild;     { Draw this view only }
+         P^.ReDrawArea(Ps.rcPaint.Left + P^.RawOrigin.X,
+           Ps.rcPaint.Top + P^.RawOrigin.Y,
+           Ps.rcPaint.Right + P^.RawOrigin.X-1,
+           Ps.rcPaint.Bottom + P^.RawOrigin.Y-1);     { Redraw the area }
+         P^.DrawMask := P^.DrawMask AND NOT vdNoChild;{ Child draws enabled }
+         P^.Dc := 0;                                  { Zero device context }
+         EndPaint(Wnd, Ps);                           { End painting }
+       End Else PostMessage(Wnd, iMessage, wParam,
+        lParam);                                      { Busy repost message }
+       WM_HScroll, WM_VScroll: Begin                  { SCROLLBAR MESSAGES }
+         {$IFDEF BIT_16}                              { 16 BIT WINDOWS CODE }
+         PtrRec(Q).Seg := GetProp(HiWord(lParam),
+           ViewSeg);                                  { Fetch seg property }
+         PtrRec(Q).Ofs := GetProp(HiWord(lParam),
+           ViewOfs);                                  { Fetch ofs property }
+         W := wParam;                                 { Transfer word }
+         {$ENDIF}
+         {$IFDEF BIT_32}                              { 32 BIT WINDOWS CODE }
+         LongInt(Q) := GetProp(lParam, ViewPtr);      { Fetch seg property }
+         W := LoWord(wParam);                         { Low param part }
+         {$ENDIF}
+         If (Q <> Nil) Then Begin                     { Valid scrollbar }
+           If (Q^.GetState(sfFocused) = False) Then
+             Q^.FocusFromTop;                         { Focus up to us }
+           Bc := 0;                                   { Preset do call }
+           Case W Of
+             SB_TOP: Q^.SetValue(Q^.Min);             { Set to minimum }
+             SB_BOTTOM: Q^.SetValue(Q^.Max);          { Set to maximum }
+             SB_ENDSCROLL: Bc := 1;                   { Fail this call }
+             SB_LINEDOWN: Q^.SetValue(Q^.Value +
+                 Q^.ScrollStep(sbDownArrow));         { One line down }
+             SB_LINEUP: Q^.SetValue(Q^.Value +
+               Q^.ScrollStep(sbUpArrow));             { One line up }
+             SB_PAGEDOWN: Q^.SetValue(Q^.Value +
+               Q^.ScrollStep(sbPageDown));            { One page down }
+             SB_PAGEUP: Q^.SetValue(Q^.Value +
+               Q^.ScrollStep(sbPageUp));              { One page up }
+             SB_THUMBPOSITION, SB_THUMBTRACK:
+               {$IFDEF BIT_16}                        { 16 BIT WINDOWS CODE }
+               Q^.SetValue(LoWord(lParam));           { Set to position }
+               {$ENDIF}
+               {$IFDEF BIT_32}                        { 32 BIT WINDOWS CODE }
+               Q^.SetValue(HiWord(wParam));           { Set to position }
+               {$ENDIF}
+             Else Bc := 1;                            { Fail other cases }
+           End;
+           If (Bc=0) Then NewMessage(Q^.Owner,
+             evBroadcast, cmScrollBarClicked, Q^.Id,
+             Q^.Value, Q);                            { Old TV style message }
+         End;
+       End;
+       {$IFDEF BIT_16}                                { 16 BIT WINDOWS CODE }
+       WM_CtlColor: If (HiWord(lParam) = CtlColor_Btn){ COLOUR CONTROL }
+       OR  (HiWord(lParam) = CtlColor_ListBox)
+       {$ENDIF}
+       {$IFDEF BIT_32}                                { 32 BIT WINDOWS CODE }
+       WM_CtlColorListBox, WM_CtlColorBtn:            { COLOUR LISTBOX/BUTTON }
+       If (lParam <> 0)                               { Valid handle }
+       {$ENDIF}
+       Then Begin
+         {$IFDEF BIT_16}                              { 16 BIT WINDOWS CODE }
+         PtrRec(P).Seg := GetProp(LoWord(lParam),
+           ViewSeg);                                  { Get view segment }
+         PtrRec(P).Ofs := GetProp(LoWord(lParam),
+           ViewOfs);                                  { Get view segment }
+         {$ENDIF}
+         {$IFDEF BIT_32}                              { 32 BIT WINDOWS CODE }
+         LongInt(P) := GetProp(LoWord(lParam),
+           ViewPtr);                                  { Get view pointer }
+         {$ENDIF}
+         If (P <> Nil) Then Begin                     { Valid view }
+           Bc := P^.GetColor(1) AND $F0 SHR 4;        { Background colour }
+           SetTextColor(wParam, ColRef[P^.GetColor(1)
+             AND $0F]);                               { Set text colour }
+           SetBkColor(wParam, ColRef[Bc]);            { Set background colour }
+           TvViewMsgHandler := ColBrush[Bc];          { Return colour brush }
+         End Else TvViewMsgHandler := DefWindowProc(
+           Wnd, iMessage, wParam, lParam);            { Call default handler }
+       End Else TvViewMsgHandler := DefWindowProc(
+         Wnd, iMessage, wParam, lParam);              { Call default handler }
+       WM_SysCommand: Begin                           { SYSTEM COMMAND MESSAGE }
+         If (P^.GetState(sfFocused) = False) Then
+           P^.FocusFromTop;                           { Focus if behind }
+         TvViewMsgHandler := DefWindowProc(
+          Wnd, iMessage, wParam, lParam);
+         If IsIconic(Wnd) Then BringWindowToTop(Wnd);
+       End;
+       WM_Command: Begin                              { COMMAND MESSAGE }
+         {$IFDEF BIT_16}                              { 16 BIT WINDOWS CODE }
+         W := HiWord(lParam);                         { Message of lParam }
+         {$ENDIF}
+         {$IFDEF BIT_32}                              { 32 BIT WINDOWS CODE }
+         W := HiWord(wParam);                         { Handle high of wParam }
+         {$ENDIF}
+         Case W Of
+           cbn_SelChange: Begin                       { COMBO/LIST SELECTION }
+             {$IFDEF BIT_16}                          { 16 BIT WINDOWS CODE }
+             PtrRec(Tp).Seg := GetProp(LoWord(lParam),
+               ViewSeg);                              { Fetch combo seg }
+             PtrRec(Tp).Ofs := GetProp(LoWord(lParam),
+               ViewOfs);                              { Fetch combo ofs }
+             {$ENDIF}
+             {$IFDEF BIT_32}                          { 32 BIT WINDOWS CODE }
+             LongInt(Tp) := GetProp(LoWord(lParam),
+               ViewPtr);                              { Fetch combo ptr }
+             {$ENDIF}
+             If (Tp <> Nil) Then Begin                { View is valid }
+               I := SendMessage(LoWord(lParam),
+                 Tp^.GetNotifyCmd, 0, 0);             { Get current state }
+               Event.What := evCommand;               { Command event }
+               Event.Command := cmNotify;             { Notify command }
+               Event.data := I;                       { Load data value }
+               Event.InfoPtr := Tp;                   { Pointer to view }
+             End;
+           End;
+           cbn_SetFocus: Begin                        { DROP BOX FOCUSED }
+             {$IFDEF BIT_16}                          { 16 BIT WINDOWS CODE }
+             PtrRec(Tp).Seg := GetProp(LoWord(lParam),
+               ViewSeg);                              { Fetch combo seg }
+             PtrRec(Tp).Ofs := GetProp(LoWord(lParam),
+               ViewOfs);                              { Fetch combo ofs }
+             {$ENDIF}
+             {$IFDEF BIT_32}                          { 32 BIT WINDOWS CODE }
+             LongInt(Tp) := GetProp(LoWord(lParam),
+               ViewPtr);                              { Fetch combo ptr }
+             {$ENDIF}
+             If (Tp <> Nil) AND                       { Combo box valid }
+               (Tp^.GetState(sfFocused) = False) Then { We have not focus }
+                 Tp^.FocusFromTop;                    { Focus up to us }
+           End;
+           lbn_SetFocus: Begin                        { LIST BOX FOCUSED }
+             {$IFDEF BIT_16}                          { 16 BIT WINDOWS CODE }
+             PtrRec(Tp).Seg := GetProp(LoWord(lParam),
+               ViewSeg);                              { Fetch listbox seg }
+             PtrRec(Tp).Ofs := GetProp(LoWord(lParam),
+               ViewOfs);                              { Fetch listbox ofs }
+             {$ENDIF}
+             {$IFDEF BIT_32}                          { 32 BIT WINDOWS CODE }
+             LongInt(Tp) := GetProp(LoWord(lParam),
+               ViewPtr);                              { Fetch listbox ptr }
+             {$ENDIF}
+             If (Tp <> Nil) Then Begin                { Listbox is valid }
+               If (Tp^.GetState(sfFocused) = False)   { We have not focus }
+                 Then Tp^.FocusFromTop;               { Focus up to us }
+             End;
+           End;
+           Else TvViewMsgHandler := DefWindowProc(
+            Wnd, iMessage, wParam, lParam);           { Call default handler }
+         End;
+       End;
+       WM_Activate, WM_ChildActivate: Begin
+         If (P^.Options AND ofTopSelect <> 0)         { Top selectable view }
+         AND (P^.Options AND ofSelectable <> 0)       { View is selectable }
+         Then P^.FocusFromTop;                        { Focus us from top }
+       End;
+       WM_WindowPosChanged: Begin                     { WINDOW HAS MOVED }
+         If (NOT ISIconic(Wnd)) AND (lParam <> 0)     { Window not iconic }
+         Then Begin
+           Wp := Pointer(lParam);                     { TWindowpos structure }
+           If (Wp^.Flags AND swp_NoMove = 0)          { No move flag is clear }
+           Then Begin
+             If (P^.Owner <> Nil) Then
+             P^.DisplaceBy(Wp^.X + P^.Owner^.RawOrigin.X -
+               P^.RawOrigin.X + P^.Owner^.FrameSize,
+               Wp^.Y + P^.Owner^.RawOrigin.Y -
+               P^.RawOrigin.Y + P^.Owner^.CaptSize)   { Displace the window }
+             Else P^.DisplaceBy(Wp^.X + P^.RawOrigin.X,
+               Wp^.Y - P^.RawOrigin.Y);               { Displace the window }
+           End;
+           If (Wp^.Flags AND swp_NoSize = 0)          { No resize flag clear }
+           Then Begin
+             P^.RawSize.X := Wp^.Cx;                  { Size the window x }
+             P^.RawSize.Y := Wp^.Cy;                  { Size the window y }
+           End;
+         End;
+         TvViewMsgHandler := DefWindowProc(Wnd,
+           iMessage, wParam, lParam);                 { Default handler }
+       End;
+       Else TvViewMsgHandler := DefWindowProc(Wnd,
+         iMessage, wParam, lParam);                   { Call Default handler }
+     End;                                             { End of case }
+     If (Event.What <> evNothing) Then Begin          { Check any GFV event }
+       If (Event.What AND evMouse <> 0) Then Begin    { Mouse event }
+         If (P <> Nil) Then Begin                     { Valid view pointer }
+           Event.Where.X := LoWord(lParam) +
+             P^.RawOrigin.X + P^.FrameSize;           { X mouse co-ordinate }
+           Event.Where.Y := HiWord(lParam) +
+             P^.RawOrigin.Y + P^.CaptSize;            { Y mouse co-ordinate }
+           MouseWhere := Event.Where;                 { Update mouse where }
+           Event.Buttons := MouseButtons;             { Return mouse buttons }
+         End Else Exit;                               { View is not valid }
+       End;
+       PutEventInQueue(Event);                        { Put event in queue }
+     End;
+   End Else TvViewMsgHandler := DefWindowProc(Wnd,
+     iMessage, wParam, lParam);                       { Call Default handler }
+END;
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CODE }
+{---------------------------------------------------------------------------}
+{  TvViewMsgHandler -> Platforms OS2 - Updated 09Aug99 LdB                  }
+{---------------------------------------------------------------------------}
+FUNCTION TvViewMsgHandler(Wnd: HWnd; Msg: ULong; Mp1, Mp2: MParam): MResult;
+VAR Bc: Byte; R: RectL; Event: TEvent; P: PView; Pt: PointL; PS: hPs; Sp: Swp;
+    Q: PScrollBar; Sh: HWnd;
+BEGIN
+   P := Nil;                                          { Clear the pointer }
+   WinQueryPresParam(Wnd, PP_User, 0, Nil,
+     SizeOf(Pointer), @P, 0);                         { Fetch view pointer }
+   If (P <> Nil) Then Begin                           { PView is valid }
+     TvViewMSgHandler := 0;                           { Preset handled }
+     Event.What := evNothing;                         { Preset no event }
+     Case Msg Of
+       WM_Close: Begin                                { CLOSE COMMAND }
+         If (P^.GetState(sfFocused) = False) Then
+           P^.FocusFromTop;                           { Focus if behind }
+         Event.What := evCommand;                     { Command event }
+         Event.Command := cmClose;                    { Quit command }
+         Event.InfoPtr := P;                          { Pointer to view }
+       End;
+       WM_EraseBackGround: TvViewMsgHandler :=        { BACKGROUND ERASE }
+         LongInt(False);                              { Return false }
+       WM_Paint: If (P^.Ps = 0) Then Begin            { PAINT MESSAGE }
+         P^.Ps := WinBeginPaint(Wnd, 0, @R);          { Fetch structure }
+         P^.DrawMask := P^.DrawMask OR vdNoChild;     { Draw this view only }
+         P^.ReDrawArea(R.xLeft + P^.RawOrigin.X,
+           R.yBottom + P^.RawOrigin.Y,
+           R.xRight + P^.RawOrigin.X,
+           R.yTop + P^.RawOrigin.Y);                  { Redraw the area }
+         P^.DrawMask := P^.DrawMask AND NOT vdNoChild;{ Child draws enabled }
+         P^.Ps := 0;                                  { Zero device context }
+         WinEndPaint(Ps);                             { End painting }
+       End Else WinPostMsg(Wnd, Msg, Mp1, Mp2);       { Busy repost message }
+       WM_Button1Down: Begin                          { LEFT MOUSE DOWN }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons OR
+           mbLeftButton;                              { Set button mask }
+       End;
+       WM_Button1Up: Begin                            { LEFT MOUSE UP }
+         Event.What := evMouseUp;                     { Mouse up event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons AND NOT
+           mbLeftButton;                              { Clear button mask }
+       End;
+       WM_Button1DBLClk: Begin                        { LEFT MOUSE DBL CLK }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := True;                        { Double click }
+         MouseButtons := MouseButtons OR
+           mbLeftButton;                              { Set button mask }
+       End;
+       WM_Button2Down: Begin                          { RIGHT MOUSE DOWN }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons OR
+           mbRightButton;                             { Set button mask }
+       End;
+       WM_Button2Up: Begin                            { RIGHT MOUSE UP }
+         Event.What := evMouseUp;                     { Mouse up event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons AND NOT
+           mbRightButton;                             { Clear button mask }
+       End;
+       WM_Button2DBLClk: Begin                        { RIGHT MOUSE DBL CLK }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := True;                        { Double click }
+         MouseButtons := MouseButtons OR
+           mbLeftButton;                              { Set button mask }
+       End;
+       WM_Button3Down: Begin                          { MIDDLE MOUSE DOWN }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons OR
+           mbMiddleButton;                            { Set button mask }
+       End;
+       WM_Button3Up: Begin                            { MIDDLE MOUSE UP }
+         Event.What := evMouseUp;                     { Mouse up event }
+         Event.Double := False;                       { Not double click }
+         MouseButtons := MouseButtons AND NOT
+           mbMiddleButton;                            { Clear button mask }
+       End;
+       WM_Button3DBLClk: Begin                        { MIDDLE MOUSE DBL CLK }
+         Event.What := evMouseDown;                   { Mouse down event }
+         Event.Double := True;                        { Double click }
+         MouseButtons := MouseButtons OR
+           mbMiddleButton;                            { Set button mask }
+       End;
+       WM_MouseMove: Begin                            { MOUSE MOVEMENT }
+         Event.What := evMouseMove;                   { Mouse move event }
+         Event.Double := False;                       { Not double click }
+         If (WinQueryPointer(HWND_Desktop) <>
+           DefPointer) Then                           { Check mouse ptr }
+           WinSetPointer(HWND_DeskTop, DefPointer);   { Set mouse ptr }
+       End;
+       WM_HScroll, WM_VScroll: Begin                  { SCROLLBAR MESSAGES }
+         Q := Nil;                                    { Clear the pointer }
+         Sh := WinQueryFocus(HWnd_DeskTop);           { Scrollbar has focus }
+         If (Sh <> 0) Then WinQueryPresParam(Sh,
+           PP_User, 0, Nil, SizeOf(Pointer), @Q, 0);  { Fetch scrollbar ptr }
+         If (Q <> Nil) AND (Q^.GOptions AND
+         goNativeClass <> 0) Then Begin               { Valid scrollbar }
+           If (Q^.GetState(sfFocused) = False) Then
+             Q^.FocusFromTop;                         { Focus up to us }
+           Bc := 0;                                   { Preset do call }
+           Case Short2FromMP(Mp2) Of                  { Scrollbar message }
+             SB_ENDSCROLL:;
+             SB_LINEDOWN: Q^.SetValue(Q^.Value +
+               Q^.ScrollStep(sbDownArrow));           { One line down }
+             SB_LINEUP: Q^.SetValue(Q^.Value +
+               Q^.ScrollStep(sbUpArrow));             { One line up }
+             SB_PAGEDOWN: Q^.SetValue(Q^.Value +
+               Q^.ScrollStep(sbPageDown));            { One page down }
+             SB_PAGEUP: Q^.SetValue(Q^.Value +
+               Q^.ScrollStep(sbPageUp));              { One page up }
+             SB_SLIDERPOSITION, SB_SLIDERTRACK:
+               Q^.SetValue(Short1FromMP(Mp2));        { Set to position }
+             Else Bc := 1;                            { Fail other cases }
+           End;
+           If (Bc=0) Then NewMessage(Q^.Owner,
+             evBroadcast, cmScrollBarClicked, Q^.Id,
+             Q^.Value, Q);                            { Old TV style message }
+         End;
+       End;
+       WM_QueryTrackInfo: Begin                      { WINDOW HAS MOVED }
+         (*If (NOT ISIconic(Wnd)) AND (lParam <> 0)    { Window not iconic }
+         Then Begin*)
+           (*Sp := PSwp(Mp1)^;                          { New SWP data }
+           If (Sp.Fl AND swp_Size  <> 0) Then Begin   { Size change request }
+             P^.RawSize.X := Sp.Cx-1;                 { Size the window x }
+             P^.RawSize.Y := Sp.Cy-1;                 { Size the window y }
+           End;*)
+           (*P^.DisplaceBy(Sp1.X - Sp2.X,
+             -(Sp1.Y - Sp2.Y));*)
+         TvViewMSgHandler := 0;
+       End;
+       Else TvViewMSgHandler := WinDefWindowProc(
+         Wnd, Msg, Mp1, Mp2);                         { Call default handler }
+     End;
+     If (Event.What <> evNothing) Then Begin          { Check any FV event }
+       If (Event.What AND evMouse <> 0) Then Begin    { Mouse event }
+         WinQueryWindowPos(Wnd, Sp);                  { Query client area }
+         Event.Where.X := Short1FromMP(Mp1)-1
+          + P^.RawOrigin.X;                           { X mouse co-ordinate }
+         Event.Where.Y := Sp.Cy -
+          Short2FromMP(Mp1)-1 + P^.RawOrigin.Y;       { Y mouse co-ordinate }
+         Event.Buttons := MouseButtons;               { Return buttons }
+         MouseWhere := Event.Where;                   { Update mouse where }
+       End;
+       PutEventInQueue(Event);                        { Put event in queue }
+     End;
+   End Else TvViewMSgHandler := WinDefWindowProc(Wnd,
+     Msg, Mp1, Mp2);                                  { Call default handler }
+END;
+{$ENDIF}
+
+{***************************************************************************}
+{                              OBJECT METHODS                               }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                            TView OBJECT METHODS                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{$IFNDEF OS_DOS}                                      { WIN/NT/OS2 CODE }
+{---------------------------------------------------------------------------}
+{                     TView WINDOW CLASS NAME CONSTANT                      }
+{---------------------------------------------------------------------------}
+CONST TvViewClassName = 'TVIEW';                      { TView window class }
+{$ENDIF}
+
+{--TView--------------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 20Jun96 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TView.Init (Var Bounds: TRect);
+BEGIN
+   Inherited Init;                                    { Call ancestor }
+   DragMode := dmLimitLoY;                            { Default drag mode }
+   HelpCtx := hcNoContext;                            { Clear help context }
+   State := sfVisible;                                { Default state }
+   EventMask := evMouseDown + evKeyDown + evCommand;  { Default event masks }
+   GOptions := goTabSelect;                           { Set new options }
+   SetBounds(Bounds);                                 { Set view bounds }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06May98 LdB              }
+{---------------------------------------------------------------------------}
+{   This load method will read old original TV data from a stream but the   }
+{  new options and tabmasks are not set so some NEW functionality is not    }
+{  supported but it should work as per original TV code.                    }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TView.Load (Var S: TStream);
+BEGIN
+   Inherited Init;                                    { Call ancestor }
+   S.Read(Origin.X, 2);                               { Read origin x value }
+   S.Read(Origin.Y, 2);                               { Read origin y value }
+   S.Read(Size.X, 2);                                 { Read view x size }
+   S.Read(Size.Y, 2);                                 { Read view y size }
+   S.Read(Cursor.X, 2);                               { Read cursor x size }
+   S.Read(Cursor.Y, 2);                               { Read cursor y size }
+   S.Read(GrowMode, 1);                               { Read growmode flags }
+   S.Read(DragMode, 1);                               { Read dragmode flags }
+   S.Read(HelpCtx, 2);                                { Read help context }
+   S.Read(State, 2);                                  { Read state masks }
+   S.Read(Options, 2);                                { Read options masks }
+   S.Read(Eventmask, 2);                              { Read event masks }
+   If (Options AND ofGFVModeView <> 0) Then Begin     { STREAM HAS GFV TVIEW }
+     S.Read(GOptions, 2);                             { Read new option masks }
+     S.Read(TabMask, 1);                              { Read new tab masks }
+     S.Read(RawOrigin.X, 2);                          { Read raw x origin point }
+     S.Read(RawOrigin.Y, 2);                          { Read raw y origin point }
+     S.Read(RawSize.X, 2);                            { Read raw x size }
+     S.Read(RawSize.Y, 2);                            { Read raw y size }
+     S.Read(ColourOfs, 2);                            { Read palette offset }
+   End Else Begin                                     { STREAM HAS OLD TView }
+     RawOrigin.X := Origin.X * FontWidth;             { Set x origin pt }
+     RawOrigin.Y := Origin.Y * FontHeight;            { Set y origin pt }
+     RawSize.X := (Size.X * FontWidth) - 1;           { Calc raw x size }
+     RawSize.Y := (Size.Y * FontHeight) - 1;          { Calc raw y size }
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Nov99 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TView.Done;
+VAR P: PComplexArea; {$IFNDEF OS_DOS} S: String; {$ENDIF}
+BEGIN
+   Hide;                                              { Hide the view }
+   If (Owner <> Nil) Then Owner^.Delete(@Self);       { Delete from owner }
+   While (HoldLimit <> Nil) Do Begin                  { Free limit memory }
+     P := HoldLimit^.NextArea;                        { Hold next pointer }
+     FreeMem(HoldLimit, SizeOf(TComplexArea));        { Release memory }
+     HoldLimit := P;                                  { Shuffle to next }
+   End;
+   {$IFNDEF OS_DOS}                                   { WIN/NT/OS2 CODE }
+   If (HWindow <> 0) Then Begin                       { Handle valid }
+     S := GetClassName + #0;                          { Make asciiz }
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE}
+       {$IFDEF BIT_16}                                { 16 BIT CODE }
+       RemoveProp(HWindow, ViewSeg);                  { Remove seg property }
+       RemoveProp(HWindow, ViewOfs);                  { Remove offs property }
+       {$ENDIF}
+       {$IFDEF BIT_32}                                { 32 BIT CODE }
+       RemoveProp(HWindow, ViewPtr);                  { Remove view property }
+       {$ENDIF}
+       DestroyWindow(HWindow);                        { Destroy window }
+       If (GOptions AND goNativeClass = 0) Then       { Not native class check }
+         {$IFDEF PPC_SPEED}                           { SPEEDSOFT SYBIL2+ }
+         UnRegisterClass(CString(@S[1]), 0);          { Unregister class }
+         {$ELSE}                                      { OTHER COMPILERS }
+         UnRegisterClass(@S[1], HInstance);           { Unregister class }
+         {$ENDIF}
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+       WinRemovePresParam(HWindow, PP_User);          { Remove self ptr }
+       WinDestroyWindow(HWindow);                     { Destroy window }
+       If (GOptions AND goNativeClass = 0) Then       { Not native class check }
+         WinDeregisterObjectClass(@S[1]);             { Unregister class }
+     {$ENDIF}
+   End;
+   {$ENDIF}
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Prev -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION TView.Prev: PView;
+VAR P: PView;
+BEGIN
+   P := @Self;                                        { Start with self }
+   While (P^.Next <> Nil) AND (P^.Next <> @Self)
+     Do P := P^.Next;                                 { Locate next view }
+   Prev := P;                                         { Return result }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Execute -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TView.Execute: Word;
+BEGIN
+   Execute := cmCancel;                               { Return cancel }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Focus -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 05May98 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION TView.Focus: Boolean;
+VAR Res: Boolean;
+BEGIN
+   Res := True;                                       { Preset result }
+   If (State AND (sfSelected + sfModal)=0) Then Begin { Not modal/selected }
+     If (Owner <> Nil) Then Begin                     { View has an owner }
+       Res := Owner^.Focus;                           { Return focus state }
+       If Res Then                                    { Owner has focus }
+         If ((Owner^.Current = Nil) OR                { No current view }
+         (Owner^.Current^.Options AND ofValidate = 0) { Non validating view }
+         OR (Owner^.Current^.Valid(cmReleasedFocus))) { Okay to drop focus }
+           Then Select Else Res := False;             { Then select us }
+     End;
+   End;
+   Focus := Res;                                      { Return focus result }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  DataSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TView.DataSize: Word;
+BEGIN
+   DataSize := 0;                                     { Transfer size }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  TopView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TView.TopView: PView;
+VAR P: PView;
+BEGIN
+   If (TheTopView = Nil) Then Begin                   { Check topmost view }
+     P := @Self;                                      { Start with us }
+     While (P <> Nil) AND (P^.State AND sfModal = 0)  { Check if modal }
+       Do P := P^.Owner;                              { Search each owner }
+     TopView := P;                                    { Return result }
+   End Else TopView := TheTopView;                    { Return topview }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  PrevView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TView.PrevView: PView;
+BEGIN
+   If (@Self = Owner^.First) Then PrevView := Nil     { We are first view }
+     Else PrevView := Prev;                           { Return our prior }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  NextView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TView.NextView: PView;
+BEGIN
+   If (@Self = Owner^.Last) Then NextView := Nil      { This is last view }
+     Else NextView := Next;                           { Return our next }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetHelpCtx -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetHelpCtx: Word;
+BEGIN
+   If (State AND sfDragging <> 0) Then                { Dragging state check }
+     GetHelpCtx := hcDragging Else                    { Return dragging }
+     GetHelpCtx := HelpCtx;                           { Return help context }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  EventAvail -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TView.EventAvail: Boolean;
+VAR Event: TEvent;
+BEGIN
+   GetEvent(Event);                                   { Get next event }
+   If (Event.What <> evNothing) Then PutEvent(Event); { Put it back }
+   EventAvail := (Event.What <> evNothing);           { Return result }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetPalette: PPalette;
+BEGIN
+   GetPalette := Nil;                                 { Return nil ptr }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetColor -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Jul99 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetColor (Color: Word): Word;
+VAR Col: Byte; W: Word; P: PPalette; Q: PView;
+BEGIN
+   W := 0;                                            { Clear colour word }
+   If (Hi(Color) > 0) Then Begin                      { High colour req }
+     Col := Hi(Color) + ColourOfs;                    { Initial offset }
+     Q := @Self;                                      { Pointer to self }
+     Repeat
+       P := Q^.GetPalette;                            { Get our palette }
+       If (P <> Nil) Then Begin                       { Palette is valid }
+         If (Col <= Length(P^)) Then
+           Col := Ord(P^[Col]) Else                   { Return colour }
+           Col := ErrorAttr;                          { Error attribute }
+       End;
+       Q := Q^.Owner;                                 { Move up to owner }
+     Until (Q = Nil);                                 { Until no owner }
+     W := Col SHL 8;                                  { Translate colour }
+   End;
+   If (Lo(Color) > 0) Then Begin
+     Col := Lo(Color) + ColourOfs;                    { Initial offset }
+     Q := @Self;                                      { Pointer to self }
+     Repeat
+       P := Q^.GetPalette;                            { Get our palette }
+       If (P <> Nil) Then Begin                       { Palette is valid }
+         If (Col <= Length(P^)) Then
+           Col := Ord(P^[Col]) Else                   { Return colour }
+           Col := ErrorAttr;                          { Error attribute }
+       End;
+       Q := Q^.Owner;                                 { Move up to owner }
+     Until (Q = Nil);                                 { Until no owner }
+   End Else Col := ErrorAttr;                         { No colour found }
+   GetColor := W OR Col;                              { Return color }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Valid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION TView.Valid (Command: Word): Boolean;
+BEGIN
+   Valid := True;                                     { Simply return true }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetState (AState: Word): Boolean;
+BEGIN
+   GetState := State AND AState = AState;             { Check states equal }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  TextWidth -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 25Nov99 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION TView.TextWidth (Txt: String): Integer;
+VAR I: Integer; S: String;
+{$IFNDEF OS_DOS} P: Pointer; Wnd: HWnd; {$ENDIF}
+{$IFDEF OS_WINDOWS} ODc: HDc; M: TSize; {$ENDIF}
+{$IFDEF OS_OS2} OPs: HPs; Pt: Array [0..3] Of PointL; {$ENDIF}
+BEGIN
+   S := Txt;                                          { Transfer text }
+   Repeat
+     I := Pos('~', S);                                { Check for tilde }
+      If (I <> 0) Then System.Delete(S, I, 1);        { Remove the tilde }
+   Until (I = 0);                                     { Remove all tildes }
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+     TextWidth := Length(S) * SysFontWidth;           { Calc text length }
+   {$ENDIF}
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+     ODc := Dc;                                       { Hold device context }
+     If (Dc = 0) Then Begin                           { No context set }
+       If (HWindow = 0) OR (State AND sfVisible = 0)  { Check window valid }
+       OR (State AND sfExposed = 0)
+         Then Wnd := AppWindow Else Wnd := HWindow;   { Select window or app }
+       Dc := GetDC(Wnd);                              { Get device context }
+     End;
+     SelectObject(Dc, DefGFVFont);                    { Select the font }
+     P := @S[1];                                      { Pointer to text }
+     {$IFDEF BIT_32}                                  { WINDOWS 32 BIT CODE }
+       {$IFDEF PPC_SPEED}                             { SPEEDSOFT SYBIL2+ }
+         If (GetTextExtentPoint(Dc, CString(P),
+           Length(S), M)=False) Then M.Cx := 0;       { Get text extents }
+       {$ELSE}                                        { OTHER COMPILERS }
+         {$IFDEF PPC_FPC}                             { FPC WINDOWS COMPILER }
+          If (GetTextExtentPoint(Dc, P, Length(S),
+           @M)=False) Then M.Cx := 0;                 { Get text extents }
+         {$ELSE}                                      { ALL OTHER COMPILERS }
+         If (GetTextExtentPoint(Dc, P, Length(S),
+           M)=False) Then M.Cx := 0;                  { Get text extents }
+         {$ENDIF}
+       {$ENDIF}
+     {$ELSE}                                          { WINDOWS 16 BIT CODE }
+       {$IFDEF PPC_DELPHI}                            { DELPHI1 COMPILER }
+         If (GetTextExtentPoint(Dc, @S[1], Length(S),
+           M)=False)Then M.Cx := 0;                   { Get text extents }
+       {$ELSE}                                        { OTHER COMPILERS }
+         If (GetTextExtentPoint(Dc, @S[1], Length(S),
+           M.Cx)=False)Then M.Cx := 0;                { Get text extents }
+       {$ENDIF}
+     {$ENDIF}
+     TextWidth := M.Cx;                               { Return text width }
+     If (ODc = 0) Then ReleaseDC(Wnd, Dc);            { Release context }
+     Dc := ODc;                                       { Original context set }
+   {$ENDIF}
+   {$IFDEF OS_OS2}
+     OPs := Ps;                                       { Hold pres space }
+     If (Ps = 0) Then Begin
+       If (HWindow = 0) OR (State AND sfVisible = 0)  { Check window valid }
+       OR (State AND sfExposed = 0)
+         Then Wnd := AppWindow Else Wnd := Client;    { Select window or app }
+       Ps := WinGetPS(Wnd);                           { Get pres space  }
+     End;
+     GPISetCharSet(PS, DefGFVFont);                   { Set the font style }
+     P := @S[1];                                      { Pointer to text }
+     GpiQueryTextBox(Ps, Length(S), P, 3, Pt[0]);     { Get text extents }
+     TextWidth := Pt[2].X;                            { Return text width }
+     If (OPs = 0) Then WinReleasePS(Ps);              { Release pres space }
+     Ps := OPs;                                       { Original pres space }
+   {$ENDIF}
+END;
+
+{--TView--------------------------------------------------------------------}
+{  MouseInView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+FUNCTION TView.MouseInView (Point: TPoint): Boolean;
+BEGIN
+   MouseInView := False;                              { Preset false }
+   If (Point.X < RawOrigin.X) Then Exit;              { Point to left }
+   If (Point.X > (RawOrigin.X+RawSize.X)) Then Exit;  { Point to right }
+   If (Point.Y < RawOrigin.Y) Then Exit;              { Point is above }
+   If (Point.Y > (RawOrigin.Y+RawSize.Y)) Then Exit;  { Point is below }
+   MouseInView := True;                               { Return true }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  CommandEnabled -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB    }
+{---------------------------------------------------------------------------}
+FUNCTION TView.CommandEnabled(Command: Word): Boolean;
+BEGIN
+   CommandEnabled := (Command > 255) OR
+     (Command IN CurCommandSet);                      { Check command }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  OverLapsArea -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Sep97 LdB      }
+{---------------------------------------------------------------------------}
+FUNCTION TView.OverlapsArea (X1, Y1, X2, Y2: Integer): Boolean;
+BEGIN
+   OverLapsArea := False;                             { Preset false }
+   If (RawOrigin.X > X2) Then Exit;                   { Area to the left }
+   If ((RawOrigin.X + RawSize.X) < X1) Then Exit;     { Area to the right }
+   If (RawOrigin.Y > Y2) Then Exit;                   { Area is above }
+   If ((RawOrigin.Y + RawSize.Y) < Y1) Then Exit;     { Area is below }
+   OverLapsArea := True;                              { Return true }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  MouseEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TView.MouseEvent (Var Event: TEvent; Mask: Word): Boolean;
+BEGIN
+   Repeat
+     GetEvent(Event);                                 { Get next event }
+   Until (Event.What AND (Mask OR evMouseUp) <> 0);   { Wait till valid }
+   MouseEvent := Event.What <> evMouseUp;             { Return result }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Hide -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.Hide;
+BEGIN
+   If (State AND sfVisible <> 0) Then                 { View is visible }
+     SetState(sfVisible, False);                      { Hide the view }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Show -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.Show;
+BEGIN
+   If (State AND sfVisible = 0) Then                  { View not visible }
+     SetState(sfVisible, True);                       { Show the view }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Sep97 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.Draw;
+BEGIN                                                 { Abstract method }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Select -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 05May98 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.Select;
+BEGIN
+   If (Options AND ofSelectable <> 0) Then            { View is selectable }
+     If (Options AND ofTopSelect <> 0) Then MakeFirst { Top selectable }
+     Else If (Owner <> Nil) Then                      { Valid owner }
+       Owner^.SetCurrent(@Self, NormalSelect);        { Make owners current }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Awaken -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.Awaken;
+BEGIN                                                 { Abstract method }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  DrawView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06May98 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.DrawView;
+VAR ViewPort: ViewPortType;                           { Common variables }
+   {$IFDEF OS_WINDOWS} ODc: HDc; {$ENDIF}             { WIN/NT variables }
+   {$IFDEF OS_OS2} OPs: HPs; {$ENDIF}                 { OS2 variables }
+BEGIN
+   If (State AND sfVisible <> 0) AND                  { View is visible }
+   (State AND sfExposed <> 0) AND                     { View is exposed }
+   (State AND sfIconised = 0) Then Begin              { View not iconised }
+     SetViewLimits;                                   { Set view limits }
+     GetViewSettings(ViewPort);                       { Get set viewport }
+     If OverlapsArea(ViewPort.X1, ViewPort.Y1,
+     ViewPort.X2, ViewPort.Y2) Then Begin             { Must be in area }
+       {$IFDEF OS_DOS}                                { DOS/DPMI CODE }
+         HideMouseCursor;                             { Hide mouse cursor }
+       {$ENDIF}
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+       If (HWindow <> 0) Then Begin                   { Valid window }
+         ODc := Dc;                                   { Hold device context }
+         If (Dc = 0) Then Dc := GetDc(HWindow);       { Get device context }
+       {$ENDIF}
+       {$IFDEF OS_OS2}                                { OS2 CODE }
+       If (HWindow <> 0) Then Begin                   { Valid window }
+         OPs := Ps;                                   { Hold paint struct }
+         If (Ps = 0) Then Ps := WinGetPS(Client);     { Create paint struct }
+       {$ENDIF}
+         If (DrawMask = 0) OR (DrawMask = vdNoChild)  { No special masks set }
+         Then Begin                                   { Treat as a full redraw }
+           DrawBackGround;                            { Draw background }
+           Draw;                                      { Draw interior }
+           If (GOptions AND goDrawFocus <> 0) Then
+             DrawFocus;                               { Draw focus }
+           If (State AND sfCursorVis <> 0)
+             Then DrawCursor;                         { Draw any cursor }
+           If (Options AND ofFramed <> 0) OR
+           (GOptions AND goThickFramed <> 0)          { View has border }
+             Then DrawBorder;                         { Draw border }
+         End Else Begin                               { Masked draws only  }
+           If (DrawMask AND vdBackGnd <> 0) Then      { Chk background mask }
+             DrawBackGround;                          { Draw background }
+           If (DrawMask AND vdInner <> 0) Then        { Check Inner mask }
+             Draw;                                    { Draw interior }
+           If (DrawMask AND vdFocus <> 0)
+           AND (GOptions AND goDrawFocus <> 0)
+             Then DrawFocus;                          { Check focus mask }
+           If (DrawMask AND vdCursor <> 0) Then       { Check cursor mask }
+             DrawCursor;                              { Draw any cursor }
+           If (DrawMask AND vdBorder <> 0) Then       { Check border mask }
+             DrawBorder;                              { Draw border }
+         End;
+       {$IFDEF OS_DOS}                                { DOS/DPMI CODE }
+         ShowMouseCursor;                             { Show mouse cursor }
+       {$ENDIF}
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+         If (ODc = 0) Then ReleaseDc(HWindow, Dc);    { Release context }
+         Dc := ODc;                                   { Reset held context }
+       End;
+       {$ENDIF}
+       {$IFDEF OS_OS2}                                { OS2 CODE }
+         If (OPs = 0) Then WinReleasePS(Ps);          { Free paint struct }
+         Ps := OPs;                                   { Reset held struct }
+       End;
+       {$ENDIF}
+     End;
+     ReleaseViewLimits;                               { Release the limits }
+   End;
+   DrawMask := 0;                                     { Clear the draw mask }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  MakeFirst -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 29Sep99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.MakeFirst;
+BEGIN
+   If (Owner <> Nil) Then Begin                       { Must have owner }
+     PutInFrontOf(Owner^.First);                      { Float to the top }
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     If (HWindow <> 0) Then                           { Valid window }
+       SetWindowPos(HWindow, HWND_TOP, 0, 0, 0, 0,
+         swp_NoSize OR swp_NoMove);                   { Bring window to top }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (HWindow <> 0) Then                           { Valid window }
+       WinSetWindowPos(HWindow, HWND_TOP, 0, 0, 0, 0,
+         swp_ZOrder);                                 { Bring window to top }
+     {$ENDIF}
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  DrawFocus -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Sep97 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.DrawFocus;
+BEGIN                                                 { Abstract method }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  DrawCursor -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.DrawCursor;
+BEGIN                                                 { Abstract method }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  DrawBorder -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17May98 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.DrawBorder;
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE ONLY }
+   BiColorRectangle(0, 0, RawSize.X, RawSize.Y, White,
+     DarkGray, False);                                { Draw 3d effect }
+   If (GOptions AND goThickFramed <> 0) Then Begin    { Thick frame at work }
+     GraphRectangle(1, 1, RawSize.X-1, RawSize.Y-1,
+       LightGray);                                    { Draw frame part 1 }
+     GraphRectangle(2, 2, RawSize.X-2, RawSize.Y-2,
+       LightGray);                                    { Fraw frame part 2 }
+     BiColorRectangle(3, 3, RawSize.X-3, RawSize.Y-3,
+       White, DarkGray, True);                        { Draw highlights }
+   End;
+   {$ENDIF}
+END;
+
+{--TView--------------------------------------------------------------------}
+{  HideCursor -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.HideCursor;
+BEGIN
+   SetState(sfCursorVis , False);                     { Hide the cursor }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  ShowCursor -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.ShowCursor;
+BEGIN
+   SetState(sfCursorVis , True);                      { Show the cursor }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  BlockCursor -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.BlockCursor;
+BEGIN
+   SetState(sfCursorIns, True);                       { Set insert mode }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  NormalCursor -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.NormalCursor;
+BEGIN
+   SetState(sfCursorIns, False);                      { Clear insert mode }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  FocusFromTop -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11Aug99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.FocusFromTop;
+BEGIN
+   If (Owner <> Nil) AND
+     (Owner^.State AND sfSelected = 0)
+       Then Owner^.Select;
+   If (State AND sfFocused = 0) Then Focus;
+   If (State AND sfSelected = 0) Then Select;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SetViewLimits -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Sep99 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SetViewLimits;
+VAR X1, Y1, X2, Y2: Integer; P: PGroup; ViewPort: ViewPortType; Ca: PComplexArea;
+BEGIN
+   If (MaxAvail >= SizeOf(TComplexArea)) Then Begin   { Check enough memory }
+     GetMem(Ca, SizeOf(TComplexArea));                { Allocate memory }
+     GetViewSettings(ViewPort);                       { Fetch view port }
+     Ca^.X1 := ViewPort.X1;                           { Hold current X1 }
+     Ca^.Y1 := ViewPort.Y1;                           { Hold current Y1 }
+     Ca^.X2 := ViewPort.X2;                           { Hold current X2 }
+     Ca^.Y2 := ViewPort.Y2;                           { Hold current Y2 }
+     Ca^.NextArea := HoldLimit;                       { Pointer to next }
+     HoldLimit := Ca;                                 { Move down chain }
+     X1 := RawOrigin.X;                               { Xfer x raw origin }
+     Y1 := RawOrigin.Y;                               { Xfer y raw origin }
+     X2 := X1 + RawSize.X;                            { Calc right value }
+     Y2 := Y1 + RawSize.Y;                            { Calc lower value }
+     P := Owner;                                      { Start on owner }
+     While (P <> Nil) Do Begin                        { While owner valid }
+      If (X1 < P^.RawOrigin.X) Then
+         X1 := P^.RawOrigin.X;                        { X minimum contain }
+       If (Y1 < P^.RawOrigin.Y) Then
+         Y1 := P^.RawOrigin.Y;                        { Y minimum contain }
+       If (X2 > P^.RawOrigin.X + P^.RawSize.X)
+         Then X2 := P^.RawOrigin.X + P^.RawSize.X;    { X maximum contain }
+       If (Y2 > P^.RawOrigin.Y + P^.RawSize.Y)
+         Then Y2 := P^.RawOrigin.Y + P^.RawSize.Y;    { Y maximum contain }
+       P := P^.Owner;                                 { Move to owners owner }
+     End;
+     If (LimitsLocked <> Nil) Then Begin              { Locked = area redraw }
+       If (X2 < ViewPort.X1) Then Exit;               { View left of locked }
+       If (X1 > ViewPort.X2) Then Exit;               { View right of locked }
+       If (Y2 < ViewPort.Y1) Then Exit;               { View above locked }
+       If (Y1 > ViewPort.Y2) Then Exit;               { View below locked }
+       If (X1 < ViewPort.X1) Then X1 := ViewPort.X1;  { Adjust x1 to locked }
+       If (Y1 < ViewPort.Y1) Then Y1 := ViewPort.Y1;  { Adjust y1 to locked }
+       If (X2 > ViewPort.X2) Then X2 := ViewPort.X2;  { Adjust x2 to locked }
+       If (Y2 > ViewPort.Y2) Then Y2 := ViewPort.Y2;  { Adjust y2 to locked }
+     End;
+     SetViewPort(X1, Y1, X2, Y2, ClipOn);             { Set new clip limits }
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 21Sep99 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.DrawBackGround;
+VAR Bc: Byte; X1, Y1, X2, Y2: Integer; ViewPort: ViewPortType;
+{$IFDEF OS_OS2} Ptl: PointL; {$ENDIF}
+BEGIN
+   If (GOptions AND goNoDrawView = 0) Then Begin      { Non draw views exit }
+     If (State AND sfDisabled = 0) Then
+       Bc := GetColor(1) AND $F0 SHR 4 Else           { Select back colour }
+       Bc := GetColor(4) AND $F0 SHR 4;               { Disabled back colour }
+     GetViewSettings(ViewPort);                       { Get view settings }
+     If (ViewPort.X1 <= RawOrigin.X) Then X1 := 0     { Right to left edge }
+       Else X1 := ViewPort.X1-RawOrigin.X;            { Offset from left }
+     If (ViewPort.Y1 <= RawOrigin.Y) Then Y1 := 0     { Right to top edge }
+       Else Y1 := ViewPort.Y1-RawOrigin.Y;            { Offset from top }
+     If (ViewPort.X2 >= RawOrigin.X+RawSize.X) Then
+       X2 := RawSize.X Else                           { Right to right edge }
+       X2 := ViewPort.X2-RawOrigin.X;                 { Offset from right }
+     If (ViewPort.Y2 >= RawOrigin.Y+RawSize.Y) Then
+       Y2 := RawSize.Y Else                           { Right to bottom edge }
+       Y2 := ViewPort.Y2-RawOrigin.Y;                 { Offset from bottom }
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+       SetFillStyle(SolidFill, Bc);                   { Set fill colour }
+       Bar(0, 0, X2-X1, Y2-Y1);                       { Clear the area }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     If (Dc <> 0) Then Begin                          { Valid device context }
+       SelectObject(Dc, ColBrush[Bc]);                { Select brush }
+       SelectObject(Dc, ColPen[Bc]);                  { Select pen }
+       Rectangle(Dc, X1, Y1, X2+1, Y2+1);             { Clear the view area }
+     End;
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (Ps <> 0) Then Begin                          { Valid pres space }
+       GpiSetColor(Ps, ColRef[Bc]);                   { Select colour }
+       Ptl.X := X1;                                   { X1 position }
+       Ptl.Y := RawSize.Y - Y1;                       { Y1 position }
+       GpiMove(PS, Ptl);                              { Move to position }
+       Ptl.X := X2;                                   { X2 position }
+       Ptl.Y := RawSize.Y - Y2;                       { Y2 position }
+       GpiBox(Ps, dro_Fill, Ptl, 0, 0);               { Clear the view area }
+     End;
+     {$ENDIF}
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  ReleaseViewLimits -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 05May98 LdB }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.ReleaseViewLimits;
+VAR P: PComplexArea;
+BEGIN
+   P := HoldLimit;                                    { Transfer pointer }
+   If (P <> Nil) Then Begin                           { Valid complex area }
+     HoldLimit := P^.NextArea;                        { Move to prior area }
+     SetViewPort(P^.X1, P^.Y1, P^.X2, P^.Y2, ClipOn); { Restore clip limits }
+     FreeMem(P, SizeOf(TComplexArea));                { Release memory }
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  MoveTo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.MoveTo (X, Y: Integer);
+VAR R: TRect;
+BEGIN
+   R.Assign(X, Y, X + Size.X, Y + Size.Y);            { Assign area }
+   Locate(R);                                         { Locate the view }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GrowTo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GrowTo (X, Y: Integer);
+VAR R: TRect;
+BEGIN
+   R.Assign(Origin.X, Origin.Y, Origin.X + X,
+     Origin.Y + Y);                                   { Assign area }
+   Locate(R);                                         { Locate the view }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SetDrawMask -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 05Sep99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SetDrawMask (Mask: Byte);
+BEGIN
+   If (Options AND ofFramed = 0) AND                  { Check for no frame }
+     (GOptions AND goThickFramed = 0) AND             { Check no thick frame }
+     (GOptions AND goTitled = 0) Then                 { Check for title }
+       Mask := Mask AND NOT vdBorder;                 { Clear border draw }
+   If (State AND sfCursorVis = 0) Then                { Check for no cursor }
+     Mask := Mask AND NOT vdCursor;                   { Clear cursor draw }
+   If (GOptions AND goDrawFocus = 0) Then             { Check no focus draw }
+     Mask := Mask AND NOT vdFocus;                    { Clear focus draws }
+   DrawMask := DrawMask OR Mask;                      { Set draw masks }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  EndModal -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.EndModal (Command: Word);
+VAR P: PView;
+BEGIN
+   P := TopView;                                      { Get top view }
+   If (P <> Nil) Then P^.EndModal(Command);           { End modal operation }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SetCursor -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SetCursor (X, Y: Integer);
+BEGIN
+   Cursor.X := X;                                     { New x position }
+   Cursor.Y := Y;                                     { New y position }
+   If (State AND sfCursorVis <> 0) Then Begin         { Cursor visible }
+     SetDrawMask(vdCursor);                           { Set draw mask }
+     DrawView;                                        { Draw the cursor }
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  PutInFrontOf -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 29Sep99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.PutInFrontOf (Target: PView);
+VAR P, LastView: PView;
+BEGIN
+   If (Owner <> Nil) AND (Target <> @Self) AND
+   (Target <> NextView) AND ((Target = Nil) OR
+   (Target^.Owner = Owner)) Then                      { Check validity }
+     If (State AND sfVisible = 0) Then Begin          { View not visible }
+       Owner^.RemoveView(@Self);                      { Remove from list }
+       Owner^.InsertView(@Self, Target);              { Insert into list }
+     End Else Begin
+       LastView := NextView;                          { Hold next view }
+       If (LastView <> Nil) Then Begin                { Lastview is valid }
+         P := Target;                                 { P is target }
+         While (P <> Nil) AND (P <> LastView)
+           Do P := P^.NextView;                       { Find our next view }
+         If (P = Nil) Then LastView := Target;        { Lastview is target }
+       End;
+       State := State AND NOT sfVisible;              { Temp stop drawing }
+       If (LastView = Target) Then
+         If (Owner <> Nil) Then Owner^.ReDrawArea(
+           RawOrigin.X, RawOrigin.Y, RawOrigin.X +
+           RawSize.X, RawOrigin.Y + RawSize.Y);       { Redraw old area }
+       Owner^.RemoveView(@Self);                      { Remove from list }
+       Owner^.InsertView(@Self, Target);              { Insert into list }
+       State := State OR sfVisible;                   { Allow drawing again }
+       If (LastView <> Target) Then DrawView;         { Draw the view now }
+       If (Options AND ofSelectable <> 0) Then        { View is selectable }
+         If (Owner <> Nil) Then Owner^.ResetCurrent;  { Reset current }
+     End;
+END;
+
+{ ******************************* REMARK ****************************** }
+{   The original TV origin data is only adjusted incase the user uses   }
+{  the values directly. New views should rely only on RawOrigin values. }
+{ ****************************** END REMARK *** Leon de Boer, 15May98 * }
+
+{--TView--------------------------------------------------------------------}
+{  DisplaceBy -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.DisplaceBy (Dx, Dy: Integer);
+BEGIN
+   RawOrigin.X := RawOrigin.X + Dx;                   { Displace raw x }
+   RawOrigin.Y := RawOrigin.Y + Dy;                   { Displace raw y }
+   Origin.X := RawOrigin.X DIV FontWidth;             { Calc new x origin }
+   Origin.Y := RawOrigin.Y DIV FontHeight;            { Calc new y origin }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SetCommands -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SetCommands (Commands: TCommandSet);
+BEGIN
+   CommandSetChanged := CommandSetChanged OR
+     (CurCommandSet <> Commands);                     { Set change flag }
+   CurCommandSet := Commands;                         { Set command set }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  ReDrawArea -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 05May98 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.ReDrawArea (X1, Y1, X2, Y2: Integer);
+VAR HLimit: PView; ViewPort: ViewPortType;
+BEGIN
+   GetViewSettings(ViewPort);                         { Hold view port }
+   SetViewPort(X1, Y1, X2, Y2, ClipOn);               { Set new clip limits }
+   HLimit := LimitsLocked;                            { Hold lock limits }
+   LimitsLocked := @Self;                             { We are the lock view }
+   DrawView;                                          { Redraw the area }
+   LimitsLocked := HLimit;                            { Release our lock }
+   SetViewPort(ViewPort.X1, ViewPort.Y1,
+     ViewPort.X2, ViewPort.Y2, ClipOn);               { Reset old limits }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  EnableCommands -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.EnableCommands (Commands: TCommandSet);
+BEGIN
+   CommandSetChanged := CommandSetChanged OR
+     (CurCommandSet * Commands <> Commands);          { Set changed flag }
+   CurCommandSet := CurCommandSet + Commands;         { Update command set }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  DisableCommands -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB   }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.DisableCommands (Commands: TCommandSet);
+BEGIN
+   CommandSetChanged := CommandSetChanged OR
+     (CurCommandSet * Commands <> []);                { Set changed flag }
+   CurCommandSet := CurCommandSet - Commands;         { Update command set }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23Sep99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SetState (AState: Word; Enable: Boolean);
+VAR Command: Word;
+BEGIN
+   If Enable Then State := State OR AState            { Set state mask }
+     Else State := State AND NOT AState;              { Clear state mask }
+   If (AState AND sfVisible <> 0) Then Begin          { Visibilty change }
+     If (Owner <> Nil) AND                            { valid owner }
+     (Owner^.State AND sfExposed <> 0)                { If owner exposed }
+       Then SetState(sfExposed, Enable);              { Expose this view }
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+     If Enable Then DrawView Else                     { Draw the view }
+       If (Owner <> Nil) Then Owner^.ReDrawArea(      { Owner valid }
+         RawOrigin.X, RawOrigin.Y, RawOrigin.X +
+         RawSize.X, RawOrigin.Y + RawSize.Y);         { Owner redraws area }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     If (HWindow <> 0) Then Begin                     { Window handle valid }
+       If Enable Then ShowWindow(HWindow, sw_Show)    { Show the window }
+         Else ShowWindow(HWindow, sw_Hide);           { Hide the window }
+     End;
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (HWindow <> 0) Then Begin                     { Window handle valid }
+       If Enable Then WinSetWindowPos(HWindow, 0, 0,
+         0, 0, 0, swp_Show)                           { Show the window }
+       Else WinSetWindowPos(HWindow, 0, 0, 0, 0, 0,
+         swp_Hide);                                   { Hide the window }
+     End;
+     {$ENDIF}
+     If (Options AND ofSelectable <> 0) Then          { View is selectable }
+       If (Owner <> Nil) Then Owner^.ResetCurrent;    { Reset selected }
+   End;
+   If (AState AND sfFocused <> 0) Then Begin          { Focus change }
+     If (Owner <> Nil) Then Begin                     { Owner valid }
+       If Enable Then Command := cmReceivedFocus      { View gaining focus }
+         Else Command := cmReleasedFocus;             { View losing focus }
+       Message(Owner, evBroadcast, Command, @Self);   { Send out message }
+     End;
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     If (HWindow <> 0) Then                           { Window handle valid }
+       If Enable Then SetFocus(HWindow);              { Focus the window }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (HWindow <> 0) Then                           { Window handle valid }
+       If Enable Then WinSetFocus(HWND_DESKTOP,
+         HWindow);                                    { Focus the window }
+     {$ENDIF}
+     If (GOptions AND goDrawFocus <> 0) Then Begin    { Draw focus view }
+       SetDrawMask(vdFocus);                          { Set focus draw mask }
+       DrawView;                                      { Redraw focus change }
+     End;
+   End;
+   If (AState AND (sfCursorVis + sfCursorIns) <> 0)   { Change cursor state }
+   Then Begin
+     SetDrawMask(vdCursor);                           { Set cursor draw mask }
+     DrawView;                                        { Redraw the cursor }
+   End;
+   If (AState AND sfDisabled <> 0) Then Begin         { Disbale change }
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     If (HWindow <> 0) Then                           { Window handle valid }
+       If Enable Then EnableWindow(HWindow, False)    { Disable the window }
+         Else EnableWindow(HWindow, True);            { Enable the window }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (HWindow <> 0) Then                           { Window handle valid }
+       If Enable Then WinEnableWindow(HWindow,False)  { Disable the window }
+         Else WinEnableWindow(HWindow, True);         { Enable the window }
+     {$ENDIF}
+   End;
+   If (AState AND sfShadow <> 0) Then Begin End;      { Change shadow state }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SetCmdState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SetCmdState (Commands: TCommandSet; Enable: Boolean);
+BEGIN
+   If Enable Then EnableCommands(Commands)            { Enable commands }
+     Else DisableCommands(Commands);                  { Disable commands }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GetData (Var Rec);
+BEGIN                                                 { Abstract method }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SetData (Var Rec);
+BEGIN                                                 { Abstract method }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06May98 LdB             }
+{---------------------------------------------------------------------------}
+{  You can save data to the stream compatable with the old original TV by   }
+{  temporarily turning off the ofGFVModeView making the call to this store  }
+{  routine and resetting the ofGFVModeView flag after the call.             }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.Store (Var S: TStream);
+VAR SaveState: Word;
+BEGIN
+   SaveState := State;                                { Hold current state }
+   State := State AND NOT (sfActive OR sfSelected OR
+     sfFocused OR sfExposed);                         { Clear flags }
+   S.Write(Origin.X, 2);                              { Write view x origin }
+   S.Write(Origin.Y, 2);                              { Write view y origin }
+   S.Write(Size.X, 2);                                { Write view x size }
+   S.Write(Size.Y, 2);                                { Write view y size }
+   S.Write(Cursor.X, 2);                              { Write cursor x size }
+   S.Write(Cursor.Y, 2);                              { Write cursor y size }
+   S.Write(GrowMode, 1);                              { Write growmode flags }
+   S.Write(DragMode, 1);                              { Write dragmode flags }
+   S.Write(HelpCtx, 2);                               { Write help context }
+   S.Write(State, 2);                                 { Write state masks }
+   S.Write(Options, 2);                               { Write options masks }
+   S.Write(Eventmask, 2);                             { Write event masks }
+   If (Options AND ofGFVModeView <> 0) Then Begin     { GFV GRAPHICAL TVIEW }
+     S.Write(GOptions, 2);                            { Write new option masks }
+     S.Write(TabMask, 1);                             { Write new tab masks }
+     S.Write(RawOrigin.X, 2);                         { Write raw origin x point }
+     S.Write(RawOrigin.Y, 2);                         { Write raw origin y point }
+     S.Write(RawSize.X, 2);                           { Write raw x size }
+     S.Write(RawSize.Y, 2);                           { Write raw y size }
+     S.Write(ColourOfs, 2);                           { Write Palette offset }
+   End;
+   State := SaveState;                                { Reset state masks }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  Locate -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24Sep99 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.Locate (Var Bounds: TRect);
+VAR {$IFDEF OS_DOS} X1, Y1, X2, Y2: Integer; {$ENDIF}
+    Min, Max: TPoint; R: TRect;
+
+   FUNCTION Range(Val, Min, Max: Integer): Integer;
+   BEGIN
+     If (Val < Min) Then Range := Min Else            { Value to small }
+       If (Val > Max) Then Range := Max Else          { Value to large }
+         Range := Val;                                { Value is okay }
+   END;
+
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+   X1 := RawOrigin.X;                                 { Current x origin }
+   Y1 := RawOrigin.Y;                                 { Current y origin }
+   X2 := RawOrigin.X + RawSize.X;                     { Current x size }
+   Y2 := RawOrigin.Y + RawSize.Y;                     { Current y size }
+   {$ENDIF}
+   SizeLimits(Min, Max);                              { Get size limits }
+   Bounds.B.X := Bounds.A.X + Range(Bounds.B.X -
+     Bounds.A.X, Min.X, Max.X);                       { X bound limit }
+   Bounds.B.Y := Bounds.A.Y + Range(Bounds.B.Y
+     - Bounds.A.Y, Min.Y, Max.Y);                     { Y bound limit }
+   GetBounds(R);                                      { Current bounds }
+   If NOT Bounds.Equals(R) Then Begin                 { Size has changed }
+     ChangeBounds(Bounds);                            { Change bounds }
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+     If (State AND sfVisible <> 0) AND                { View is visible }
+     (State AND sfExposed <> 0) AND (Owner <> Nil)    { Check view exposed }
+       Then Owner^.ReDrawArea(X1, Y1, X2, Y2);        { Owner redraw }
+     DrawView;                                        { Redraw the view }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     If (HWindow <> 0) Then Begin                     { Valid window handle }
+       If (Owner <> Nil) AND (Owner^.HWindow <> 0)    { Valid owner }
+       Then MoveWindow(HWindow, RawOrigin.X-Owner^.RawOrigin.X,
+         RawOrigin.Y-Owner^.RawOrigin.Y, RawSize.X+1,
+         RawSize.Y+1, True) Else                      { Move window in owner }
+       MoveWindow(HWindow, RawOrigin.X, RawOrigin.Y,
+         RawSize.X+1, RawSize.Y+1, True);             { Move window raw }
+     End;
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     If (HWindow <> 0) Then Begin                     { Valid window handle }
+       If (Owner <> Nil) AND (Owner^.HWindow <> 0)    { Valid owner }
+       Then WinSetWindowPos(HWindow, 0,
+         RawOrigin.X - Owner^.RawOrigin.X,
+         (Owner^.RawOrigin.Y + Owner^.RawSize.Y) -
+         (RawOrigin.Y + RawSize.Y), RawSize.X,
+         RawSize.Y, swp_Size OR swp_Move) Else        { Move window in owner }
+       WinSetWindowPos(HWindow, 0, RawOrigin.X,
+         SysScreenHeight - (RawOrigin.Y + RawSize.Y),
+         RawSize.X, RawSize.Y, swp_Size OR swp_Move); { Move window raw }
+     End;
+     {$ENDIF}
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  KeyEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.KeyEvent (Var Event: TEvent);
+BEGIN
+   Repeat
+     GetEvent(Event);                                 { Get next event }
+   Until (Event.What = evKeyDown);                    { Wait till keydown }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GetEvent (Var Event: TEvent);
+BEGIN
+  If (Owner <> Nil) Then Owner^.GetEvent(Event);      { Event from owner }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  PutEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.PutEvent (Var Event: TEvent);
+BEGIN
+   If (Owner <> Nil) Then Owner^.PutEvent(Event);     { Put in owner }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetExtent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GetExtent (Var Extent: TRect);
+BEGIN
+   Extent.A.X := 0;                                   { Zero x field }
+   Extent.A.Y := 0;                                   { Zero y field }
+   Extent.B.X := Size.X;                              { Return x size }
+   Extent.B.Y := Size.Y;                              { Return y size }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetBounds -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GetBounds (Var Bounds: TRect);
+BEGIN
+   Bounds.A := Origin;                                { Get first corner }
+   Bounds.B.X := Origin.X + Size.X;                   { Calc corner x value }
+   Bounds.B.Y := Origin.Y + Size.Y;                   { Calc corner y value }
+   If (Owner <> Nil) Then
+     Bounds.Move(-Owner^.Origin.X, -Owner^.Origin.Y); { Sub owner offset }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SetBounds -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 24Sep99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SetBounds (Var Bounds: TRect);
+VAR D, COrigin: TPoint;
+BEGIN
+   If (Bounds.B.X > 0) AND (Bounds.B.Y > 0)           { Normal text co-ords }
+   AND (GOptions AND goGraphView = 0) Then Begin      { Normal text view }
+     If (Owner <> Nil) Then Begin                     { Owner is valid }
+       COrigin.X := Origin.X - Owner^.Origin.X;       { Corrected x origin }
+       COrigin.Y := Origin.Y - Owner^.Origin.Y;       { Corrected y origin }
+       D.X := Bounds.A.X - COrigin.X;                 { X origin disp }
+       D.Y := Bounds.A.Y - COrigin.Y;                 { Y origin disp }
+       If ((D.X <> 0) OR (D.Y <> 0)) Then
+         DisplaceBy(D.X*FontWidth, D.Y*FontHeight);   { Offset the view }
+     End Else Origin := Bounds.A;                     { Hold as origin }
+     Size.X := Bounds.B.X-Bounds.A.X;                 { Hold view x size }
+     Size.Y := Bounds.B.Y-Bounds.A.Y;                 { Hold view y size }
+     RawOrigin.X := Origin.X * FontWidth;             { Raw x origin }
+     RawOrigin.Y := Origin.Y * FontHeight;            { Raw y origin }
+     RawSize.X := Size.X * FontWidth - 1;             { Set raw x size }
+     RawSize.Y := Size.Y * FontHeight - 1;            { Set raw y size }
+   End Else Begin                                     { Graphical co-ords }
+     If (Owner <> Nil) Then Begin                     { Owner is valid }
+       COrigin.X := RawOrigin.X - Owner^.RawOrigin.X; { Corrected x origin }
+       COrigin.Y := RawOrigin.Y - Owner^.RawOrigin.Y; { Corrected y origin }
+       D.X := Bounds.A.X - COrigin.X;                 { X origin disp }
+       D.Y := Bounds.A.Y - COrigin.Y;                 { Y origin disp }
+       If ((D.X <> 0) OR (D.Y <> 0)) Then
+         DisplaceBy(D.X, D.Y);                        { Offset the view }
+     End Else RawOrigin := Bounds.A;                  { Hold as origin }
+     RawSize.X := Abs(Bounds.B.X) - Bounds.A.X;       { Set raw x size }
+     RawSize.Y := Abs(Bounds.B.Y) - Bounds.A.Y;       { Set raw y size }
+     Origin.X := RawOrigin.X DIV FontWidth;           { Rough x position }
+     Origin.Y := RawOrigin.Y DIV FontHeight;          { Rough y position }
+     Size.X := RawSize.X DIV FontWidth;               { Rough x size }
+     Size.Y := RawSize.Y DIV FontHeight;              { Rough y size }
+   End;
+   Options := Options OR ofGFVModeView;               { Now in GFV mode }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetClipRect -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GetClipRect (Var Clip: TRect);
+BEGIN
+   GetBounds(Clip);                                   { Get current bounds }
+   If (Owner <> Nil) Then Clip.Intersect(Owner^.Clip);{ Intersect with owner }
+   Clip.Move(-Origin.X, -Origin.Y);                   { Sub owner origin }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  ClearEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.ClearEvent (Var Event: TEvent);
+BEGIN
+   Event.What := evNothing;                           { Clear the event }
+   Event.InfoPtr := @Self;                            { Set us as handler }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.HandleEvent (Var Event: TEvent);
+BEGIN
+   If (Event.What = evMouseDown) Then                 { Mouse down event }
+     If (State AND (sfSelected OR sfDisabled) = 0)    { Not selected/disabled }
+       AND (Options AND ofSelectable <> 0) Then       { View is selectable }
+       If (Focus = False) OR                          { Not view with focus }
+         (Options AND ofFirstClick = 0)               { Not 1st click select }
+           Then ClearEvent(Event);                    { Handle the event }
+   If (Event.What = evKeyDown) AND                    { Key down event }
+   (Options OR ofGFVModeView <> 0) Then Begin         { GFV mode view check }
+     If (Owner <> Nil) AND (TabMask <> 0) AND         { Owner and tab masks }
+     (State AND sfFocused <> 0) Then Begin            { View has focus }
+       Case Event.KeyCode Of
+         kbTab: If (TabMask AND tmTab <> 0) Then      { Tab key mask set }
+           Owner^.FocusNext(False) Else Exit;         { Focus next view }
+         kbEnter: If (TabMask AND tmEnter <> 0) Then  { Enter key mask set }
+           Owner^.FocusNext(False) Else Exit;         { Focus next view }
+         kbShiftTab: If (TabMask AND tmShiftTab <> 0) { Shit tab mask set }
+           Then Owner^.FocusNext(True) Else Exit;     { Focus prior view }
+         kbLeft: If (TabMask AND tmLeft <> 0) Then    { Left arrow mask set }
+           Owner^.FocusNext(True) Else Exit;          { Focus prior view }
+         kbRight: If (TabMask AND tmRight <> 0) Then  { Right arrow mask set }
+           Owner^.FocusNext(False) Else Exit;         { Focus next view }
+         kbUp: If (TabMask AND tmUp <> 0) Then        { Up arrow mask set }
+           Owner^.FocusNext(True) Else Exit;          { Focus prior view }
+         kbDown: If (TabMask AND tmDown <> 0) Then    { Down arrow mask set }
+           Owner^.FocusNext(False) Else Exit;         { Focus next view }
+         Else Exit;                                   { Not a tab key }
+       End;
+       ClearEvent(Event);                             { Clear handled events }
+     End;
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  ChangeBounds -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.ChangeBounds (Var Bounds: TRect);
+BEGIN
+   SetBounds(Bounds);                                 { Set new bounds }
+   DrawView;                                          { Draw the view }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  SizeLimits -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.SizeLimits (Var Min, Max: TPoint);
+BEGIN
+   Min.X := 0;                                        { Zero x minimum }
+   Min.Y := 0;                                        { Zero y minimum }
+   If (Owner = Nil) Then Begin
+     Max.X := $7FFF;                                  { Max possible x size }
+     Max.Y := $7FFF;                                  { Max possible y size }
+   End Else Max := Owner^.Size;                       { Max owner size }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetCommands -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GetCommands (Var Commands: TCommandSet);
+BEGIN
+   Commands := CurCommandSet;                         { Return command set }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetPeerViewPtr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GetPeerViewPtr (Var S: TStream; Var P);
+VAR Index: Integer;
+BEGIN
+   Index := 0;                                        { Zero index value }
+   S.Read(Index, 2);                                  { Read view index }
+   If (Index = 0) OR (OwnerGroup = Nil) Then          { Check for peer views }
+     Pointer(P) := Nil Else Begin                     { Return nil }
+       Pointer(P) := FixupList^[Index];               { New view ptr }
+       FixupList^[Index] := @P;                       { Patch this pointer }
+     End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  PutPeerViewPtr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.PutPeerViewPtr (Var S: TStream; P: PView);
+VAR Index: Integer;
+BEGIN
+   If (P = Nil) OR (OwnerGroup = Nil) Then Index := 0 { Return zero index }
+     Else Index := OwnerGroup^.IndexOf(P);            { Return view index }
+   S.Write(Index, 2);                                 { Write the index }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  CalcBounds -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.CalcBounds (Var Bounds: TRect; Delta: TPoint);
+VAR S, D: Integer; Min, Max: TPoint;
+
+   FUNCTION Range (Val, Min, Max: Integer): Integer;
+   BEGIN
+     If (Val < Min) Then Range := Min Else            { Value below min }
+     If (Val > Max) Then Range := Max Else            { Value above max }
+       Range := Val;                                  { Accept value }
+   END;
+
+   PROCEDURE Grow (Var I: Integer);
+   BEGIN
+     If (GrowMode AND gfGrowRel = 0) Then Inc(I, D)
+       Else I := (I * S + (S - D) SHR 1) DIV (S - D); { Calc grow value }
+   END;
+
+BEGIN
+   GetBounds(Bounds);                                 { Get bounds }
+   If (GrowMode = 0) Then Exit;                       { No grow flags exits }
+   S := Owner^.Size.X;                                { Set initial size }
+   D := Delta.X;                                      { Set initial delta }
+   If (GrowMode AND gfGrowLoX <> 0) Then
+     Grow(Bounds.A.X);                                { Grow left side }
+   If (GrowMode AND gfGrowHiX <> 0) Then
+     Grow(Bounds.B.X);                                { Grow right side }
+   If (Bounds.B.X - Bounds.A.X > MaxViewWidth) Then
+     Bounds.B.X := Bounds.A.X + MaxViewWidth;         { Check values }
+   S := Owner^.Size.Y; D := Delta.Y;                  { set initial values }
+   If (GrowMode AND gfGrowLoY <> 0) Then
+     Grow(Bounds.A.Y);                                { Grow top side }
+   If (GrowMode AND gfGrowHiY <> 0) Then
+     Grow(Bounds.B.Y);                                { grow lower side }
+   SizeLimits(Min, Max);                              { Check sizes }
+   Bounds.B.X := Bounds.A.X + Range(Bounds.B.X -
+     Bounds.A.X, Min.X, Max.X);                       { Set right side }
+   Bounds.B.Y := Bounds.A.Y + Range(Bounds.B.Y -
+     Bounds.A.Y, Min.Y, Max.Y);                       { Set lower side }
+END;
+
+{$IFNDEF OS_DOS}                                      { WIN/NT/OS2 CODE }
+{***************************************************************************}
+{                    TView OBJECT WIN/NT/OS2 ONLY METHODS                   }
+{***************************************************************************}
+
+{--TView--------------------------------------------------------------------}
+{  GetClassId -> Platforms WIN/NT/OS2 - Updated 29Jul99 LdB                 }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetClassId: LongInt;
+BEGIN
+   GetClassId := 0;                                   { No view class id }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetClassName -> Platforms WIN/NT/OS2 - Updated 17Mar98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetClassName: String;
+BEGIN
+   GetClassName := TvViewClassName;                   { View class name }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetClassText -> Platforms WIN/NT/OS2 - Updated 17Mar98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetClassText: String;
+BEGIN
+   GetClassText := '';                                { Return empty string }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetClassAttr -> Platforms WIN/NT/OS2 - Updated 17Mar98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetClassAttr: LongInt;
+VAR Li: LongInt;
+BEGIN
+   If (State AND sfVisible = 0) Then Li := 0          { View not visible }
+     Else Li := ws_Visible;                           { View is visible }
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (State AND sfDisabled <> 0) Then                { Check disabled flag }
+     Li := Li OR ws_Disabled;                         { Set disabled flag }
+   If (GOptions AND goTitled <> 0) Then Begin
+     Li := Li OR ws_Caption;                          { View has a caption }
+     CaptSize := GetSystemMetrics(SM_CYCaption);      { Caption height }
+   End;
+   If (GOptions AND goThickFramed <> 0) Then Begin
+     Li := Li OR ws_ThickFrame;                       { Thick frame on view  }
+     FrameSize := GetSystemMetrics(SM_CXFrame);       { Frame width }
+     If (GOptions AND goTitled = 0) Then
+      CaptSize := GetSystemMetrics(SM_CYFrame);       { Frame height }
+   End Else If (Options AND ofFramed <> 0) Then Begin
+     Li := Li OR ws_Border;                           { Normal frame on view }
+     FrameSize := GetSystemMetrics(SM_CXBorder);      { Frame width }
+     If (GOPtions AND goTitled = 0) Then
+       CaptSize := GetSystemMetrics(SM_CYBorder);     { Frame height }
+   End;
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   Li := Li OR fcf_NoByteAlign;                       { Not byte aligned }
+   If (GOptions AND goTitled <> 0) Then Begin
+     Li := Li OR fcf_TitleBar;                        { View has a caption }
+     CaptSize := WinQuerySysValue(HWND_Desktop,
+       SV_CYTitleBar);                                { Caption height }
+   End;
+   If (GOptions AND goThickFramed <> 0) Then Begin
+     Li := Li OR fcf_DlgBorder;                       { Thick frame on view  }
+     FrameSize := WinQuerySysValue(HWND_DeskTop,
+      SV_CXSizeBorder);                               { Frame width }
+     CaptSize := CaptSize + WinQuerySysValue(
+       HWND_DeskTop, SV_CYSizeBorder);                { Frame height }
+   End Else If (Options AND ofFramed <> 0) Then Begin
+     Li := Li OR fcf_Border;                          { Normal frame on view }
+     FrameSize := WinQuerySysValue(HWND_Desktop,
+       SV_CXBorder);                                  { Frame width }
+     CaptSize := CaptSize + WinQuerySysValue(
+       HWND_DeskTop, SV_CYBorder);                    { Frame height }
+   End;
+   {$ENDIF}
+   Li := Li OR ws_ClipChildren OR ws_ClipSiblings;    { By default clip others }
+   GetClassAttr := Li;                                { Return attributes }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetNotifyCmd -> Platforms WIN/NT/OS2 - Updated 06Aug99 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetNotifyCmd: LongInt;
+BEGIN
+   GetNotifyCmd := -1;                                { No notify cmd }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GetMsgHandler -> Platforms WIN/NT/OS2 - Updated 17Mar98 LdB              }
+{---------------------------------------------------------------------------}
+FUNCTION TView.GetMsgHandler: Pointer;
+BEGIN
+   GetMsgHandler := @TvViewMsgHandler;                { Default msg handler }
+END;
+
+{$ENDIF}
+
+{***************************************************************************}
+{                       TView OBJECT PRIVATE METHODS                        }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TGroup OBJECT METHODS                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TGroup-------------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Jul99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TGroup.Init (Var Bounds: TRect);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   Options := Options OR (ofSelectable + ofBuffered); { Set options }
+   GOptions := GOptions OR goNoDrawView;              { Non drawing view }
+   GetExtent(Clip);                                   { Get clip extents }
+   EventMask := $FFFF;                                { See all events }
+   GOptions := GOptions OR goTabSelect;               { Set graphic options }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TGroup.Load (Var S: TStream);
+VAR I, Count: Word; P, Q: ^Pointer; V: PView; OwnerSave: PGroup;
+    FixupSave: PFixupList;
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   GetExtent(Clip);                                   { Get view extents }
+   OwnerSave := OwnerGroup;                           { Save current group }
+   OwnerGroup := @Self;                               { We are current group }
+   FixupSave := FixupList;                            { Save current list }
+   Count := 0;                                        { Zero count value }
+   S.Read(Count, 2);                                  { Read entry count }
+   If (MaxAvail >= Count*SizeOf(Pointer)) Then Begin  { Memory available }
+     GetMem(FixupList, Count*SizeOf(Pointer));        { List size needed }
+     FillChar(FixUpList^, Count*SizeOf(Pointer), #0); { Zero all entries }
+     For I := 1 To Count Do Begin
+       V := PView(S.Get);                             { Get view off stream }
+       If (V <> Nil) Then InsertView(V, Nil);         { Insert valid views }
+     End;
+     V := Last;                                       { Start on last view }
+     For I := 1 To Count Do Begin
+       V := V^.Next;                                  { Fetch next view }
+       P := FixupList^[I];                            { Transfer pointer }
+       While (P <> Nil) Do Begin                      { If valid view }
+         Q := P;                                      { Copy pointer }
+         P := P^;                                     { Fetch pointer }
+         Q^ := V;                                     { Transfer view ptr }
+       End;
+     End;
+     FreeMem(FixupList, Count*SizeOf(Pointer));       { Release fixup list }
+   End;
+   OwnerGroup := OwnerSave;                           { Reload current group }
+   FixupList := FixupSave;                            { Reload current list }
+   GetSubViewPtr(S, V);                               { Load any subviews }
+   SetCurrent(V, NormalSelect);                       { Select current view }
+   If (OwnerGroup = Nil) Then Awaken;                 { If topview activate }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TGroup.Done;
+VAR P, T: PView;
+BEGIN
+   Hide;                                              { Hide the view }
+   P := Last;                                         { Start on last }
+   If (P <> Nil) Then Begin                           { Subviews exist }
+     Repeat
+       P^.Hide;                                       { Hide each view }
+       P := P^.Prev;                                  { Prior view }
+     Until (P = Last);                                { Loop complete }
+     Repeat
+       T := P^.Prev;                                  { Hold prior pointer }
+       Dispose(P, Done);                              { Dispose subview }
+       P := T;                                        { Transfer pointer }
+     Until (Last = Nil);                              { Loop complete }
+   End;
+   Inherited Done;                                    { Call ancestor }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  First -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.First: PView;
+BEGIN
+   If (Last = Nil) Then First := Nil                  { No first view }
+     Else First := Last^.Next;                        { Return first view }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  Execute -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.Execute: Word;
+VAR Event: TEvent;
+BEGIN
+   Repeat
+     EndState := 0;                                   { Clear end state }
+     Repeat
+       GetEvent(Event);                               { Get next event }
+       HandleEvent(Event);                            { Handle the event }
+       If (Event.What <> evNothing) Then
+         EventError(Event);                           { Event not handled }
+     Until (EndState <> 0);                           { Until command set }
+   Until Valid(EndState);                             { Repeat until valid }
+   Execute := EndState;                               { Return result }
+   EndState := 0;                                     { Clear end state }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  GetHelpCtx -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.GetHelpCtx: Word;
+VAR H: Word;
+BEGIN
+   H := hcNoContext;                                  { Preset no context }
+   If (Current <> Nil) Then H := Current^.GetHelpCtx; { Current context }
+   If (H=hcNoContext) Then H := Inherited GetHelpCtx; { Call ancestor }
+   GetHelpCtx := H;                                   { Return result }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  DataSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Jul98 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.DataSize: Word;
+VAR Total: Word; P: PView;
+BEGIN
+   Total := 0;                                        { Zero totals count }
+   P := Last;                                         { Start on last view }
+   If (P <> Nil) Then Begin                           { Subviews exist }
+     Repeat
+       P := P^.Next;                                  { Move to next view }
+       Total := Total + P^.DataSize;                  { Add view size }
+     Until (P = Last);                                { Until last view }
+   End;
+   DataSize := Total;                                 { Return data size }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  ExecView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Jul99 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.ExecView (P: PView): Word;
+VAR SaveOptions: Word; SaveTopView, SaveCurrent: PView; SaveOwner: PGroup;
+    SaveCommands: TCommandSet;
+BEGIN
+   If (P<>Nil) Then Begin
+     SaveOptions := P^.Options;                       { Hold options }
+     SaveOwner := P^.Owner;                           { Hold owner }
+     SaveTopView := TheTopView;                       { Save topmost view }
+     SaveCurrent := Current;                          { Save current view }
+     GetCommands(SaveCommands);                       { Save commands }
+     TheTopView := P;                                 { Set top view }
+     P^.Options := P^.Options AND NOT ofSelectable;   { Not selectable }
+     P^.SetState(sfModal, True);                      { Make modal }
+     SetCurrent(P, EnterSelect);                      { Select next }
+     If (SaveOwner = Nil) Then Insert(P);             { Insert view }
+     ExecView := P^.Execute;                          { Execute view }
+     If (SaveOwner = Nil) Then Delete(P);             { Remove view }
+     SetCurrent(SaveCurrent, LeaveSelect);            { Unselect current }
+     P^.SetState(sfModal, False);                     { Clear modal state }
+     P^.Options := SaveOptions;                       { Restore options }
+     TheTopView := SaveTopView;                       { Restore topview }
+     SetCommands(SaveCommands);                       { Restore commands }
+   End Else ExecView := cmCancel;                     { Return cancel }
+END;
+
+{ ********************************* REMARK ******************************** }
+{    This call really is very COMPILER SPECIFIC and really can't be done    }
+{    effectively any other way but assembler code as SELF & FRAMES need     }
+{    to be put down in exact order and OPTIMIZERS make a mess of it.        }
+{ ******************************** END REMARK *** Leon de Boer, 17Jul99 *** }
+
+{--TGroup-------------------------------------------------------------------}
+{  FirstThat -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Jul99 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.FirstThat (P: Pointer): PView; ASSEMBLER;
+{&USES EBX, ECX, ESI, EDI} {&FRAME-}
+{$IFDEF BIT_16} VAR HoldLast: Pointer; {$ENDIF}
+{$IFDEF BIT_16}                                       { 16 BIT CODE }
+ASM
+   LES DI, Self;                                      { Load self pointer }
+   LES DI, ES:[DI].TGroup.Last;                       { Fetch last view }
+   MOV AX, ES;
+   OR AX, DI;                                         { Check for nil }
+   JZ @@Exit;                                         { No subviews exit }
+   MOV WORD PTR HoldLast[2], ES;
+   MOV WORD PTR HoldLast[0], DI;                      { Hold this last view }
+@@LoopPoint:
+   LES DI, ES:[DI].TView.Next;                        { Move to next view }
+   PUSH ES;                                           { * Save this view for }
+   PUSH DI;                                           { post call to proc P * }
+   PUSH ES;
+   PUSH DI;                                           { Push view for proc P }
+   MOV AX, [BP];                                      { Get our frame }
+   {$IFNDEF OS_DOS}                                   { WIN/OS2 CODE }
+   AND AL, 0FEH;                                      { Must be even }
+   {$ENDIF}
+   PUSH AX;                                           { Push this frame }
+   CALL P;                                            { Call the procedure P }
+   POP DI;                                            { * Restore the view }
+   POP ES;                                            { we saved above * }
+   OR AL, AL;                                         { Look for true result }
+   JNZ @@TrueReturned;                                { Branch if true }
+   CMP DI, WORD PTR HoldLast[0];                      { HoldLast ofs match? }
+   JNZ @@LoopPoint;                                   { No match the continue }
+   MOV AX, ES;
+   CMP AX, WORD PTR HoldLast[2];                      { HoldLast seg match? }
+   JNZ @@LoopPoint;                                   { No match continue }
+   XOR DI, DI;
+   MOV ES, DI;                                        { No matches return nil }
+@@TrueReturned:
+    MOV SP, BP;                                       { Restore stack pointer }
+@@Exit:
+    MOV AX, DI;
+    MOV DX, ES;                                       { Return result pointer }
+END;
+{$ENDIF}
+{$IFDEF BIT_32}                                       { 32 BIT CODE }
+
+   {$IFNDEF PPC_FPC}                                  { NONE FPC COMPILERS }
+   ASM
+     MOV EAX, Self;                                   { Fetch self pointer }
+     MOV EAX, [EAX].TGroup.Last;                      { Fetch last view }
+     OR EAX, EAX;                                     { Check for nil }
+     JZ @@Exit;                                       { No subviews exit }
+     MOV ECX, EAX;                                    { Hold this last view }
+     MOV EBX, P;                                      { Procedure to call }
+   @@LoopPoint:
+     MOV EAX, [EAX].TView.Next;                       { Fetch next view }
+     PUSH ECX;                                        { Save holdlast view }
+     PUSH EBX;                                        { Save procedure address }
+     PUSH EAX;                                        { Save for recovery }
+     PUSH EAX;                                        { [1]:Pointer = PView }
+     {$IFDEF PPC_SPEED}                               { SPEEDSOFT SYBIL 2.0+ }
+     DB $66;
+     DB $FF;
+     DB $D1;                                          { Doesn't know CALL ECX }
+     {$ELSE}
+     CALL EBX;                                        { Call the test function }
+     {$ENDIF}
+     TEST AL, AL;                                     { True result check }
+     POP EAX;                                         { PView recovered }
+     POP EBX;                                         { Restore procedure addr }
+     POP ECX;                                         { Restore holdlast view }
+     JNZ @@Exit;                                      { Exit if true }
+     CMP EAX, ECX;                                    { Check if last view }
+     JNZ @@LoopPoint;                                 { Reloop if not last }
+     XOR EAX, EAX;                                    { No matches return nil }
+   @@Exit:
+   END;
+   {$ELSE}                                            { FPC COMPILER }
+   ASM
+     MOVL 8(%EBP), %ESI;                              { Self pointer }
+     MOVL TGroup.Last(%ESI), %EAX;                    { Load last view }
+     ORL %EAX, %EAX;                                  { Check for nil }
+     JZ .L_Exit;                                      { No subviews exit }
+     MOVL %EAX, %ECX;                                 { Hold last view }
+     MOVL P, %EBX;                                    { Procedure to call }
+   .L_LoopPoint:
+     MOVL TView.Next(%EAX), %EAX;                     { Fetch next pointer }
+     PUSHL %ECX;                                      { Save holdlast view }
+     PUSHL %EBX;                                      { Save procedure address }
+     PUSHL %EAX;                                      { Save for recovery }
+     PUSHL %EAX;                                      { PView pushed }
+     MOVL (%EBP), %EAX;                               { Fetch self ptr }
+     PUSH %EAX;                                       { Push self ptr }
+     CALL %EBX;                                       { Call the procedure }
+     ORB %AL, %AL;                                    { Test for true }
+     POPL %EAX;                                       { Recover next PView }
+     POPL %EBX;                                       { Restore procedure addr }
+     POPL %ECX;                                       { Restore holdlast view }
+     JNZ .L_Exit;                                     { Call returned true }
+     CMPL %ECX, %EAX;                                 { Check if last view }
+     JNZ .L_LoopPoint;                                { Continue to last }
+     XOR %EAX, %EAX;                                  { No views gave true }
+   .L_Exit:
+     MOVL %EAX, -4(%EBP);                             { Return result }
+   END;
+  {$ENDIF}
+
+{$ENDIF}
+
+{--TGroup-------------------------------------------------------------------}
+{  Valid -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB             }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.Valid (Command: Word): Boolean;
+
+   FUNCTION IsInvalid (P: PView): Boolean; FAR;
+   BEGIN
+     IsInvalid := NOT P^.Valid(Command);              { Check if valid }
+   END;
+
+BEGIN
+   Valid := True;                                     { Preset valid }
+   If (Command = cmReleasedFocus) Then Begin          { Release focus cmd }
+     If (Current <> Nil) AND                          { Current view exists }
+       (Current^.Options AND ofValidate <> 0) Then    { Validating view }
+         Valid := Current^.Valid(Command);            { Validate command }
+   End Else Valid := FirstThat(@IsInvalid) = Nil;     { Check first valid }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  FocusNext -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB         }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.FocusNext (Forwards: Boolean): Boolean;
+VAR P: PView;
+BEGIN
+   P := FindNext(Forwards);                           { Find next view }
+   FocusNext := True;                                 { Preset true }
+   If (P <> Nil) Then FocusNext := P^.Focus;          { Check next focus }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Sep97 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.Draw;
+VAR P: PView;
+BEGIN
+   If (DrawMask AND vdNoChild = 0) Then Begin         { No draw child clear }
+     P := Last;                                       { Start on Last }
+     While (P <> Nil) Do Begin
+       P^.DrawView;                                   { Redraw each subview }
+       P := P^.PrevView;                              { Move to prior view }
+     End;
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  Awaken -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.Awaken;
+
+   PROCEDURE DoAwaken (P: PView); FAR;
+   BEGIN
+     If (P <> Nil) Then P^.Awaken;                    { Awaken view }
+   END;
+
+BEGIN
+   ForEach(@DoAwaken);                                { Awaken each view }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  ReDraw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Sep97 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.ReDraw;
+BEGIN
+   DrawView;                                          { For compatability }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  SelectDefaultView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Oct99 LdB }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.SelectDefaultView;
+VAR P: PView;
+BEGIN
+   P := Last;                                         { Start at last }
+   While (P <> Nil) Do Begin
+     If P^.GetState(sfDefault) Then Begin             { Search 1st default }
+       P^.Select;                                     { Select default view }
+       P := Nil;                                      { Force kick out }
+     End Else P := P^.PrevView;                       { Prior subview }
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  Insert -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 29Sep99 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.Insert (P: PView);
+BEGIN
+   If (P <> Nil) Then                                 { View is valid }
+     If (Options AND ofGFVModeView <> 0) Then         { GFV mode view check }
+       P^.DisplaceBy(RawOrigin.X, RawOrigin.Y) Else   { We are in GFV mode }
+       P^.DisplaceBy(Origin.X*FontWidth,
+         Origin.Y*FontHeight);                        { Displace old view }
+   InsertBefore(P, First);                            { Insert the view }
+   {$IFNDEF OS_DOS}                                   { WIN/NT/OS2 CODE }
+   If (HWindow <> 0) Then                             { We are created }
+     If (P^.HWindow = 0) Then                         { Child not created }
+       P^.CreateWindowNow(0);                         { Create child window }
+   {$ENDIF}
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  Delete -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.Delete (P: PView);
+VAR SaveState: Word;
+BEGIN
+   SaveState := P^.State;                             { Save state }
+   P^.Hide;                                           { Hide the view }
+   RemoveView(P);                                     { Remove the view }
+   P^.Owner := Nil;                                   { Clear owner ptr }
+   P^.Next := Nil;                                    { Clear next ptr }
+   If (SaveState AND sfVisible <> 0) Then P^.Show;    { Show view }
+END;
+
+{ ********************************* REMARK ******************************** }
+{    This call really is very COMPILER SPECIFIC and really can't be done    }
+{    effectively any other way but assembler code as SELF & FRAMES need     }
+{    to be put down in exact order and OPTIMIZERS make a mess of it.        }
+{ ******************************** END REMARK *** Leon de Boer, 17Jul99 *** }
+
+{--TGroup-------------------------------------------------------------------}
+{  ForEach -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 17Jul99 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.ForEach (P: Pointer); ASSEMBLER;
+{&USES EBX, ECX, EDI} {&FRAME-}
+VAR HoldLast: Pointer;
+{$IFDEF BIT_16}                                       { 16 BIT CODE }
+ASM
+   LES DI, Self;                                      { Load self pointer }
+   LES DI, ES:[DI].TGroup.Last;                       { Fetch last view }
+   MOV AX, ES;
+   OR AX, DI;                                         { Check for nil }
+   JZ @@Exit;                                         { No subviews exit }
+   MOV WORD PTR HoldLast[2], ES;
+   MOV WORD PTR HoldLast[0], DI;                      { Hold this last view }
+   LES DI, ES:[DI].TView.Next;                        { Move to next view }
+@@LoopPoint:
+   CMP DI, WORD PTR HoldLast[0];                      { HoldLast ofs match? }
+   JNZ @@2;                                           { No match continue }
+   MOV AX, ES;
+   CMP AX, WORD PTR HoldLast[2];                      { HoldLast seg match? }
+   JZ @@3;                                            { Branch if last }
+@@2:
+   PUSH WORD PTR ES:[DI].TView.Next[2];               { * Save this view }
+   PUSH WORD PTR ES:[DI].TView.Next[0];               { for recovery later * }
+   PUSH ES;
+   PUSH DI;                                           { Push view to test }
+   MOV AX, [BP];                                      { Get our frame }
+   {$IFNDEF OS_DOS}                                   { WIN/OS2 CODE }
+   AND AL, 0FEH;                                      { Must be even }
+   {$ENDIF}
+   PUSH AX;                                           { Push our frame }
+   CALL P;                                            { Call the proc P }
+   POP DI;                                            { * Recover the view }
+   POP ES;                                            { we saved earlier * }
+   JMP @@LoopPoint;                                   { Continue on }
+@@3:
+   MOV AX, [BP];                                      { Get our frame }
+   {$IFNDEF OS_DOS}                                   { WIN/OS2 CODE }
+   AND AL, 0FEH;                                      { Must be even }
+   {$ENDIF}
+   PUSH AX;                                           { Push our frame }
+   CALL P;                                            { Call the proc P }
+@@Exit:
+END;
+{$ENDIF}
+{$IFDEF BIT_32}                                       { 32 BIT CODE }
+
+   {$IFNDEF PPC_FPC}                                  { NON FPC COMPILERS }
+   ASM
+     MOV ECX, Self;                                   { Load self pointer }
+     MOV ECX, [ECX].TGroup.Last;                      { Fetch last view }
+     OR ECX, ECX;                                     { Check for nil }
+     JZ @@Exit;                                       { No subviews exit }
+     MOV HoldLast, ECX;                               { Hold last view }
+     MOV ECX, [ECX].TView.Next;                       { Fetch next pointer }
+     MOV EBX, P;                                      { Fetch proc address }
+   @@LoopPoint:
+     CMP ECX, HoldLast;                               { Check if last view }
+     JZ @@2;                                          { Branch if last view }
+     MOV EAX, [ECX].TView.Next;                       { Fetch next view }
+     PUSH EBX;                                        { Save procedure address }
+     PUSH EAX;                                        { Save next view }
+     {$IFDEF PPC_DELPHI3}                             { DELPHI3+ COMPILER }
+     MOV EAX, ECX;                                    { Use register parameter }
+     MOV ESI, ECX;
+     {$ELSE}                                          { OTHER COMPILERS }
+     PUSH ECX;                                        { Push view to do }
+     {$ENDIF}
+     {$IFDEF PPC_SPEED}                               { SPEEDSOFT SYBIL 2.0+ }
+     DB $66;
+     DB $FF;
+     DB $D3;                                          { Can't do CALL EBX }
+     {$ELSE}
+     CALL EBX;                                        { Call the proc P }
+     {$ENDIF}
+     POP ECX;                                         { Recover saved view }
+     POP EBX;                                         { Recover procedure addr }
+     JMP @@LoopPoint;                                 { Continue on }
+   @@2:
+     {$IFDEF PPC_DELPHI3}                             { DELPHI3+ COMPILERS }
+     MOV EAX, ECX;                                    { Use register parameter }
+     {$ELSE}                                          { OTHER COMPILERS }
+     PUSH ECX;                                        { Push view to do }
+     {$ENDIF}
+     {$IFDEF PPC_SPEED}                               { SPEEDSOFT SYBIL 2.0+ }
+     DB $66;
+     DB $FF;
+     DB $D3;                                          { Can't do CALL EBX }
+     {$ELSE}
+     CALL EBX;                                        { Call the proc P }
+     {$ENDIF}
+   @@Exit:
+   END;
+   {$ELSE}                                            { FPC COMPILER }
+   ASM
+     MOVL 8(%EBP), %ESI;                              { Self pointer }
+     MOVL TGroup.Last(%ESI), %ECX;                    { Load last view }
+     ORL %ECX, %ECX;                                  { Check for nil }
+     JZ .L_Exit;                                      { No subviews exit }
+     MOVL %ECX, HOLDLAST;                             { Hold last view }
+     MOVL TView.Next(%ECX), %ECX;                     { Fetch next pointer }
+   .L_LoopPoint:
+     MOVL P, %EBX;                                    { Fetch proc address }
+     CMPL HOLDLAST, %ECX;                             { Check if last view }
+     JZ .L_2;                                         { Exit if last view }
+     MOVL TView.Next(%ECX), %EAX;                     { Fetch next pointer }
+     PUSHL %EAX;                                      { Save next view ptr }
+     PUSHL %ECX;                                      { Push view to do }
+     MOVL (%EBP), %EAX;
+     PUSH %EAX;
+     CALL %EBX;                                       { Call the procedure }
+     POPL %ECX;                                       { Recover next view  }
+     JMP .L_LoopPoint;                                { Redo loop }
+   .L_2:
+     PUSHL %ECX;                                      { Push view to do }
+     MOVL (%EBP), %EAX;
+     PUSH %EAX;
+     CALL %EBX;                                       { Call the procedure }
+   .L_Exit:
+  END;
+  {$ENDIF}
+
+{$ENDIF}
+
+{--TGroup-------------------------------------------------------------------}
+{  EndModal -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.EndModal (Command: Word);
+BEGIN
+   If (State AND sfModal <> 0) Then                   { This view is modal }
+     EndState := Command Else                         { Set endstate }
+     Inherited EndModal(Command);                     { Call ancestor }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  DisplaceBy -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15May98 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.DisplaceBy (Dx, Dy: Integer);
+VAR P: PView;
+BEGIN
+   P := First;                                        { Get first view }
+   While (P <> Nil) Do Begin
+     P^.DisplaceBy(Dx, Dy);                           { Displace subviews }
+     P := P^.NextView;                                { Next view }
+   End;
+   Inherited DisplaceBy(Dx, Dy);                      { Call ancestor }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  SelectNext -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.SelectNext (Forwards: Boolean);
+VAR P: PView;
+BEGIN
+   P := FindNext(Forwards);                           { Find next view }
+   If (P <> Nil) Then P^.Select;                      { Select view }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  InsertBefore -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 29Sep99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.InsertBefore (P, Target: PView);
+VAR SaveState, I: Word;
+BEGIN
+   If (P <> Nil) AND (P^.Owner = Nil) AND             { View valid }
+   ((Target = Nil) OR (Target^.Owner = @Self))        { Target valid }
+   Then Begin
+     If (P^.Options AND ofCenterX <> 0) Then Begin    { Centre on x axis }
+       If (Options AND ofGFVModeView <> 0) Then       { GFV mode view check }
+         I := RawSize.X Else I := Size.X * FontWidth; { Calc owner x size }
+       If (P^.Options AND ofGFVModeView <> 0)         { GFV mode view check }
+       Then Begin
+         I := (I - P^.RawSize.X) DIV 2;               { Calc view offset }
+         I := I - P^.RawOrigin.X;                     { Subtract x origin }
+       End Else Begin
+         I := (I - (P^.Size.X * FontWidth)) DIV 2;    { Calc view offset }
+         I := I - (P^.Origin.X * FontWidth);          { Subtract x origin }
+       End;
+       P^.DisplaceBy(I, 0);                           { Displace the view }
+     End;
+     If (P^.Options AND ofCenterY <> 0) Then Begin    { Centre on y axis }
+       If (Options AND ofGFVModeView <> 0) Then       { GFV mode view check }
+         I := RawSize.Y Else I := Size.Y * FontHeight;{ Calc owner y size }
+       If (P^.Options AND ofGFVModeView <> 0)         { GFV mode view check }
+       Then Begin
+         I := (I - P^.RawSize.Y) DIV 2;               { Calc view offset }
+         I := I - P^.RawOrigin.Y;                     { Subtract y origin }
+       End Else Begin
+         I := (I - (P^.Size.Y * FontHeight)) DIV 2;   { Calc view offset }
+         I := I - (P^.Origin.Y * FontHeight);         { Subtract y origin }
+       End;
+       P^.DisplaceBy(0, I);                           { Displace the view }
+     End;
+     SaveState := P^.State;                           { Save view state }
+     P^.Hide;                                         { Make sure hidden }
+     InsertView(P, Target);                           { Insert into list }
+     If (SaveState AND sfVisible <> 0) Then P^.Show;  { Show the view }
+     If (State AND sfActive <> 0) Then                { Was active before }
+       P^.SetState(sfActive , True);                  { Make active again }
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  SetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.SetState (AState: Word; Enable: Boolean);
+
+    PROCEDURE DoSetState (P: PView); FAR;
+    BEGIN
+      If (P <> Nil) Then P^.SetState(AState, Enable); { Set subview state }
+    END;
+
+    PROCEDURE DoExpose (P: PView); FAR;
+    BEGIN
+      If (P <> Nil) Then Begin
+        If (P^.State AND sfVisible <> 0) Then         { Check view visible }
+          P^.SetState(sfExposed, Enable);             { Set exposed flag }
+      End;
+    END;
+
+BEGIN
+   Inherited SetState(AState, Enable);                { Call ancestor }
+   Case AState Of
+     sfActive, sfDragging: Begin
+         Lock;                                        { Lock the view }
+         ForEach(@DoSetState);                        { Set each subview }
+         UnLock;                                      { Unlock the view }
+       End;
+     sfFocused: If (Current <> Nil) Then
+       Current^.SetState(sfFocused, Enable);          { Focus current view }
+     sfExposed: Begin
+         ForEach(@DoExpose);                          { Expose each subview }
+       End;
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  GetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 29Mar98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.GetData (Var Rec);
+VAR Total: Word; P: PView;
+BEGIN
+   Total := 0;                                        { Clear total }
+   P := Last;                                         { Start at last }
+   While (P <> Nil) Do Begin                          { Subviews exist }
+     P^.GetData(TByteArray(Rec)[Total]);              { Get data }
+     Inc(Total, P^.DataSize);                         { Increase total }
+     P := P^.PrevView;                                { Previous view }
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  SetData -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 29Mar98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.SetData (Var Rec);
+VAR Total: Word; P: PView;
+BEGIN
+   Total := 0;                                        { Clear total }
+   P := Last;                                         { Start at last }
+   While (P <> Nil) Do Begin                          { Subviews exist }
+     P^.SetData(TByteArray(Rec)[Total]);              { Get data }
+     Inc(Total, P^.DataSize);                         { Increase total }
+     P := P^.PrevView;                                { Previous view }
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Mar98 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.Store (Var S: TStream);
+VAR Count: Integer; OwnerSave: PGroup;
+
+   PROCEDURE DoPut (P: PView); FAR;
+   BEGIN
+     S.Put(P);                                        { Put view on stream }
+   END;
+
+BEGIN
+   TView.Store(S);                                    { Call view store }
+   OwnerSave := OwnerGroup;                           { Save ownergroup }
+   OwnerGroup := @Self;                               { Set as owner group }
+   Count := IndexOf(Last);                            { Subview count }
+   S.Write(Count, 2);                                 { Write the count }
+   ForEach(@DoPut);                                   { Put each in stream }
+   PutSubViewPtr(S, Current);                         { Current on stream }
+   OwnerGroup := OwnerSave;                           { Restore ownergroup }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  EventError -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.EventError (Var Event: TEvent);
+BEGIN
+   If (Owner <> Nil) Then Owner^.EventError(Event);   { Event error }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.HandleEvent (Var Event: TEvent);
+
+   FUNCTION ContainsMouse (P: PView): Boolean; FAR;
+   BEGIN
+     ContainsMouse := (P^.State AND sfVisible <> 0)   { Is view visible }
+       AND P^.MouseInView(Event.Where);               { Is point in view }
+   END;
+
+   PROCEDURE DoHandleEvent (P: PView); FAR;
+   BEGIN
+     If (P = Nil) OR ((P^.State AND sfDisabled <> 0) AND
+       (Event.What AND(PositionalEvents OR FocusedEvents) <>0 ))
+        Then Exit;                                     { Invalid/disabled }
+     Case Phase Of
+       phPreProcess: If (P^.Options AND ofPreProcess = 0)
+         Then Exit;                                   { Not pre processing }
+       phPostProcess: If (P^.Options AND ofPostProcess = 0)
+         Then Exit;                                   { Not post processing }
+     End;
+     If (Event.What AND P^.EventMask <> 0) Then       { View handles event }
+       P^.HandleEvent(Event);                         { Pass to view }
+   END;
+
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   If (Event.What = evNothing) Then Exit;             { No valid event exit }
+   If (Event.What AND FocusedEvents <> 0) Then Begin  { Focused event }
+     Phase := phPreProcess;                           { Set pre process }
+     ForEach(@DoHandleEvent);                         { Pass to each view }
+     Phase := phFocused;                              { Set focused }
+     DoHandleEvent(Current);                          { Pass to current }
+     Phase := phPostProcess;                          { Set post process }
+     ForEach(@DoHandleEvent);                         { Pass to each }
+   End Else Begin
+     Phase := phFocused;                              { Set focused }
+     If (Event.What AND PositionalEvents <> 0) Then   { Positional event }
+       DoHandleEvent(FirstThat(@ContainsMouse))       { Pass to first }
+       Else ForEach(@DoHandleEvent);                  { Pass to all }
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  ChangeBounds -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.ChangeBounds (Var Bounds: TRect);
+VAR D: TPoint;
+
+   PROCEDURE DoCalcChange (P: PView); FAR;
+   VAR R: TRect;
+   BEGIN
+     P^.CalcBounds(R, D);                             { Calc view bounds }
+     P^.ChangeBounds(R);                              { Change view bounds }
+   END;
+
+BEGIN
+   D.X := Bounds.B.X - Bounds.A.X - Size.X;           { Delta x value }
+   D.Y := Bounds.B.Y - Bounds.A.Y - Size.Y;           { Delta y value }
+   If ((D.X=0) AND (D.Y=0)) Then Begin
+     SetBounds(Bounds);                               { Set new bounds }
+     DrawView;                                        { Draw the view }
+   End Else Begin
+     SetBounds(Bounds);                               { Set new bounds }
+     GetExtent(Clip);                                 { Get new clip extents }
+     Lock;                                            { Lock drawing }
+     ForEach(@DoCalcChange);                          { Change each view }
+     UnLock;                                          { Unlock drawing }
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  GetSubViewPtr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 20May98 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.GetSubViewPtr (Var S: TStream; Var P);
+VAR Index, I: Word; Q: PView;
+BEGIN
+   Index := 0;                                        { Zero index value }
+   S.Read(Index, 2);                                  { Read view index }
+   If (Index > 0) Then Begin                          { Valid index }
+     Q := Last;                                       { Start on last }
+     For I := 1 To Index Do Q := Q^.Next;             { Loop for count }
+     Pointer(P) := Q;                                 { Return the view }
+   End Else Pointer(P) := Nil;                        { Return nil }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  PutSubViewPtr -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 20May98 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.PutSubViewPtr (Var S: TStream; P: PView);
+VAR Index: Word;
+BEGIN
+   If (P = Nil) Then Index := 0 Else                  { Nil view, Index = 0 }
+     Index := IndexOf(P);                             { Calc view index }
+   S.Write(Index, 2);                                 { Write the index }
+END;
+
+{$IFNDEF OS_DOS}                                      { WIN/NT/OS2 CODE }
+{***************************************************************************}
+{                  TGroup OBJECT WIN/NT/OS2 ONLY METHODS                    }
+{***************************************************************************}
+
+{--TGroup-------------------------------------------------------------------}
+{  CreateWindowNow -> Platforms WIN/NT/OS2 - Updated 23Mar98 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.CreateWindowNow (CmdShow: Integer);
+VAR P: PView;
+BEGIN
+   Inherited CreateWindowNow (CmdShow);               { Call ancestor }
+   P := Last;                                         { Start on Last }
+   While (P <> Nil) Do Begin
+     If (P^.HWindow = 0) Then                         { No window created }
+       P^.CreateWindowNow(0);                         { Create each subview }
+     P := P^.PrevView;                                { Move to prev view }
+   End;
+END;
+{$ENDIF}
+
+{***************************************************************************}
+{                       TGroup OBJECT PRIVATE METHODS                       }
+{***************************************************************************}
+
+{--TGroup-------------------------------------------------------------------}
+{  IndexOf -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.IndexOf (P: PView): Integer;
+VAR I: Integer; Q: PView;
+BEGIN
+   Q := Last;                                         { Start on last view }
+   If (Q <> Nil) Then Begin                           { Subviews exist }
+     I := 1;                                          { Preset value }
+     While (Q <> P) AND (Q^.Next <> Last) Do Begin
+       Q := Q^.Next;                                  { Load next view }
+       Inc(I);                                        { Increment count }
+     End;
+     If (Q <> P) Then IndexOf := 0 Else IndexOf := I; { Return index }
+   End Else IndexOf := 0;                             { Return zero }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  FindNext -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23Sep99 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.FindNext (Forwards: Boolean): PView;
+VAR P: PView;
+BEGIN
+   FindNext := Nil;                                   { Preset nil return }
+   If (Current <> Nil) Then Begin                     { Has current view }
+     P := Current;                                    { Start on current }
+     Repeat
+       If Forwards Then P := P^.Next                  { Get next view }
+         Else P := P^.Prev;                           { Get prev view }
+     Until ((P^.State AND (sfVisible+sfDisabled) = sfVisible)
+     AND ((P^.Options AND ofSelectable <> 0) AND      { Selectable }
+     (P^.GOptions AND goTabSelect <> 0))) OR          { Tab selectable }
+     (P = Current);                                   { Not singular select }
+     If (P <> Current) Then FindNext := P;            { Return result }
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  FirstMatch -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TGroup.FirstMatch (AState: Word; AOptions: Word): PView;
+
+   FUNCTION Matches (P: PView): Boolean; FAR;
+   BEGIN
+     Matches := (P^.State AND AState = AState) AND
+       (P^.Options AND AOptions = AOptions);          { Return match state }
+   END;
+
+BEGIN
+   FirstMatch := FirstThat(@Matches);                 { Return first match }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  ResetCurrent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.ResetCurrent;
+BEGIN
+   SetCurrent(FirstMatch(sfVisible, ofSelectable),
+     NormalSelect);                                   { Reset current view }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  RemoveView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.RemoveView (P: PView);
+VAR Q: PView;
+BEGIN
+   If (P <> Nil) AND (Last <> Nil) Then Begin         { Check view is valid }
+     Q := Last;                                       { Start on last view }
+     While (Q^.Next <> P) AND (Q^.Next <> Last) Do
+       Q := Q^.Next;                                  { Find prior view }
+     If (Q^.Next = P) Then Begin                      { View found }
+       If (Q^.Next <> Q) Then Begin                   { Not only view }
+         Q^.Next := P^.Next;                          { Rechain views }
+         If (P = Last) Then Last := P^.Next;          { Fix if last removed }
+       End Else Last := Nil;                          { Only view }
+     End;
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  InsertView -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.InsertView (P, Target: PView);
+BEGIN
+   If (P <> Nil) Then Begin                           { Check view is valid }
+     P^.Owner := @Self;                               { Views owner is us }
+     If (Target <> Nil) Then Begin                    { Valid target }
+       Target := Target^.Prev;                        { 1st part of chain }
+       P^.Next := Target^.Next;                       { 2nd part of chain }
+       Target^.Next := P;                             { Chain completed }
+     End Else Begin
+       If (Last <> Nil) Then Begin                    { Not first view }
+         P^.Next := Last^.Next;                       { 1st part of chain }
+         Last^.Next := P;                             { Completed chain }
+       End Else P^.Next := P;                         { 1st chain to self }
+       Last := P;                                     { P is now last }
+     End;
+   End;
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  SetCurrent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23Sep99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.SetCurrent (P: PView; Mode: SelectMode);
+
+   PROCEDURE SelectView (P: PView; Enable: Boolean);
+   BEGIN
+     If (P <> Nil) Then                               { View is valid }
+       P^.SetState(sfSelected, Enable);               { Select the view }
+   END;
+
+   PROCEDURE FocusView (P: PView; Enable: Boolean);
+   BEGIN
+     If (State AND sfFocused <> 0) AND (P <> Nil)     { Check not focused }
+       Then P^.SetState(sfFocused, Enable);           { Focus the view }
+   END;
+
+BEGIN
+   If (Current<>P) Then Begin                         { Not already current }
+     Lock;                                            { Stop drawing }
+     FocusView(Current, False);                       { Defocus current }
+     If (Mode <> EnterSelect) Then
+       SelectView(Current, False);                    { Deselect current }
+     If (Mode<>LeaveSelect) Then SelectView(P, True); { Select view P }
+     FocusView(P, True);                              { Focus view P }
+     Current := P;                                    { Set as current view }
+     UnLock;                                          { Redraw now }
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                           TFrame OBJECT METHODS                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TFrame-------------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TFrame.Init (Var Bounds: TRect);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   GrowMode := gfGrowHiX + gfGrowHiY;                 { Set grow modes }
+   EventMask := EventMask OR evBroadcast;             { See broadcasts }
+END;
+
+{--TFrame-------------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TFrame.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CFrame;                             { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CFrame)] = CFrame;             { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                         TScrollBar OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{                  TScrollBar WINDOW CLASS NAME CONSTANT                    }
+{---------------------------------------------------------------------------}
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CLASSNAME }
+CONST TvScrollBarName = 'SCROLLBAR';                  { Native classname }
+{$ENDIF}
+{$IFDEF OS_OS2}                                       { OS2 CLASSNAME }
+CONST TvScrollBarName = '#8';                         { Native classname }
+{$ENDIF}
+
+{--TScrollBar---------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TScrollBar.Init (Var Bounds: TRect);
+CONST VChars: TScrollChars = (#30, #31, #177, #254, #178);
+      HChars: TScrollChars = (#17, #16, #177, #254, #178);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   If (Size.X = 1) Then RawSize.X := WinQuerySysValue(
+     HWND_Desktop, SV_CXVScroll) Else
+     RawSize.Y := WinQuerySysValue(HWND_Desktop,
+       SV_CYHScroll);                                 { Set approp size }
+   {$ENDIF}
+   PgStep := 1;                                       { Page step size = 1 }
+   ArStep := 1;                                       { Arrow step sizes = 1 }
+   If (Size.X = 1) Then Begin                         { Vertical scrollbar }
+     GrowMode := gfGrowLoX + gfGrowHiX + gfGrowHiY;   { Grow vertically }
+     Chars := VChars;                                 { Vertical chars }
+   End Else Begin                                     { Horizontal scrollbar }
+     GrowMode := gfGrowLoY + gfGrowHiX + gfGrowHiY;   { Grow horizontal }
+     Chars := HChars;                                 { Horizontal chars }
+   End;
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May98 LdB              }
+{---------------------------------------------------------------------------}
+{   This load method will read old original TV data from a stream with the  }
+{   scrollbar id set to zero.                                               }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TScrollBar.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(Value, 2);                                  { Read current value }
+   S.Read(Min , 2);                                   { Read min value }
+   S.Read(Max, 2);                                    { Read max value }
+   S.Read(PgStep, 2);                                 { Read page step size }
+   S.Read(ArStep, 2);                                 { Read arrow step size }
+   S.Read(Chars, SizeOf(Chars));                      { Read scroll chars }
+   If (Options AND ofGFVModeView <> 0) Then           { GFV mode view check }
+     S.Read(Id, 2);                                   { Read id }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TScrollBar.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CScrollBar;                         { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CScrollBar)] = CScrollBar;     { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  ScrollStep -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TScrollBar.ScrollStep (Part: Integer): Integer;
+VAR Step: Integer;
+BEGIN
+   If (Part AND $0002 = 0) Then Step := ArStep        { Range step size }
+     Else Step := PgStep;                             { Page step size }
+   If (Part AND $0001 = 0) Then ScrollStep := -Step   { Upwards move }
+     Else ScrollStep := Step;                         { Downwards move }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  Draw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.Draw;
+BEGIN
+   If (GOptions AND goNativeClass = 0) Then
+     DrawPos(GetPos);                                 { Draw position }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  ScrollDraw -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May98 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.ScrollDraw;
+VAR P: PView;
+BEGIN
+   If (Id <> 0) Then Begin
+     P := TopView;                                    { Get topmost view }
+     NewMessage(P, evCommand, cmIdCommunicate, Id,
+       Value, @Self);                                 { New Id style message }
+   End;
+   NewMessage(Owner, evBroadcast, cmScrollBarChanged,
+     Id, Value, @Self);                               { Old TV style message }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May98 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.DrawBackGround;
+VAR Bc: Byte;
+BEGIN
+   If (GOptions AND goNativeClass = 0) Then Begin     { Non natives draw }
+     Inherited DrawBackGround;                        { Call ancestor }
+     Bc := GetColor(1) AND $F0 SHR 4;                 { Background colour }
+     ClearArea(0, 0, FontWidth-1, FontHeight-1, Bc);  { Clear top/left area }
+     BiColorRectangle(0, 0, FontWidth-1, FontHeight-1,
+       15, 0, False);                                 { Draw 3d effect }
+     ClearArea(RawSize.X-FontWidth+1, RawSize.Y-
+       FontHeight+1, RawSize.X, RawSize.Y, Bc);       { Clr right/lower area }
+     BiColorRectangle(RawSize.X-FontWidth+1,
+       RawSize.Y-FontHeight+1,RawSize.X, RawSize.Y,
+       15, 0, False);                                 { Draw 3d effect }
+   End;
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  SetValue -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May98 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.SetValue (AValue: Integer);
+BEGIN
+   SetParams(AValue, Min, Max, PgStep, ArStep);       { Set value }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  SetRange -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May98 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.SetRange (AMin, AMax: Integer);
+BEGIN
+   SetParams(Value, AMin, AMax, PgStep, ArStep);      { Set range }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  SetStep -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19May98 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.SetStep (APgStep, AArStep: Integer);
+BEGIN
+   SetParams(Value, Min, Max, APgStep, AArStep);      { Set step sizes }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  SetParams -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 21Jul99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.SetParams (AValue, AMin, AMax, APgStep, AArStep: Integer);
+BEGIN
+   If (AMax < AMin) Then AMax := AMin;                { Max below min fix up }
+   If (AValue < AMin) Then AValue := AMin;            { Value below min fix }
+   If (AValue > AMax) Then AValue := AMax;            { Value above max fix }
+   If (Value <> AValue) OR (Min <> AMin) OR
+   (Max <> AMax) Then Begin                           { Something changed }
+     If (Min <> AMin) OR (Max <> AMax) Then Begin     { Range has changed }
+       If (GOptions AND goNativeClass = 0) Then
+         ClearPos(GetPos);                            { Clear old position }
+       Min := AMin;                                   { Set new minimum }
+       Max := AMax;                                   { Set new maximum }
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+       If (GOptions AND goNativeClass <> 0) AND       { In native class mode }
+       (HWindow <> 0) Then
+         SetScrollRange(HWindow, sb_Ctl, Min, Max,    { Set range }
+           AValue = Value);                           { Value=AValue redraws }
+       {$ENDIF}
+       {$IFDEF OS_OS2}                                { OS2 CODE }
+       If (GOptions AND goNativeClass <> 0) AND       { In native class mode }
+       (HWindow <> 0) AND ((Min <> 0) OR (Max <> 0))
+       Then Begin                                     { Valid window }
+         WinSendMsg(HWindow, sbm_SetScrollBar, Value,
+           (LongInt(Max-1) SHL 16) OR Min);           { Post the message }
+       End;
+       {$ENDIF}
+       { This was removed as found not needed but if you
+       change limits but value unchanged scrollbar is not redrawm..LdB }
+       {If (Value = AValue) AND (State and sfVisible <> 0)
+         Then ScrollDraw;}                             { Send message out }
+     End Else Begin
+       If (GOptions AND goNativeClass = 0) Then       { Not in native mode }
+         ClearPos(GetPos);                            { Clear old position }
+     End;
+     If (Value <> AValue) Then Begin                  { Position moved }
+       Value := AValue;                               { Set new value }
+       If (GOptions AND goNativeClass = 0) Then Begin { Not in native mode }
+         SetDrawMask(vdInner);                        { Set draw masks }
+         DrawView;                                    { Redraw changed }
+       End;
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+       If (GOptions AND goNativeClass <> 0) AND       { In native class mode }
+       (HWindow <> 0) Then                            { Valid handle }
+         SetScrollPos(HWindow, sb_Ctl, Value, True);  { Set scrollbar pos }
+       {$ENDIF}
+       {$IFDEF OS_OS2}                                { OS2 CODE }
+       If (GOptions AND goNativeClass <> 0) AND       { In native class mode }
+       (HWindow <> 0) Then Begin                      { Valid window }
+         WinSendMsg(HWindow, sbm_SetPos, Value, 0);   { Dispatch the message }
+       End;
+       {$ENDIF}
+       If (State AND sfVisible <> 0) Then ScrollDraw; { Send update message }
+     End;
+   End;
+   PgStep := APgStep;                                 { Hold page step }
+   ArStep := AArStep;                                 { Hold arrow step }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May98 LdB             }
+{---------------------------------------------------------------------------}
+{  You can save data to the stream compatable with the old original TV by   }
+{  temporarily turning off the ofGrafVersion making the call to this store  }
+{  routine and resetting the ofGrafVersion flag after the call.             }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { TView.Store called }
+   S.Write(Value, 2);                                 { Write current value }
+   S.Write(Min, 2);                                   { Write min value }
+   S.Write(Max, 2);                                   { Write max value }
+   S.Write(PgStep, 2);                                { Write page step size }
+   S.Write(ArStep, 2);                                { Write arrow step size }
+   S.Write(Chars, SizeOf(Chars));                     { Write scroll chars }
+   If (Options AND ofGFVModeView <> 0) Then           { GFV mode view check }
+     S.Write(Id, 2);                                  { Write scrollbar id }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22May98 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.HandleEvent (Var Event: TEvent);
+VAR Tracking: Boolean; I, P, S, ClickPart, Iv: Integer;
+    Mouse: TPoint; Extent: TRect;
+
+   FUNCTION GetPartCode: Integer;
+   VAR Mark, Part, J: Integer;
+   BEGIN
+     Part := -1;                                      { Preset failure }
+     If Extent.Contains(Mouse) Then Begin             { Contains mouse }
+       If (Size.X = 1) Then Begin                     { Vertical scrollbar }
+         Mark := Mouse.Y - FontHeight;                { Calc position }
+         J := FontHeight;                             { Font height }
+       End Else Begin                                 { Horizontal bar }
+         Mark := Mouse.X - FontWidth;                 { Calc position }
+         J := FontWidth;                              { Font width }
+       End;
+       If (Mark >= P) AND (Mark < P+J) Then           { Within thumbnail }
+         Part := sbIndicator;                         { Indicator part }
+       If (Part <> sbIndicator) Then Begin            { Not indicator part }
+         If (Mark < 1) Then Part := sbLeftArrow Else  { Left arrow part }
+         If (Mark < P) Then Part := sbPageLeft Else   { Page left part }
+         If (Mark < S) Then Part := sbPageRight Else  { Page right part }
+           Part := sbRightArrow;                      { Right arrow part }
+         If (Size.X = 1) Then Inc(Part, 4);           { Correct for vertical }
+       End;
+     End;
+     GetPartCode := Part;                             { Return part code }
+   END;
+
+   PROCEDURE Clicked;
+   BEGIN
+     NewMessage(Owner, evBroadcast, cmScrollBarClicked,
+       Id, Value, @Self);                             { Old TV style message }
+   END;
+
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   Case Event.What Of
+     evNothing: Exit;                                 { Speed up exit }
+     evCommand: Begin                                 { Command event }
+       If (Event.Command = cmIdCommunicate) AND       { Id communication }
+       (Event.Id = Id) AND (Event.InfoPtr <> @Self)   { Targeted to us }
+       Then Begin
+         SetValue(Round(Event.Data));                 { Set scrollbar value }
+         ClearEvent(Event);                           { Event was handled }
+       End;
+     End;
+     evKeyDown:
+       If (State AND sfVisible <> 0) Then Begin       { Scrollbar visible }
+         ClickPart := sbIndicator;                    { Preset result }
+         If (Size.Y = 1) Then                         { Horizontal bar }
+           Case CtrlToArrow(Event.KeyCode) Of
+             kbLeft: ClickPart := sbLeftArrow;        { Left one item }
+             kbRight: ClickPart := sbRightArrow;      { Right one item }
+             kbCtrlLeft: ClickPart := sbPageLeft;     { One page left }
+             kbCtrlRight: ClickPart := sbPageRight;   { One page right }
+             kbHome: I := Min;                        { Move to start }
+             kbEnd: I := Max;                         { Move to end }
+             Else Exit;                               { Not a valid key }
+           End
+         Else                                         { Vertical bar }
+           Case CtrlToArrow(Event.KeyCode) Of
+             kbUp: ClickPart := sbUpArrow;            { One item up }
+             kbDown: ClickPart := sbDownArrow;        { On item down }
+             kbPgUp: ClickPart := sbPageUp;           { One page up }
+             kbPgDn: ClickPart := sbPageDown;         { One page down }
+             kbCtrlPgUp: I := Min;                    { Move to top }
+             kbCtrlPgDn: I := Max;                    { Move to bottom }
+             Else Exit;                               { Not a valid key }
+           End;
+         Clicked;                                     { Send out message }
+         If (ClickPart <> sbIndicator) Then
+           I := Value + ScrollStep(ClickPart);        { Calculate position }
+         SetValue(I);                                 { Set new item }
+         ClearEvent(Event);                           { Event now handled }
+     End;
+     evMouseDown: Begin                               { Mouse press event }
+         Clicked;                                     { Scrollbar clicked }
+         Mouse.X := Event.Where.X - RawOrigin.X;      { Localize x value }
+         Mouse.Y := Event.Where.Y - RawOrigin.Y;      { Localize y value }
+         Extent.A.X := 0;                             { Zero x extent value }
+         Extent.A.Y := 0;                             { Zero y extent value }
+         Extent.B.X := RawSize.X;                     { Set extent x value }
+         Extent.B.Y := RawSize.Y;                     { set extent y value }
+         P := GetPos;                                 { Current position }
+         S := GetSize;                                { Initial size }
+         ClickPart := GetPartCode;                    { Get part code }
+         If (ClickPart <> sbIndicator) Then Begin     { Not thumb nail }
+           Repeat
+             Mouse.X := Event.Where.X-RawOrigin.X;    { Localize x value }
+             Mouse.Y := Event.Where.Y-RawOrigin.Y;    { Localize y value }
+             If GetPartCode = ClickPart Then
+               SetValue(Value+ScrollStep(ClickPart)); { Same part repeat }
+           Until NOT MouseEvent(Event, evMouseAuto);  { Until auto done }
+           Clicked;                                   { Scrollbar clicked }
+         End Else Begin                               { Thumb nail move }
+           Iv := Value;                               { Initial value }
+           Repeat
+             Mouse.X := Event.Where.X - RawOrigin.X;  { Localize x value }
+             Mouse.Y := Event.Where.Y - RawOrigin.Y;  { Localize y value }
+             Tracking := Extent.Contains(Mouse);      { Check contains }
+             If Tracking Then Begin                   { Tracking mouse }
+               If (Size.X=1) Then
+                 I := Mouse.Y-FontHeight Else         { Calc vert position }
+                 I := Mouse.X-FontWidth;              { Calc horz position }
+               If (I < 0) Then I := 0;                { Check underflow }
+               If (I > S) Then I := S;                { Check overflow }
+             End Else I := GetPos;                    { Get position }
+             If (I <> P) Then Begin
+               SetValue(LongInt((LongInt(I)*(Max-Min))
+                 +(S SHR 1)) DIV S + Min);            { Set new value }
+               P := I;                                { Hold new position }
+             End;
+           Until NOT MouseEvent(Event, evMouseMove);  { Until not moving }
+           If Tracking AND (S > 0) Then               { Tracking mouse }
+             SetValue(LongInt((LongInt(P)*(Max-Min))+
+               (S SHR 1)) DIV S + Min);               { Set new value }
+           If (Iv <> Value) Then Clicked;             { Scroll has moved }
+         End;
+         ClearEvent(Event);                           { Clear the event }
+     End;
+   End;
+END;
+
+{$IFNDEF OS_DOS}                                      { WIN/NT/OS2 CODE }
+{***************************************************************************}
+{                TScrollBar OBJECT WIN/NT/OS2 ONLY METHODS                  }
+{***************************************************************************}
+
+{--TScrollBar---------------------------------------------------------------}
+{  GetClassName -> Platforms WIN/NT/OS2 - Updated 21May98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TScrollBar.GetClassName: String;
+BEGIN
+   If UseNativeClasses Then Begin
+     GetClassName := TvScrollBarName;                 { Windows class name }
+     GOptions := GOptions OR goNativeClass;           { Native class window }
+   End Else GetClassName := Inherited GetClassName;   { Use standard class }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  GetClassAttr -> Platforms WIN/NT/OS2 - Updated 20May98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TScrollBar.GetClassAttr: LongInt;
+VAR Li: LongInt;
+BEGIN
+   Li := Inherited GetClassAttr;                      { Call ancestor }
+   If UseNativeClasses Then Begin
+     If (Size.Y = 1) Then
+       {$IFDEF OS_WINDOWS}                            { WIN/NT CODE }
+       Li := Li OR sbs_Horz OR sbs_TopAlign Else      { Horizontal scrollbar }
+       Li := Li OR sbs_Vert OR sbs_LeftAlign;         { Vertical scollbar }
+       {$ENDIF}
+       {$IFDEF OS_OS2}                                { OS2 CODE }
+       lStyle :=lStyle OR sbs_Horz OR sbs_AutoSize    { Horizontal scrollbar }
+         Else lStyle := lStyle OR sbs_Vert OR
+           sbs_AutoSize;                              { Vertical scollbar }
+       {$ENDIF}
+   End;
+   GetClassAttr := Li;                                { Return attributes }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  CreateWindowNow -> Platforms WIN/NT/OS2 - Updated 22May98 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.CreateWindowNow (CmdShow: Integer);
+{$IFDEF OS_OS2} VAR Mp1, Mp2: MParam; {$ENDIF}
+BEGIN
+    Inherited CreateWindowNow(0);                     { Call inherited }
+    If (GOptions AND goNativeClass <> 0) AND          { In native class mode }
+    (HWindow <> 0) AND ((Min <> 0) OR (Max <> 0))
+    Then Begin                                        { Scrollbar created }
+      {$IFDEF OS_WINDOWS}                             { WIN/NT CODE }
+      SetScrollRange(HWindow, sb_Ctl, Min,Max, True); { Set scrollbar range }
+      SetScrollPos(HWindow, sb_Ctl, Value, True);     { Set scrollbar pos }
+      {$ENDIF}
+      {$IFDEF OS_OS2}                                 { OS2 CODE }
+      WinSendMsg(HWindow, sbm_SetScrollBar, Value,
+        (LongInt(Max-1) SHL 16) OR Min);              { Post the message }
+      {$ENDIF}
+    End;
+END;
+{$ENDIF}
+
+{***************************************************************************}
+{                 TScrollBar OBJECT PRIVATE METHODS                         }
+{***************************************************************************}
+
+{--TScrollBar---------------------------------------------------------------}
+{  GetPos -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23May98 LdB            }
+{---------------------------------------------------------------------------}
+FUNCTION TScrollBar.GetPos: Integer;
+VAR R: Integer;
+BEGIN
+   R := Max - Min;                                    { Get full range }
+   If (R = 0) Then GetPos := 0 Else                   { Return zero }
+     GetPos := LongInt((LongInt(Value-Min) * GetSize)
+       + (R SHR 1)) DIV R;                            { Calc position }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  GetSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TScrollBar.GetSize: Integer;
+VAR S: Integer;
+BEGIN
+   If (Size.X = 1) Then S := RawSize.Y-3*FontHeight+1 { Vertical bar }
+     Else S := RawSize.X-3*FontWidth+1;               { Horizontal bar }
+   If (S < 1) Then S := 1;                            { Fix minimum size }
+   GetSize := S;                                      { Return size }
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  DrawPos -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27OctMay99 LdB        }
+{---------------------------------------------------------------------------}
+{   This could be called from a message handling event so it must check the }
+{  view is visible, exposed and not obstructed before drawing the thumbnail }
+{  square area.                                                             }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.DrawPos (Pos: Integer);
+VAR X1, Y1, X2, Y2: Integer; ViewPort: ViewPortType;
+BEGIN
+   If (State AND sfVisible <> 0) AND                  { View is visible }
+   (State AND sfExposed <> 0) AND                     { View is exposed }
+   (Max <> Min) Then Begin                            { View has some size }
+     SetViewLimits;                                   { Set view limits }
+     GetViewSettings(ViewPort);                       { Get set viewport }
+     If OverlapsArea(ViewPort.X1, ViewPort.Y1,
+     ViewPort.X2, ViewPort.Y2) Then Begin             { Must be in area }
+       {$IFDEF OS_DOS}
+       HideMouseCursor;                               { Hide the mouse }
+       {$ENDIF}
+       X1 := 0;                                       { Initial x position }
+       Y1 := 0;                                       { Initial y position }
+       If (Size.X=1) Then Y1 := Pos + FontHeight      { Vertical bar }
+         Else X1 := Pos + FontWidth;                  { Horizontal bar }
+       X2 := X1 + FontWidth - 1;                      { Right side point }
+       Y2 := Y1 + FontHeight - 1;                     { Lower side point }
+       ClearArea(X1, Y1, X2, Y2, GetColor(2) AND $0F);{ Thumbnail back }
+       BiColorRectangle(X1, Y1, X2, Y2, 15, 8, False);{ Draw highlight }
+       Y1 := (Y2 + Y1) DIV 2;                         { Middle of thumb }
+       Y2 := Y1+1;                                    { One line down }
+       Inc(X1, 1);                                    { One in off left }
+       Dec(X2, 1);                                    { One in off right }
+       BiColorRectangle(X1, Y1, X2, Y2, 15, 8, True); { Draw line marker }
+       {$IFDEF OS_DOS}
+       ShowMouseCursor;                               { Show the mouse }
+       {$ENDIF}
+     End;
+     ReleaseViewLimits;                               { Release the limits }
+   End;
+END;
+
+{--TScrollBar---------------------------------------------------------------}
+{  ClearPos -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB          }
+{---------------------------------------------------------------------------}
+{   This could be called from a message handling event so it must check the }
+{  view is visible, exposed and not obstructed before clearing the old      }
+{  thumbnail area.                                                          }
+{---------------------------------------------------------------------------}
+PROCEDURE TScrollBar.ClearPos (Pos: Integer);
+VAR X, Y: Integer; ViewPort: ViewPortType;
+BEGIN
+   If (State AND sfVisible <> 0) AND                  { View is visible }
+   (State AND sfExposed <> 0) Then Begin              { View is exposed }
+     SetViewLimits;                                   { Set view limits }
+     GetViewSettings(ViewPort);                       { Get set viewport }
+     If OverlapsArea(ViewPort.X1, ViewPort.Y1,
+     ViewPort.X2, ViewPort.Y2) Then Begin             { Must be in area }
+       {$IFDEF OS_DOS}
+       HideMouseCursor;                               { Hide the mouse }
+       {$ENDIF}
+       X := 0;                                        { Initial x position }
+       Y := 0;                                        { Initial y position }
+       If (Size.X=1) Then Y := Pos + FontHeight       { Vertical bar }
+         Else X := Pos + FontWidth;                   { Horizontal bar }
+       ClearArea(X, Y, X+FontWidth-1, Y+FontHeight-1,
+         GetColor(1) AND $F0 SHR 4);                  { Clear the area }
+       {$IFDEF OS_DOS}
+       ShowMouseCursor;                               { Show the mouse }
+       {$ENDIF}
+     End;
+     ReleaseViewLimits;                               { Release the limits }
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                         TScroller OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TScroller----------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TScroller.Init (Var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   Options := Options OR ofSelectable;                { View is selectable }
+   EventMask := EventMask OR evBroadcast;             { See broadcasts }
+   HScrollBar := AHScrollBar;                         { Hold horz scrollbar }
+   VScrollBar := AVScrollBar;                         { Hold vert scrollbar }
+END;
+
+{--TScroller----------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB              }
+{---------------------------------------------------------------------------}
+{   This load method will read old original TV data from a stream as well   }
+{   as the new graphical scroller views.                                    }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TScroller.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   GetPeerViewPtr(S, HScrollBar);                     { Load horz scrollbar }
+   GetPeerViewPtr(S, VScrollBar);                     { Load vert scrollbar }
+   S.Read(Delta.X, 2);                                { Read delta x value }
+   S.Read(Delta.Y, 2);                                { Read delta y value }
+   S.Read(Limit.X, 2);                                { Read limit x value }
+   S.Read(Limit.Y, 2);                                { Read limit y value }
+END;
+
+{--TScroller----------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TScroller.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CScroller;                          { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CScroller)] = CScroller;       { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Scroller palette }
+END;
+
+{--TScroller----------------------------------------------------------------}
+{  ScrollTo -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TScroller.ScrollTo (X, Y: Integer);
+BEGIN
+   Inc(DrawLock);                                     { Set draw lock }
+   If (HScrollBar<>Nil) Then HScrollBar^.SetValue(X); { Set horz scrollbar }
+   If (VScrollBar<>Nil) Then VScrollBar^.SetValue(Y); { Set vert scrollbar }
+   Dec(DrawLock);                                     { Release draw lock }
+   CheckDraw;                                         { Check need to draw }
+END;
+
+{--TScroller----------------------------------------------------------------}
+{  SetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TScroller.SetState (AState: Word; Enable: Boolean);
+
+   PROCEDURE ShowSBar (SBar: PScrollBar);
+   BEGIN
+     If (SBar <> Nil) Then                            { Scroll bar valid }
+       If GetState(sfActive + sfSelected) Then        { Check state masks }
+         SBar^.Show Else SBar^.Hide;                  { Draw appropriately }
+   END;
+
+BEGIN
+   Inherited SetState(AState, Enable);                { Call ancestor }
+   If (AState AND (sfActive + sfSelected) <> 0)       { Active/select change }
+   Then Begin
+     ShowSBar(HScrollBar);                            { Redraw horz scrollbar }
+     ShowSBar(VScrollBar);                            { Redraw vert scrollbar }
+   End;
+END;
+
+{--TScroller----------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB             }
+{---------------------------------------------------------------------------}
+{  The scroller is saved to the stream compatable with the old TV object.   }
+{---------------------------------------------------------------------------}
+PROCEDURE TScroller.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { Call TView explicitly }
+   PutPeerViewPtr(S, HScrollBar);                     { Store horz bar }
+   PutPeerViewPtr(S, VScrollBar);                     { Store vert bar }
+   S.Write(Delta.X, 2);                               { Write delta x value }
+   S.Write(Delta.Y, 2);                               { Write delta y value }
+   S.Write(Limit.X, 2);                               { Write limit x value }
+   S.Write(Limit.Y, 2);                               { Write limit y value }
+END;
+
+{--TScroller----------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TScroller.HandleEvent (Var Event: TEvent);
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   If (Event.What = evBroadcast) AND
+     (Event.Command = cmScrollBarChanged) AND         { Scroll bar change }
+     ((Event.InfoPtr = HScrollBar) OR                 { Our scrollbar? }
+      (Event.InfoPtr = VScrollBar)) Then ScrollDraw;  { Redraw scroller }
+END;
+
+{--TScroller----------------------------------------------------------------}
+{  ChangeBounds -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TScroller.ChangeBounds (Var Bounds: TRect);
+BEGIN
+   SetBounds(Bounds);                                 { Set new bounds }
+   Inc(DrawLock);                                     { Set draw lock }
+   SetLimit(Limit.X, Limit.Y);                        { Adjust limits }
+   Dec(DrawLock);                                     { Release draw lock }
+   DrawFlag := False;                                 { Clear draw flag }
+   DrawView;                                          { Redraw now }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                        TListViewer OBJECT METHODS                         }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+CONST TvListViewerName = 'LISTBOX';                   { Native name }
+
+{--TListViewer--------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TListViewer.Init (Var Bounds: TRect; ANumCols: Word; AHScrollBar,
+  AVScrollBar: PScrollBar);
+VAR ArStep, PgStep: Integer;
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   Options := Options OR (ofFirstClick+ofSelectable); { Set options }
+   EventMask := EventMask OR evBroadcast;             { Set event mask }
+   NumCols := ANumCols;                               { Hold column number }
+   If (AVScrollBar <> Nil) Then Begin                 { Chk vert scrollbar }
+     If (NumCols = 1) Then Begin                      { Only one column }
+       PgStep := Size.Y -1;                           { Set page size }
+       ArStep := 1;                                   { Set step size }
+     End Else Begin                                   { Multiple columns }
+       PgStep := Size.Y * NumCols;                    { Set page size }
+       ArStep := Size.Y;                              { Set step size }
+     End;
+     AVScrollBar^.SetStep(PgStep, ArStep);            { Set scroll values }
+   End;
+   If (AHScrollBar <> Nil) Then
+     AHScrollBar^.SetStep(Size.X DIV NumCols, 1);     { Set step size }
+   HScrollBar := AHScrollBar;                         { Horz scrollbar held }
+   VScrollBar := AVScrollBar;                         { Vert scrollbar held }
+   GOptions := GOptions OR goDrawFocus;               { Draw focus changes }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28May98 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TListViewer.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   GetPeerViewPtr(S, HScrollBar);                     { Get horz scrollbar }
+   GetPeerViewPtr(S, VScrollBar);                     { Get vert scrollbar }
+   S.Read(NumCols, 2);                                { Read column number }
+   S.Read(TopItem, 2);                                { Read top most item }
+   S.Read(Focused, 2);                                { Read focused item }
+   S.Read(Range, 2);                                  { Read listview range }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TListViewer.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST P: String = CListViewer;                        { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST P: String[Length(CListViewer)] = CListViewer;   { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P;                                  { Return palette }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  IsSelected -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28May98 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TListViewer.IsSelected (Item: Integer): Boolean;
+BEGIN
+   If (Item = Focused) Then IsSelected := True Else
+     IsSelected := False;                             { Selected item }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  GetText -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28May98 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION TListViewer.GetText (Item: Integer; MaxLen: Integer): String;
+BEGIN                                                 { Abstract method }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  DrawBackGround -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB    }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.DrawBackGround;
+VAR SCOff: Byte; I, J, ColWidth, Item, Indent, CurCol: Integer; Color: Word;
+    Text: String; B: TDrawBuffer;
+    {$IFDEF OS_WINDOWS} S: String; {$ENDIF}           { WIN/NT CODE }
+
+BEGIN
+   ColWidth := Size.X DIV NumCols + 1;                { Calc column width }
+   If (HScrollBar = Nil) Then Indent := 0 Else        { Set indent to zero }
+     Indent := HScrollBar^.Value;                     { Fetch any indent }
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (GOptions AND goNativeClass <> 0) Then Begin    { Native class mode }
+     If (Range <> SendMessage(HWindow, lb_GetCount,
+     0, 0)) Then SendMessage(HWindow,lb_ResetContent, { If ranges differ }
+       0, 0);                                         { Clear all strings }
+     For I := 1 To Range Do Begin                     { For each item }
+       J := SendMessage(HWindow, lb_GetText, 0,
+         LongInt(@S[1]));                             { Get current text }
+       If (J <> lb_Err) Then Begin                    { Check for error }
+         {$IFDEF PPC_DELPHI3}                         { DELPHI 3+ COMPILER }
+         SetLength(S, J);                             { Set string length }
+         {$ELSE}                                      { OTHER COMPILERS }
+         S[0] := Chr(J);                              { Set string legth }
+         {$ENDIF}
+       End Else S := '';                              { Error no string }
+       Text := GetText(I-1, ColWidth + Indent);       { Fetch text }
+       Text := Copy(Text, Indent, ColWidth) + #0;     { Select right bit }
+       If (S <> Text) Then Begin                      { Strings differ }
+         If (J <> lb_Err) Then SendMessage(HWindow,
+          lb_DeleteString, I-1, 0);                   { Delete current string }
+         SendMessage(HWindow, lb_InsertString, I-1,
+           LongInt(@Text[1]));                        { Set string in list }
+       End;
+     End;
+     If (Options AND ofSelectable <> 0) Then
+       SendMessage(HWindow, lb_SetCurSel, Focused, 0); { Focus selected item }
+     TopItem := SendMessage(HWindow, lb_GetTopIndex,
+       0, 0);                                         { Synchronize }
+     UpdateWindow(HWindow);                           { Redraw new strings }
+     Exit;                                            { Native mode is done }
+    End;
+   {$ENDIF}
+   Inherited DrawBackGround;                          { Call ancestor }
+   Color := GetColor(2);                              { Normal colour }
+   For I := 0 To Size.Y - 1 Do Begin                  { For each line }
+     For J := 0 To NumCols-1 Do Begin                 { For each column }
+       Item := J*Size.Y + I + TopItem;                { Process this item }
+       CurCol := J*ColWidth;                          { Current column }
+       MoveChar(B[CurCol], ' ', Color, ColWidth);     { Clear buffer }
+       If (Item < Range) Then Begin                   { Within text range }
+         Text := GetText(Item, ColWidth + Indent);    { Fetch text }
+         Text := Copy(Text, Indent, ColWidth);        { Select right bit }
+         MoveStr(B[CurCol+1], Text, Color);           { Transfer to buffer }
+         If ShowMarkers Then Begin
+           WordRec(B[CurCol]).Lo := Byte(
+             SpecialChars[SCOff]);                    { Set marker character }
+           WordRec(B[CurCol+ColWidth-2]).Lo := Byte(
+             SpecialChars[SCOff+1]);                  { Set marker character }
+         End;
+       End;
+       MoveChar(B[CurCol+ColWidth-1], #179,
+         GetColor(5), 1);                             { Put centre line marker }
+     End;
+     WriteLine(0, I, Size.X, 1, B);                   { Write line to screen }
+   End;
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  DrawFocus -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.DrawFocus;
+VAR DrawIt: Boolean; I, J, Item, CurCol, ColWidth: Integer;
+    Color: Word;
+
+  Indent: Integer;
+  B: TDrawBuffer;
+  Text,S: String;
+  SCOff: Byte;
+BEGIN
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (GOptions AND goNativeClass <> 0) Then Exit;    { Native class exits }
+   {$ENDIF}
+   ColWidth := Size.X DIV NumCols + 1;                { Calc column width }
+   If (HScrollBar = Nil) Then Indent := 0 Else        { Set indent to zero }
+     Indent := HScrollBar^.Value;                     { Fetch any indent }
+   For I := 0 To Size.Y - 1 Do Begin                  { For each line }
+     For J := 0 To NumCols-1 Do Begin                 { For each column }
+       Item := J*Size.Y + I + TopItem;                { Process this item }
+       CurCol := J*ColWidth;                          { Current column }
+       DrawIt := False;                               { Preset false }
+       If (State AND (sfSelected + sfActive) =
+       (sfSelected + sfActive)) AND (Focused = Item)  { Focused item }
+       AND (Range > 0) Then Begin
+         DrawIt := True;                              { Draw this item }
+         Color := GetColor(3);                        { Focused colour }
+         SetCursor(CurCol+1,I);                       { Set the cursor }
+         SCOff := 0;                                  { Zero colour offset }
+       End Else If (Item < Range) AND IsSelected(Item){ Selected item }
+       Then Begin
+         DrawIt := True;                              { Draw this item }
+         If (State AND sfActive <> 0) Then
+           Color := GetColor(4) Else                  { Selected colour }
+           Color := GetColor(2);                      { Remove focus }
+         SCOff := 2;                                  { Colour offset=2 }
+       End;
+       If DrawIt Then Begin                           { We are drawing item }
+         ClearArea(0, I*FontHeight, ColWidth*FontWidth,
+           (I+1)*FontHeight-1, Color AND $F0 SHR 4);  { Draw the bar }
+         MoveChar(B[CurCol], ' ', Color, ColWidth);
+         if Item < Range then begin
+           Text := GetText(Item, ColWidth + Indent);
+           Text := Copy(Text,Indent,ColWidth);
+           MoveStr(B[CurCol+1], Text, Color);
+           if ShowMarkers then begin
+             WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
+             WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
+           end;
+         end;
+         MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
+         WriteLine(0, I, Size.X, 1, B);
+       End;
+     End;
+   End;
+END;
+
+
+{--TListViewer--------------------------------------------------------------}
+{  FocusItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.FocusItem (Item: Integer);
+BEGIN
+   Focused := Item;                                   { Set focus to item }
+   If (VScrollBar <> Nil) Then
+     VScrollBar^.SetValue(Item);                      { Scrollbar to value }
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (GOptions AND goNativeClass <> 0) Then Begin    { Native class mode }
+     If (HWindow <> 0) Then Begin                     { Check window valid }
+       If (Options AND ofSelectable <> 0) Then
+       SendMessage(HWindow, lb_SetCurSel, Focused, 0);{ Focus selected item }
+       TopItem := SendMessage(HWindow, lb_GetTopIndex,
+         0, 0);                                       { Synchronize }
+     End;
+     Exit;                                            { Native mode done }
+   End;
+   {$ENDIF}
+   If (Item < TopItem) Then                           { Item above top item }
+     If (NumCols = 1) Then TopItem := Item            { Set top item }
+       Else TopItem := Item - Item MOD Size.Y         { Set top item }
+   Else If (Item >= TopItem + (Size.Y*NumCols)) Then  { Item below bottom }
+     If (NumCols = 1) Then TopItem := Item-Size.Y+1   { Set new top item }
+     Else TopItem := Item - Item MOD Size.Y -
+       (Size.Y*(NumCols-1));                          { Set new top item }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  SetTopItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06Aug99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.SetTopItem (Item: Integer);
+BEGIN
+   TopItem := Item;                                   { Set the top item }
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (GOptions AND goNativeClass <> 0) AND           { Native class mode }
+   (HWindow <> 0) Then                                { Window valid }
+     SendMessage(HWindow, lb_SetTopIndex, Item, 0);   { Synchronize }
+   {$ENDIF}
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  SetRange -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.SetRange (ARange: Integer);
+BEGIN
+   Range := ARange;                                   { Set new range }
+   If (VScrollBar <> Nil) Then Begin                  { Vertical scrollbar }
+     If (Focused > ARange) Then Focused := 0;         { Clear focused }
+     VScrollBar^.SetParams(Focused, 0, ARange - 1,
+       VScrollBar^.PgStep, VScrollBar^.ArStep);       { Set parameters }
+   End;
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  SelectItem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.SelectItem (Item: Integer);
+BEGIN
+   Message(Owner, evBroadcast, cmListItemSelected,
+     @Self);                                          { Send message }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  SetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.SetState (AState: Word; Enable: Boolean);
+
+   PROCEDURE ShowSBar(SBar: PScrollBar);
+   BEGIN
+     If (SBar <> Nil) Then                            { Valid scrollbar }
+       If GetState(sfActive) AND GetState(sfVisible)  { Check states }
+         Then SBar^.Show Else SBar^.Hide;             { Show or hide }
+   END;
+
+   PROCEDURE LoseFocus;
+   VAR Cs: Integer;
+   BEGIN
+     If (GOptions AND goNativeClass = 0) Then Begin   { Not in native mode }
+       Cs := State;                                   { Hold current state }
+       {$IFDEF PPC_SPEED}                             { SPEEDSOFT SYBIL2+ }
+       State := State AND (sfActive XOR $FFFF);       { Weird bug!!! }
+       {$ELSE}                                        { OTHER COMPILERS }
+       State := State AND NOT sfActive;               { Must remove focus }
+       {$ENDIF}
+       SetDrawmask(vdFocus);                          { Set focus mask }
+       DrawView;                                      { Remove focus box }
+       State := Cs;                                   { Reset state masks }
+     End;
+   END;
+
+BEGIN
+   Inherited SetState(AState, Enable);                { Call ancestor }
+   If (AState AND sfFocused <> 0) Then                { Focus change }
+     If NOT Enable Then LoseFocus;                    { Redraw drop focus }
+   If (AState AND (sfSelected + sfActive + sfVisible) <> 0)
+   Then Begin                                         { Check states }
+     SetDrawMask(vdFocus);
+     DrawView;                                        { Draw the view }
+     ShowSBar(HScrollBar);                            { Show horz scrollbar }
+     ShowSBar(VScrollBar);                            { Show vert scrollbar }
+   End;
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.Store (Var S: TStream);
+BEGIN
+   TView.Store(S);                                    { Call TView explicitly }
+   PutPeerViewPtr(S, HScrollBar);                     { Put horz scrollbar }
+   PutPeerViewPtr(S, VScrollBar);                     { Put vert scrollbar }
+   S.Write(NumCols, 2);                               { Write column number }
+   S.Write(TopItem, 2);                               { Write top most item }
+   S.Write(Focused, 2);                               { Write focused item }
+   S.Write(Range, 2);                                 { Write listview range }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 27Oct99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.HandleEvent (Var Event: TEvent);
+CONST MouseAutosToSkip = 4;
+VAR Oi, Ni: Integer; Ct, Cw: Word; Mouse: TPoint;
+
+   PROCEDURE MoveFocus (Req: Integer);
+   VAR Ti, Cs: Integer;
+   BEGIN
+     If (GOptions AND goNativeClass = 0) Then Begin   { Not in native mode }
+       Ti := TopItem;                                 { Hold top item }
+       Cs := State;                                   { Hold current state }
+       {$IFDEF PPC_SPEED}                             { SPEEDSOFT SYBIL2+ }
+       State := State AND (sfActive XOR $FFFF);       { Weird bug!!!! }
+       {$ELSE}                                        { OTHER COMPILERS }
+       State := State AND NOT sfActive;               { Must remove focus }
+       {$ENDIF}
+       SetDrawmask(vdFocus);                          { Set focus mask }
+       DrawView;                                      { Remove focus box }
+       State := Cs;                                   { Reset state masks }
+     End;
+     FocusItemNum(Req);                               { Focus req item }
+     If (GOptions AND goNativeClass = 0) Then Begin   { Not in native mode }
+       If (Ti <> TopItem) Then DrawView Else Begin    { Redraw all view }
+         SetDrawmask(vdFocus);                        { Set focus mask }
+         DrawView;                                    { Redraw focus box }
+       End;
+     End;
+   END;
+
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   Case Event.What Of
+     evNothing: Exit;                                 { Speed up exit }
+     evKeyDown: Begin                                 { Key down event }
+       If (Event.CharCode = ' ') AND (Focused < Range){ Spacebar select }
+       Then Begin
+         SelectItem(Focused);                         { Select focused item }
+         Ni := Focused;                               { Hold new item }
+       End Else Case CtrlToArrow(Event.KeyCode) Of
+         kbUp: Ni := Focused - 1;                     { One item up }
+         kbDown: Ni := Focused + 1;                   { One item down }
+         kbRight: If (NumCols > 1) Then
+           Ni := Focused + Size.Y Else Exit;          { One column right }
+         kbLeft: If (NumCols > 1) Then
+           Ni := Focused - Size.Y Else Exit;          { One column left }
+         kbPgDn: Ni := Focused + Size.Y * NumCols;    { One page down }
+         kbPgUp: Ni := Focused - Size.Y * NumCols;    { One page up }
+         kbHome: Ni := TopItem;                       { Move to top }
+         kbEnd: Ni := TopItem + (Size.Y*NumCols)-1;   { Move to bottom }
+         kbCtrlPgDn: Ni := Range - 1;                 { Move to last item }
+         kbCtrlPgUp: Ni := 0;                         { Move to first item }
+         Else Exit;
+       End;
+       MoveFocus(Ni);                                 { Move the focus }
+       ClearEvent(Event);                             { Event was handled }
+     End;
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     evCommand: If (Event.Command = cmNotify) Then    { Notify command }
+     Begin
+       FocusItem(Round(Event.Data));                  { Focus the item }
+       SelectItem(Focused);                           { Select the item }
+       ClearEvent(Event);                             { Event was handled }
+     End Else Exit;                                   { Not handled command }
+     {$ENDIF}
+     evBroadcast: Begin                               { Broadcast event }
+       If (Options AND ofSelectable <> 0) Then        { View is selectable }
+         If (Event.Command = cmScrollBarClicked) AND  { Scrollbar click }
+         ((Event.InfoPtr = HScrollBar) OR
+         (Event.InfoPtr = VScrollBar)) Then Select    { Scrollbar selects us }
+         Else If (Event.Command = cmScrollBarChanged) { Scrollbar changed }
+         Then Begin
+           If (VScrollBar = Event.InfoPtr) Then Begin
+             MoveFocus(VScrollBar^.Value);            { Focus us to item }
+           End Else If (HScrollBar = Event.InfoPtr)
+             Then DrawView;                           { Redraw the view }
+         End;
+     End;
+     evMouseDown: Begin                               { Mouse down event }
+       Cw := Size.X DIV NumCols + 1;                  { Column width }
+       Oi := Focused;                                 { Hold focused item }
+       MakeLocal(Event.Where, Mouse);                 { Localize mouse }
+       If MouseInView(Event.Where) Then Ni := Mouse.Y
+         + (Size.Y*(Mouse.X DIV Cw))+TopItem          { Calc item to focus }
+         Else Ni := Oi;                               { Focus old item }
+       Ct := 0;                                       { Clear count value }
+       Repeat
+         If (Ni <> Oi) Then Begin                     { Item is different }
+           MoveFocus(Ni);                             { Move the focus }
+           Oi := Focused;                             { Hold as focused item }
+         End;
+         MakeLocal(Event.Where, Mouse);               { Localize mouse }
+         If NOT MouseInView(Event.Where) Then Begin
+           If (Event.What = evMouseAuto) Then Inc(Ct);{ Inc auto count }
+           If (Ct = MouseAutosToSkip) Then Begin
+             Ct := 0;                                 { Reset count }
+             If (NumCols = 1) Then Begin              { Only one column }
+               If (Mouse.Y < 0) Then Ni := Focused-1; { Move up one item  }
+               If (Mouse.Y >= Size.Y) Then
+                 Ni := Focused+1;                     { Move down one item }
+             End Else Begin                           { Multiple columns }
+               If (Mouse.X < 0) Then                  { Mouse x below zero }
+                 Ni := Focused-Size.Y;                { Move down 1 column }
+               If (Mouse.X >= Size.X) Then            { Mouse x above width }
+                 Ni := Focused+Size.Y;                { Move up 1 column }
+               If (Mouse.Y < 0) Then                  { Mouse y below zero }
+                 Ni := Focused-Focused MOD Size.Y;    { Move up one item }
+               If (Mouse.Y > Size.Y) Then             { Mouse y above height }
+                 Ni := Focused-Focused MOD
+                   Size.Y+Size.Y-1;                   { Move down one item }
+             End;
+           End;
+         End Else Ni := Mouse.Y + (Size.Y*(Mouse.X
+           DIV Cw))+TopItem;                          { New item to focus }
+       Until NOT MouseEvent(Event, evMouseMove +
+         evMouseAuto);                                { Mouse stopped }
+       If (Oi <> Ni) Then MoveFocus(Ni);              { Focus moved again }
+       If (Event.Double AND (Range > Focused)) Then
+         SelectItem(Focused);                         { Select the item }
+       ClearEvent(Event);                             { Event was handled }
+     End;
+   End;
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  ChangeBounds -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.ChangeBounds (Var Bounds: TRect);
+BEGIN
+   Inherited ChangeBounds(Bounds);                    { Call ancestor }
+   If (HScrollBar <> Nil) Then                        { Valid horz scrollbar }
+     HScrollBar^.SetStep(Size.X DIV NumCols,
+       HScrollBar^.ArStep);                           { Update horz bar }
+   If (VScrollBar <> Nil) Then                        { Valid vert scrollbar }
+     VScrollBar^.SetStep(Size.Y * NumCols,
+       VScrollBar^.ArStep);                           { Update vert bar }
+END;
+
+{$IFDEF OS_WINDOWS}                                   { WIN/NT CODE }
+{***************************************************************************}
+{                  TListViewer OBJECT WIN/NT ONLY METHODS                   }
+{***************************************************************************}
+
+{--TListViewer--------------------------------------------------------------}
+{  GetNotifyCmd -> Platforms WIN/NT/OS2 - Updated 06Aug99 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TListViewer.GetNotifyCmd: LongInt;
+BEGIN
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   GetNotifyCmd := lb_GetCurSel;                      { Listbox get selection }
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   GetNotifyCmd := lm_QuerySelection;                 { Listbox get selection }
+   {$ENDIF}
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  GetClassName -> Platforms WIN/NT - Updated 27Oct99 LdB                   }
+{---------------------------------------------------------------------------}
+FUNCTION TListViewer.GetClassName: String;
+BEGIN
+   If UseNativeClasses Then Begin                     { Use native classes }
+     GetClassName := TvListViewerName;                { Windows class name }
+     GOptions := GOptions OR goNativeClass;           { Native class window }
+   End Else GetClassName := Inherited GetClassName;   { Use standard class }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  GetClassAttr -> Platforms WIN/NT - Updated 27Oct99 LdB                   }
+{---------------------------------------------------------------------------}
+FUNCTION TListViewer.GetClassAttr: LongInt;
+VAR Li: LongInt;
+BEGIN
+   Li := Inherited GetClassAttr;                      { Call ancestor }
+   Li := Li OR lbs_HasStrings OR lbs_Notify;          { Set has strings mask }
+   If (NumCols > 1) Then
+     Li := Li OR lbs_MultiColumn;                     { Has multiple columns }
+
+   Li := Li OR LBS_NOINTEGRALHEIGHT ;
+   GetClassAttr := Li;                                { Return attributes }
+END;
+
+{--TListViewer--------------------------------------------------------------}
+{  CreateWindowNow -> Platforms WIN/NT - Updated 27Oct99 LdB                }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.CreateWindowNow (CmdShow: Integer);
+BEGIN
+   Inherited CreateWindowNow(CmdShow);                { Call ancestor }
+   DrawView;                                          { Redraw the view }
+END;
+
+{$ENDIF}
+
+{***************************************************************************}
+{                     TListViewer OBJECT PRIVATE METHODS                    }
+{***************************************************************************}
+
+{--TListViewer--------------------------------------------------------------}
+{  FocusItemNum -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 26Jul99 LdB      }
+{---------------------------------------------------------------------------}
+PROCEDURE TListViewer.FocusItemNum (Item: Integer);
+BEGIN
+   If (Item < 0) Then Item := 0 Else                  { Restrain underflow }
+     If (Item >= Range) AND (Range > 0) Then
+       Item := Range-1;                               { Restrain overflow }
+   If (Range <> 0) Then FocusItem(Item);              { Set focus value }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TWindow OBJECT METHODS                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{--TWindow------------------------------------------------------------------}
+{  Init -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB              }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TWindow.Init (Var Bounds: TRect; ATitle: TTitleStr; ANumber: Integer);
+BEGIN
+   Inherited Init(Bounds);                            { Call ancestor }
+   State := State OR sfShadow;                        { View is shadowed }
+   Options := Options OR (ofSelectable+ofTopSelect);  { Select options set }
+   GrowMode := gfGrowAll + gfGrowRel;                 { Set growmodes }
+   Flags := wfMove + wfGrow + wfClose + wfZoom;       { Set flags }
+   Title := NewStr(ATitle);                           { Hold title }
+   Number := ANumber;                                 { Hold number }
+   Palette := wpBlueWindow;                           { Default palette }
+   GOptions := GOptions OR goThickFramed;             { Thick frame }
+   GOptions := GOptions OR goTitled;                  { Title window }
+   GOptions := GOptions AND NOT goNoDrawView;         { View does draw self }
+   InitFrame;                                         { Initialize frame }
+   If (Frame <> Nil) Then Insert(Frame);              { Insert any frame }
+   GetBounds(ZoomRect);                               { Default zoom rect }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  Load -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB              }
+{---------------------------------------------------------------------------}
+{   This load method will read old original TV data from a stream however   }
+{   although a frame view is read for compatability it is disposed of.      }
+{---------------------------------------------------------------------------}
+CONSTRUCTOR TWindow.Load (Var S: TStream);
+BEGIN
+   Inherited Load(S);                                 { Call ancestor }
+   S.Read(Flags, 1);                                  { Read window flags }
+   S.Read(Number, 2);                                 { Read window number }
+   S.Read(Palette, 2);                                { Read window palette }
+   S.Read(ZoomRect.A.X, 2);                           { Read zoom area x1 }
+   S.Read(ZoomRect.A.Y, 2);                           { Read zoom area y1 }
+   S.Read(ZoomRect.B.X, 2);                           { Read zoom area x2 }
+   S.Read(ZoomRect.B.Y, 2);                           { Read zoom area y2 }
+   GetSubViewPtr(S, Frame);                           { Now read frame object }
+   If (Frame <> Nil) Then Begin
+     Dispose(Frame, Done);                            { Kill we don't use it }
+     Frame := Nil;                                    { Clear the pointer }
+   End;
+   Title := S.ReadStr;                                { Read title }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  Done -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB              }
+{---------------------------------------------------------------------------}
+DESTRUCTOR TWindow.Done;
+BEGIN
+   Inherited Done;                                    { Call ancestor }
+   If (Title <> Nil) Then DisposeStr(Title);          { Dispose title }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  GetPalette -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION TWindow.GetPalette: PPalette;
+{$IFDEF PPC_DELPHI3}                                  { DELPHI3+ COMPILER }
+CONST  P: ARRAY [wpBlueWindow..wpGrayWindow] Of String =
+  (CBlueWindow, CCyanWindow, CGrayWindow);            { Possible huge string }
+{$ELSE}                                               { OTHER COMPILERS }
+CONST  P: ARRAY [wpBlueWindow..wpGrayWindow] Of String[Length(CBlueWindow)] =
+  (CBlueWindow, CCyanWindow, CGrayWindow);            { Always normal string }
+{$ENDIF}
+BEGIN
+   GetPalette := @P[Palette];                         { Return palette }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  GetTitle -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB          }
+{---------------------------------------------------------------------------}
+FUNCTION TWindow.GetTitle (MaxSize: Integer): TTitleStr;
+VAR S: String;
+BEGIN
+   If (Number <> 0) Then begin                        { Valid window number }
+     Str(Number, S);                                  { Window number }
+     S := '(' + S + ') ';                             { Insert in brackets }
+   End Else S := '';                                  { Empty string }
+   If (Title <> Nil) Then GetTitle := S + Title^
+     Else GetTitle := S;                              { Return title }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  StandardScrollBar -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB }
+{---------------------------------------------------------------------------}
+FUNCTION TWindow.StandardScrollBar (AOptions: Word): PScrollBar;
+VAR R: TRect; S: PScrollBar;
+BEGIN
+   GetExtent(R);                                      { View extents }
+   If (AOptions AND sbVertical = 0) Then
+     R.Assign(R.A.X+2, R.B.Y-1, R.B.X-2, R.B.Y)       { Horizontal scrollbar }
+     Else R.Assign(R.B.X-1, R.A.Y+1, R.B.X, R.B.Y-1); { Vertical scrollbar }
+   S := New(PScrollBar, Init(R));                     { Create scrollbar }
+   Insert(S);                                         { Insert scrollbar }
+   If (AOptions AND sbHandleKeyboard <> 0) Then
+     S^.Options := S^.Options or ofPostProcess;       { Post process }
+   StandardScrollBar := S;                            { Return scrollbar }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  Zoom -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23Sep97 LdB              }
+{---------------------------------------------------------------------------}
+PROCEDURE TWindow.Zoom;
+VAR R: TRect; Max, Min: TPoint;
+BEGIN
+   SizeLimits(Min, Max);                              { Return size limits }
+   If ((Size.X <> Max.X) OR (Size.Y <> Max.Y))        { Larger size possible }
+   Then Begin
+     GetBounds(ZoomRect);                             { Get zoom bounds }
+     R.A.X := 0;                                      { Zero x origin }
+     R.A.Y := 0;                                      { Zero y origin }
+     R.B := Max;                                      { Bounds to max size }
+     Locate(R);                                       { Locate the view }
+   End Else Locate(ZoomRect);                         { Move to zoom rect }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  Close -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 23Sep97 LdB             }
+{---------------------------------------------------------------------------}
+PROCEDURE TWindow.Close;
+BEGIN
+   If Valid(cmClose) Then Free;                       { Dispose of self }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  InitFrame -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Jul99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TWindow.InitFrame;
+BEGIN                                                 { Compatability only }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  SetState -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Mar98 LdB          }
+{---------------------------------------------------------------------------}
+PROCEDURE TWindow.SetState (AState: Word; Enable: Boolean);
+VAR WindowCommands: TCommandSet;
+BEGIN
+   Inherited SetState(AState, Enable);                { Call ancestor }
+   If (AState = sfSelected) Then
+     SetState(sfActive, Enable);                      { Set active state }
+   If (AState = sfSelected) OR ((AState = sfExposed)
+   AND (State AND sfSelected <> 0)) Then Begin        { View is selected }
+     WindowCommands := [cmNext, cmPrev];              { Set window commands }
+     If (Flags AND (wfGrow + wfMove) <> 0) Then
+       WindowCommands := WindowCommands + [cmResize]; { Add resize command }
+     If (Flags AND wfClose <> 0) Then
+       WindowCommands := WindowCommands + [cmClose];  { Add close command }
+     If (Flags AND wfZoom <> 0) Then
+       WindowCommands := WindowCommands + [cmZoom];   { Add zoom command }
+     If Enable Then EnableCommands(WindowCommands)    { Enable commands }
+       Else DisableCommands(WindowCommands);          { Disable commands }
+   End;
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  Store -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 30Mar98 LdB             }
+{---------------------------------------------------------------------------}
+{  You can save data to the stream compatable with the old original TV by   }
+{  temporarily turning off the ofGrafVersion making the call to this store  }
+{  routine and resetting the ofGrafVersion flag after the call.             }
+{---------------------------------------------------------------------------}
+PROCEDURE TWindow.Store (Var S: TStream);
+BEGIN
+   TGroup.Store(S);                                   { Call group store }
+   S.Write(Flags, 1);                                 { Write window flags }
+   S.Write(Number, 2);                                { Write window number }
+   S.Write(Palette, 2);                               { Write window palette }
+   S.Write(ZoomRect.A.X, 2);                          { Write zoom area x1 }
+   S.Write(ZoomRect.A.Y, 2);                          { Write zoom area y1 }
+   S.Write(ZoomRect.B.X, 2);                          { Write zoom area x2 }
+   S.Write(ZoomRect.B.Y, 2);                          { Write zoom area y2 }
+   PutSubViewPtr(S, Frame);                           { Write any frame }
+   S.WriteStr(Title);                                 { Write title string }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  HandleEvent -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 11Aug99 LdB       }
+{---------------------------------------------------------------------------}
+PROCEDURE TWindow.HandleEvent (Var Event: TEvent);
+VAR {$IFDEF OS_DOS} I, J: Integer; {$ENDIF} Min, Max: TPoint; Limits: TRect;
+
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+   PROCEDURE DragWindow (Mode: Byte);
+   VAR Limits: TRect; Min, Max: TPoint;
+   BEGIN
+     Owner^.GetExtent(Limits);                        { Get owner extents }
+     SizeLimits(Min, Max);                            { Restrict size }
+     DragView(Event, DragMode OR Mode, Limits, Min,
+       Max);                                          { Drag the view }
+     ClearEvent(Event);                               { Clear the event }
+   END;
+   {$ENDIF}
+
+BEGIN
+   Inherited HandleEvent(Event);                      { Call ancestor }
+   Case Event.What Of
+     evNothing: Exit;                                 { Speeds up exit }
+     evCommand:                                       { COMMAND EVENT }
+       Case Event.Command Of                          { Command type case }
+         cmResize:                                    { RESIZE COMMAND }
+           If (Flags AND (wfMove + wfGrow) <> 0)      { Window can resize }
+           AND (Owner <> Nil) Then Begin              { Valid owner }
+             Owner^.GetExtent(Limits);                { Owners extents }
+             SizeLimits(Min, Max);                    { Check size limits }
+             DragView(Event, DragMode OR (Flags AND
+               (wfMove + wfGrow)), Limits, Min, Max); { Drag the view }
+             ClearEvent(Event);                       { Clear the event }
+           End;
+         cmClose:                                     { CLOSE COMMAND }
+           If (Flags AND wfClose <> 0) AND            { Close flag set }
+           ((Event.InfoPtr = Nil) OR                  { None specific close }
+           (Event.InfoPtr = @Self)) Then Begin        { Close to us }
+             ClearEvent(Event);                       { Clear the event }
+             If (State AND sfModal = 0) Then Close    { Non modal so close }
+             Else Begin                               { Modal window }
+               Event.What := evCommand;               { Command event }
+               Event.Command := cmCancel;             { Cancel command }
+               PutEvent(Event);                       { Place on queue }
+               ClearEvent(Event);                     { Clear the event }
+             End;
+           End;
+         cmZoom:                                      { ZOOM COMMAND }
+           If (Flags AND wfZoom <> 0) AND             { Zoom flag set }
+           ((Event.InfoPtr = Nil) OR                  { No specific zoom }
+           (Event.InfoPtr = @Self)) Then Begin
+             Zoom;                                    { Zoom our window }
+             ClearEvent(Event);                       { Clear the event }
+           End;
+       End;
+     evBroadcast:                                     { BROADCAST EVENT }
+       If (Event.Command = cmSelectWindowNum) AND
+       (Event.InfoInt = Number) AND                   { Select our number }
+       (Options AND ofSelectable <> 0) Then Begin     { Is view selectable }
+         Select;                                      { Select our view }
+         ClearEvent(Event);                           { Clear the event }
+       End;
+     evKeyDown: Begin                                 { KEYDOWN EVENT }
+       Case Event.KeyCode Of
+         kbTab: Begin                                 { TAB KEY }
+           FocusNext(False);                          { Select next view }
+           ClearEvent(Event);                         { Clear the event }
+         End;
+         kbShiftTab: Begin                            { SHIFT TAB KEY }
+           FocusNext(True);                           { Select prior view }
+           ClearEvent(Event);                         { Clear the event }
+         End;
+       End;
+     End;
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE ONLY }
+     evMouseDown:                                     { MOUSE DOWN EVENT }
+       If (GOptions AND goTitled <> 0) Then Begin     { Must have title area }
+         If (GOptions AND goThickFramed <> 0) Then
+           I := 5 Else                                { Thick frame adjust }
+           If (Options AND ofFramed <> 0) Then I := 1 { Frame adjust }
+             Else I := 0;                             { No frame size }
+         If (Event.Where.Y > (RawOrigin.Y + I)) AND
+         (Event.Where.Y < RawOrigin.Y+FontHeight+I)
+         Then Begin                                   { Within top line }
+           If (Current <> Nil) AND
+           (Current^.Options AND ofSelectable <> 0)
+             Then Current^.FocusFromTop Else
+             FocusFromTop;
+           If (Flags AND wfClose <> 0) Then Begin     { Has close icon }
+             J := I + FontWidth;                      { Set X value }
+             If (Event.Where.X > RawOrigin.X+J) AND
+             (Event.Where.X < RawOrigin.X+J+2*FontWidth)
+             Then Begin                               { In close area }
+               Event.What := evCommand;               { Command event }
+               Event.Command := cmClose;              { Close command }
+               Event.InfoPtr := Nil;                  { Clear pointer }
+               PutEvent(Event);                       { Put event on queue }
+               ClearEvent(Event);                     { Clear the event }
+               Exit;                                  { Now exit }
+             End;
+           End;
+           If (Owner <> Nil) AND (Flags AND wfMove <> 0)
+             Then DragWindow(dmDragMove);             { Drag the window }
+         End Else If (Event.Where.X >= RawOrigin.X + RawSize.X-2*FontWidth) AND
+         (Event.Where.Y >= RawOrigin.Y + RawSize.Y - FontHeight)
+         Then If (Flags AND wfGrow <> 0) Then         { Check grow flags }
+           DragWindow(dmDragGrow);                    { Change window size }
+       End;
+     {$ENDIF}
+   End;                                               { Event.What case end }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  SizeLimits -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 15Sep97 LdB        }
+{---------------------------------------------------------------------------}
+PROCEDURE TWindow.SizeLimits (Var Min, Max: TPoint);
+BEGIN
+   Inherited SizeLimits(Min, Max);                    { View size limits }
+   Min.X := MinWinSize.X;                             { Set min x size }
+   Min.Y := MinWinSize.Y;                             { Set min y size }
+END;
+
+{$IFNDEF OS_DOS}
+{***************************************************************************}
+{                   TWindow OBJECT WIN/NT/OS2 ONLY METHODS                  }
+{***************************************************************************}
+
+{--TWindow------------------------------------------------------------------}
+{  GetClassText -> Platforms WIN/NT/OS2 - Updated 18Jul99 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TWindow.GetClassText: String;
+BEGIN
+   GetClassText := GetTitle(255);                     { Return window title }
+END;
+
+{--TWindow------------------------------------------------------------------}
+{  GetClassAttr -> Platforms WIN/NT/OS2 - Updated 17Mar98 LdB               }
+{---------------------------------------------------------------------------}
+FUNCTION TWindow.GetClassAttr: LongInt;
+VAR Li: LongInt;
+BEGIN
+   Li := Inherited GetClassAttr;                      { Call ancestor }
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (Flags AND wfZoom <> 0) Then Li := Li OR        { Check zoom flags }
+     ws_MinimizeBox OR ws_MaximizeBox;                { Add min/max boxes }
+   If (Flags AND wfClose <> 0) Then                   { Check close option }
+     Li := Li OR ws_SysMenu;                          { Set menu flag }
+   Li := Li OR ws_ClipSiblings OR ws_ClipChildren;    { Clip other windows }
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   If (Flags AND wfZoom <> 0) Then Li := Li OR        { Check zoom flags }
+     fcf_MinButton OR fcf_MaxButton;                  { Add min/max boxes }
+   If (Flags AND wfClose <> 0) Then                   { Check close option }
+     Li := Li OR fcf_SysMenu;                         { Set menu flag }
+   {$ENDIF}
+   GetClassAttr := Li;                                { Return masks }
+END;
+
+{$ENDIF}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                       UNCOMPLETED OBJECT METHODS                          }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+
+
+{--TView--------------------------------------------------------------------}
+{  Exposed -> Platforms DOS/DPMI/WIN/OS2 - Checked 17Sep97 LdB              }
+{---------------------------------------------------------------------------}
+{ This needs big help!!!!!   }
+FUNCTION TView.Exposed: Boolean;
+VAR ViewPort: ViewPortType;
+BEGIN
+   GetViewSettings(ViewPort);                         { Fetch viewport }
+   If (State AND sfVisible<>0) AND                    { View visible }
+     (State AND sfExposed<>0) AND                     { View exposed }
+     OverlapsArea(ViewPort.X1, ViewPort.Y1,
+     ViewPort.X2, ViewPort.Y2) Then Exposed := True   { Must be exposed }
+       Else Exposed := False;                         { Is hidden }
+END;
+
+{--TView--------------------------------------------------------------------}
+{  GraphLine -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 22Sep99 LdB         }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.GraphLine (X1, Y1, X2, Y2: Integer; Colour: Byte);
+VAR {$IFDEF OS_DOS} ViewPort: ViewPortType; {$ENDIF}  { DOS/DPMI VARIABLES }
+    {$IFDEF OS_WINDOWS} I: Word; ODc: hDc; {$ENDIF}   { WIN/NT VARIABLES }
+    {$IFDEF OS_OS2} I: LongInt; Lp: PointL; OPs: HPs; {$ENDIF}{ OS2 VARIABLES }
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+   GetViewSettings(ViewPort);                         { Get viewport settings }
+   SetColor(Colour);                                  { Set line colour }
+   Line(RawOrigin.X + X1 - ViewPort.X1,
+     RawOrigin.Y + Y1 - ViewPort.Y1, RawOrigin.X + X2
+     - ViewPort.X1, RawOrigin.Y + Y2-ViewPort.Y1);    { Draw the line }
+   {$ENDIF}
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (HWindow <> 0) Then Begin                       { Valid window }
+     X1 := X1 - FrameSize;                            { Adjust X1 for frame }
+     X2 := X2 - FrameSize;                            { Adjust X2 for frame }
+     Y1 := Y1 - CaptSize;                             { Adjust Y1 for title }
+     Y2 := Y2 - CaptSize;                             { Adjust Y2 for title }
+     ODc := Dc;                                       { Hold device context }
+     If (Dc = 0) Then Dc := GetDC(HWindow);           { Create a context }
+     SelectObject(Dc, ColPen[Colour]);                { Select line colour }
+     Case WriteMode Of
+       NormalPut: I := R2_CopyPen;                    { Normal overwrite }
+       AndPut: I := R2_MaskPen;                       { AND colour write }
+       OrPut: I := R2_MergePen;                       { OR colour write }
+       XorPut: I := R2_XORPen;                        { XOR colour write }
+       NotPut: I := R2_Not;                           { NOT colour write }
+     End;
+     SetRop2(Dc, I);                                  { Set write mode }
+     {$IFDEF BIT_16}                                  { 16 BIT WIN CODE }
+     WinProcs.MoveTo(Dc, X1, Y1);                     { Move to first point }
+     {$ELSE}                                          { 32 BIT WIN/NT CODE }
+     MoveToEx(Dc, X1, Y1, Nil);                       { Move to first point }
+     {$ENDIF}
+     If (Abs(X2-X1) > 1) OR (Abs(Y2-Y1) > 1) Then     { Not single point }
+       LineTo(Dc, X2, Y2);                            { Line to second point }
+     SetPixel(Dc, X2, Y2, ColRef[Colour]);            { Draw last point }
+     If (ODc = 0) Then ReleaseDC(HWindow, Dc);        { Release context }
+     Dc := ODc;                                       { Reset held context }
+   End;
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   If (HWindow <> 0) Then Begin                       { Valid window }
+     X1 := X1 - FrameSize;                            { Adjust X1 for frame }
+     X2 := X2 - FrameSize;                            { Adjust X2 for frame }
+     Y1 := Y1 - CaptSize;                             { Adjust Y1 for title }
+     Y2 := Y2 - CaptSize;                             { Adjust Y2 for title }
+     OPs := Ps;                                       { Hold paint struct }
+     If (Ps = 0) Then Ps := WinGetPS(Client);         { Create paint struct }
+     Case WriteMode Of
+       NormalPut: I := fm_Overpaint;                  { Normal overwrite }
+       AndPut: I := fm_And;                           { AND colour write }
+       OrPut: I := fm_Or;                             { OR colour write }
+       XorPut: I := fm_Xor;                           { XOR colour write }
+       NotPut: I := fm_Invert;                        { NOT colour write }
+     End;
+     GPISetMix(Ps, I);                                { Set write mode }
+     GPISetColor(Ps, ColRef[Colour]);
+     Lp.X := X1;                                      { Transfer x1 value }
+     Lp.Y := RawSize.Y-Y1;                            { Transfer y1 value }
+     GPIMove(Ps, Lp);                                 { Move to first point }
+     Lp.X := X2;                                      { Transfer x2 value }
+     Lp.Y := RawSize.Y-Y2;                            { Transfer y2 value }
+     GPILine(Ps, Lp);                                 { Line to second point }
+     If (OPs = 0) Then WinReleasePS(Ps);              { Release paint struct }
+     Ps := OPs;                                       { Reset held struct }
+   End;
+   {$ENDIF}
+END;
+
+PROCEDURE TView.GraphRectangle (X1, Y1, X2, Y2: Integer; Colour: Byte);
+VAR {$IFDEF OS_DOS} ViewPort: ViewPortType; {$ENDIF}
+    {$IFDEF OS_WINDOWS} I: Word; ODc: hDc; {$ENDIF}
+    {$IFDEF OS_OS2} Lp: PointL; OPs: HPs; {$ENDIF}
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+   SetColor(Colour);                                  { Set line colour }
+   GetViewSettings(ViewPort);
+   Rectangle(RawOrigin.X + X1 - ViewPort.X1, RawOrigin.Y + Y1
+     - ViewPort.Y1, RawOrigin.X + X2 - ViewPort.X1,
+     RawOrigin.Y+Y2-ViewPort.Y1);                     { Draw a rectangle }
+   {$ENDIF}
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (HWindow <> 0) Then Begin                       { Valid window }
+     X1 := X1 - FrameSize;
+     X2 := X2 - FrameSize;
+     Y1 := Y1 - CaptSize;
+     Y2 := Y2 - CaptSize;
+     ODc := Dc;                                       { Hold device context }
+     If (Dc = 0) Then Dc := GetDC(HWindow);           { Create a context }
+     SelectObject(Dc, ColPen[Colour]);
+     Case WriteMode Of
+       NormalPut: I := R2_CopyPen;                    { Normal overwrite }
+       AndPut: I := R2_MaskPen;                       { AND colour write }
+       OrPut: I := R2_MergePen;                       { OR colour write }
+       XorPut: I := R2_XORPen;                        { XOR colour write }
+       NotPut: I := R2_Not;                           { NOT colour write }
+     End;
+     SetRop2(Dc, I);
+     {$IFDEF WIN32}
+     MoveToEx(Dc, X1, Y1, Nil);                       { Move to first point }
+     {$ELSE}
+     WinProcs.MoveTo(Dc, X1, Y1);                     { Move to first point }
+     {$ENDIF}
+     LineTo(Dc, X2, Y1);                              { Line to second point }
+     LineTo(Dc, X2, Y2);                              { Line to third point }
+     LineTo(Dc, X1, Y2);                              { Line to fourth point }
+     LineTo(Dc, X1, Y1);                              { Line to first point }
+     If (ODc = 0) Then ReleaseDC(HWindow, Dc);        { Release context }
+     Dc := ODc;                                       { Reset held context }
+   End;
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   If (HWindow <> 0) Then Begin                       { Valid window }
+     X1 := X1 - FrameSize;                            { Adjust X1 for frame }
+     X2 := X2 - FrameSize;                            { Adjust X2 for frame }
+     Y1 := Y1 - CaptSize;                             { Adjust Y1 for title }
+     Y2 := Y2 - CaptSize;                             { Adjust Y2 for title }
+     OPs := Ps;                                       { Hold paint struct }
+     If (Ps = 0) Then Ps := WinGetPS(Client);         { Create paint struct }
+     GPISetColor(Ps, ColRef[Colour]);                 { Set colour }
+     Lp.X := X1;                                      { Transfer x1 value }
+     Lp.Y := RawSize.Y-Y1;                            { Transfer y1 value }
+     GPIMove(Ps, Lp);                                 { Move to first point }
+     Lp.X := X2;                                      { Transfer x2 value }
+     Lp.Y := RawSize.Y-Y1;                            { Transfer y1 value }
+     GPILine(Ps, Lp);                                 { Line to second point }
+     Lp.X := X2;                                      { Transfer x2 value }
+     Lp.Y := RawSize.Y-Y2;                            { Transfer y2 value }
+     GPILine(Ps, Lp);                                 { Line to third point }
+     Lp.X := X1;                                      { Transfer x1 value }
+     Lp.Y := RawSize.Y-Y2;                            { Transfer y2 value }
+     GPILine(Ps, Lp);                                 { Line to fourth point }
+     Lp.X := X1;                                      { Transfer x1 value }
+     Lp.Y := RawSize.Y-Y1;                            { Transfer y1 value }
+     GPILine(Ps, Lp);                                 { Line to first point }
+     If (OPs = 0) Then WinReleasePS(Ps);              { Release paint struct }
+     Ps := OPs;                                       { Reset held struct }
+   End;
+   {$ENDIF}
+END;
+
+{--TView--------------------------------------------------------------------}
+{  ClearArea -> Platforms DOS/DPMI/WIN/OS2 - Checked 19Sep97 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.ClearArea (X1, Y1, X2, Y2: Integer; Colour: Byte);
+VAR {$IFDEF OS_DOS} ViewPort: ViewPortType; {$ENDIF}
+    {$IFDEF OS_WINDOWS} ODc: hDc; {$ENDIF}
+    {$IFDEF OS_OS2} Lp: PointL; OPs: HPs; {$ENDIF}
+BEGIN
+   {$IFDEF OS_DOS}                                    { DOS/DPMI CODE }
+   GetViewSettings(ViewPort);                         { Get viewport }
+   SetFillStyle(SolidFill, Colour);                   { Set colour up }
+   Bar(RawOrigin.X+X1-ViewPort.X1, RawOrigin.Y+Y1-
+     ViewPort.Y1, RawOrigin.X+X2-ViewPort.X1,
+     RawOrigin.Y+Y2-ViewPort.Y1);                     { Clear the area }
+   {$ENDIF}
+   {$IFDEF OS_WINDOWS}                                { WIN/NT CODE }
+   If (HWindow <> 0) Then Begin                       { Valid window }
+     X1 := X1 - FrameSize;                            { Correct for frame }
+     Y1 := Y1 - CaptSize;                             { Correct for caption }
+     X2 := X2 - FrameSize;                            { Correct for frame }
+     Y2 := Y2 - CaptSize;                             { Correct for caption }
+     ODc := Dc;                                       { Hold device context }
+     If (Dc = 0) Then Dc := GetDC(HWindow);           { Create a context }
+     SelectObject(Dc, ColPen[Colour]);
+     SelectObject(Dc, ColBrush[Colour]);
+     {$IFNDEF PPC_SPEED}
+     Rectangle(Dc, X1, Y1, X2+1, Y2+1);
+     {$ELSE}                                          { SPEEDSOFT SYBIL2+ }
+     WinGDI.Rectangle(Dc, X1, Y1, X2+1, Y2+1);
+     {$ENDIF}
+     If (ODc = 0) Then ReleaseDC(HWindow, Dc);        { Release context }
+     Dc := ODc;                                       { Reset held context }
+   End;
+   {$ENDIF}
+   {$IFDEF OS_OS2}                                    { OS2 CODE }
+   If (HWindow <> 0) Then Begin                       { Valid window }
+     X1 := X1 - FrameSize;                            { Adjust X1 for frame }
+     X2 := X2 - FrameSize;                            { Adjust X2 for frame }
+     Y1 := Y1 - CaptSize;                             { Adjust Y1 for title }
+     Y2 := Y2 - CaptSize;                             { Adjust Y2 for title }
+     OPs := Ps;                                       { Hold paint struct }
+     If (Ps = 0) Then Ps := WinGetPs(Client);         { Create paint struct }
+     GpiSetColor(Ps, ColRef[Colour]);
+     Lp.X := X1;
+     Lp.Y := RawSize.Y-Y1;
+     GpiMove(Ps, Lp);
+     Lp.X := X2;
+     Lp.Y := RawSize.Y-Y2;
+     GpiBox(Ps, dro_Fill, Lp, 0, 0);
+     If (OPs = 0) Then WinReleasePS(Ps);              { Release paint struct }
+     Ps := OPs;                                       { Reset held struct }
+   End;
+   {$ENDIF}
+END;
+
+
+PROCEDURE TView.GraphArc (Xc, Yc: Integer; Sa, Ea: Real; XRad, YRad: Integer;
+Colour: Byte);
+CONST RadConv  = 57.2957795130823229;                 { Degrees per radian }
+VAR X1, Y1, X2, Y2: Integer; {$IFDEF OS_WINDOWS} ODc: hDc; {$ENDIF}
+BEGIN
+   {$IFDEF OS_WINDOWS}
+   Xc := Xc - FrameSize;
+   Yc := Yc - CaptSize;
+   {$ENDIF}
+   While (Ea < -360) Do Ea := Ea + 360;               { Max of a full circle }
+   While (Ea > 360) Do Ea := Ea - 360;                { Max of a full circle }
+   Sa := Sa/RadConv;                                  { Convert to radians }
+   Ea := Ea/RadConv;                                  { Convert to radians }
+   X1 := Xc + Round(Sin(Sa)*XRad);                    { Calc 1st x value }
+   Y1 := Yc - Round(Cos(Sa)*YRad);                    { Calc 1st y value }
+   X2 := Xc + Round(Sin(Sa+Ea)*XRad);                 { Calc 2nd x value }
+   Y2 := Yc - Round(Cos(Sa+Ea)*YRad);                 { Calc 2nd y value }
+   {$IFDEF OS_WINDOWS}
+   If (HWindow <> 0) Then Begin                       { Valid window }
+     ODc := Dc;                                       { Hold device context }
+     If (Dc = 0) Then Dc := GetDC(HWindow);           { Create a context }
+     SelectObject(Dc, ColPen[Colour]);                { Pen colour }
+     If (XRad > 2 ) AND (YRAd > 2) Then Begin         { Must exceed 2x2 arc }
+       If (Ea < 0) Then
+         Arc(Dc, Xc-XRad, Yc-YRad, Xc+XRad, Yc+YRad,
+           X1, Y1, X2, Y2) Else                       { Draw c/clkwise arc }
+         Arc(Dc, Xc-XRad, Yc+YRad, Xc+XRad, Yc-YRad,
+           X2, Y2, X1, Y1);                           { Draw clockwise arc }
+     End;
+     If (ODc = 0) Then ReleaseDC(HWindow, Dc);        { Release context }
+     Dc := ODc;                                       { Reset held context }
+   End;
+   {$ENDIF}
+END;
+
+PROCEDURE TView.FilletArc (Xc, Yc: Integer; Sa, Ea: Real; XRad, YRad, Ht: Integer;
+Colour: Byte);
+CONST RadConv  = 57.2957795130823229;                 { Degrees per radian }
+{$IFDEF OS_WINDOWS} VAR X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer; ODc: hDc; {$ENDIF}
+BEGIN
+   {$IFDEF OS_WINDOWS}
+   If (HWindow <> 0) Then Begin                       { Valid window }
+     Xc := Xc - FrameSize;
+     Yc := Yc - CaptSize;
+     ODc := Dc;                                       { Hold device context }
+     If (Dc = 0) Then Dc := GetDC(HWindow);           { Create a context }
+     Ea := (Ea-Sa);
+     While (Ea<-360) Do Ea := Ea+360;                 { One lap only }
+     While (Ea>360) Do Ea := Ea-360;                  { One lap only }
+     X1 := Round(Sin(Sa/RadConv)*XRad);
+     Y1 := -Round(Cos(Sa/RadConv)*YRad);              { Calc 1st values }
+     X2 := Round(Sin((Sa+Ea)/RadConv)*XRad);
+     Y2 := -Round(Cos((Sa+Ea)/RadConv)*YRad);         { Calc 2nd values }
+     X3 := Round(Sin(Sa/RadConv)*(XRad+Ht));
+     Y3 := -Round(Cos(Sa/RadConv)*(YRad+Ht));         { Calc 3rd values }
+     X4 := Round(Sin((Sa+Ea)/RadConv)*(XRad+Ht));
+     Y4 := -Round(Cos((Sa+Ea)/RadConv)*(YRad+Ht));    { Calc 4th values }
+     SelectObject(Dc, ColPen[Colour]);                { Pen colour }
+     {$IFDEF WIN32}
+     MoveToEx(Dc, Xc+X1, Yc+Y1, Nil);                 { Move to first point }
+     {$ELSE}
+     WinProcs.MoveTo(Dc, Xc+X1, Yc+Y1);               { Move to first point }
+     {$ENDIF}
+     LineTo(Dc, Xc+X3, Yc+Y3);
+     {$IFDEF WIN32}
+     MoveToEx(Dc, Xc+X2, Yc+Y2, Nil);
+     {$ELSE}
+     WinProcs.MoveTo(Dc, Xc+X2, Yc+Y2);
+     {$ENDIF}
+     LineTo(Dc, Xc+X4, Yc+Y4);
+     If (Ea < 0) Then
+       Arc(Dc, Xc-XRad-Ht, Yc-YRad-Ht, Xc+XRad+Ht, Yc+YRad+Ht,
+         Xc+X1, Yc+Y1, Xc+X2, Yc+Y2) Else
+       Arc(Dc, Xc-XRad-Ht, Yc-YRad-Ht, Xc+XRad+Ht, Yc+YRad+Ht,
+         Xc+X2, Yc+Y2, Xc+X1, Yc+Y1);                 { Draw arc }
+     If (Ea < 0) Then
+       Arc(Dc, Xc-XRad, Yc-YRad, Xc+XRad, Yc+YRad,
+         Xc+X3, Yc+Y3, Xc+X4, Yc+Y4) Else
+       Arc(Dc, Xc-XRad, Yc-YRad, Xc+XRad, Yc+YRad,
+         Xc+X4, Yc+Y4, Xc+X3, Yc+Y3);                 { Draw arc }
+     If (ODc = 0) Then ReleaseDC(HWindow, Dc);        { Release context }
+     Dc := ODc;                                       { Reset held context }
+   End;
+   {$ENDIF}
+END;
+
+{--TView--------------------------------------------------------------------}
+{  BiColorRectangle -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 06May98 LdB  }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.BicolorRectangle (X1, Y1, X2, Y2: Integer; Light, Dark: Byte;
+Down: Boolean);
+VAR UpperLeft, RightDown: Byte;
+BEGIN
+   If Down Then Begin
+     UpperLeft := Dark;                               { Dark upper left }
+     RightDown := Light;                              { Light down }
+   End Else Begin
+     UpperLeft := Light;                              { Light upper left }
+     RightDown := Dark;                               { Dark down }
+   End;
+   GraphLine(X1, Y1, X1, Y2, UpperLeft);              { Draw left side }
+   GraphLine(X1, Y1, X2, Y1, UpperLeft);              { Draw top line }
+   GraphLine(X1, Y2, X2, Y2, RightDown);              { Draw bottom line }
+   GraphLine(X2, Y1, X2, Y2, RightDown);              { Draw right line }
+END;
+
+PROCEDURE TView.WriteBuf (X, Y, W, H: Integer; Var Buf);
+VAR I, J, K, L, CW: Integer; P: PDrawBuffer;
+    {$IFDEF OS_DOS} ViewPort: ViewPortType; {$ENDIF}
+    {$IFDEF OS_WINDOWS} ODc: HDc; {$ENDIF}
+    {$IFDEF OS_OS2} OPs: HPs; Pt: PointL; {$ENDIF}
+BEGIN
+   If (State AND sfVisible <> 0) AND                  { View is visible }
+   (State AND sfIconised = 0) AND                     { View is not icon}
+   (State AND sfExposed <> 0) AND (W > 0) AND (H > 0) { View is exposed }
+   {$IFNDEF OS_DOS} AND (HWindow <> 0) {$ENDIF}       { WIN/NT/OS2 CODE }
+   Then Begin
+     P := @TDrawBuffer(Buf);                          { Set draw buffer ptr }
+     L := 0;                                          { Set buffer position }
+     If (GOptions AND (goGraphical + goGraphView)= 0) Then Begin     { Not raw graphical }
+       X := X * SysFontWidth;                         { X graphical adjust }
+       Y := Y * SysFontHeight;                        { Y graphical adjust }
+     End;
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+       GetViewSettings(ViewPort);                     { Get current viewport }
+       X := X + RawOrigin.X - ViewPort.X;             { Calc x position }
+       Y := Y + RawOrigin.Y - ViewPort.Y;             { Calc y position }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+       ODc := Dc;                                     { Hold device context }
+       If (Dc = 0) Then Dc := GetDC(HWindow);         { If needed get context }
+       SelectObject(Dc, DefGFVFont);                  { Select the font }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+       OPs := Ps;                                     { Hold pres space }
+       If (Ps = 0) Then Ps := WinGetPS(Client);       { If needed get PS }
+       GPISetCharSet(Ps, DefGFVFont);                 { Select the font }
+       GpiSetBackMix(Ps, bm_OverPaint);               { Set overpaint mode }
+     {$ENDIF}
+     For J := 1 To H Do Begin                         { For each line }
+       K := X;                                        { Reset x position }
+       For I := 0 To (W-1) Do Begin                   { For each character }
+         Cw := TextWidth(Chr(Lo(P^[L])));             { Width of this char }
+         {$IFDEF OS_DOS}                              { DOS/DPMI CODE }
+           SetFillStyle(SolidFill, Hi(P^[L]) AND $F0
+             SHR 4);                                  { Set back colour }
+           SetColor(Hi(P^[L]) AND $0F);               { Set text colour }
+           Bar(K, Y, K+Cw, Y+FontHeight-1);           { Clear text backing }
+           OutTextXY(K, Y+2, Chr(Lo(P^[L])));         { Write text char }
+         {$ENDIF}
+         {$IFDEF OS_WINDOWS}                          { WIN/NT CODE }
+           SetBkColor(Dc, ColRef[Hi(P^[L]) AND $F0
+             SHR 4]);                                 { Set back colour }
+           SetTextColor(Dc, ColRef[Hi(P^[L])
+             AND $0F]);                               { Set text colour }
+           TextOut(Dc, K, Y, @P^[L], 1);              { Write text char }
+         {$ENDIF}
+         {$IFDEF OS_OS2}                              { OS2 CODE }
+           GPISetBackColor(Ps, ColRef[Hi(P^[L])
+             AND $F0 SHR 4]);                         { Set back colour }
+           GpiSetColor(Ps, ColRef[Hi(P^[L])
+             AND $0F]);                               { Set text colour }
+           Pt.X := K;
+           Pt.Y := RawSize.Y - Y - FontHeight + 5;
+           GpiCharStringAt(Ps, Pt, 1, @P^[L]);        { Write text char }
+         {$ENDIF}
+         K := K + Cw;                                 { Add char width }
+         Inc(L);                                      { Next character }
+       End;
+       Y := Y + SysFontHeight;                        { Next line down }
+     End;
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+       If (ODc = 0) Then ReleaseDC(HWindow, Dc);      { Release context }
+       Dc := ODc;                                     { Restore old context }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+       If (OPs = 0) Then WinReleasePS(Ps);            { Release pres space }
+       Ps := OPs;                                     { Restore original PS }
+     {$ENDIF}
+   End;
+END;
+
+PROCEDURE TView.WriteLine (X, Y, W, H: Integer; Var Buf);
+VAR I, J, K, Cw: Integer; P: PDrawBuffer;
+    {$IFDEF OS_DOS} ViewPort: ViewPortType; {$ENDIF}
+    {$IFDEF OS_WINDOWS} ODc: HDc; {$ENDIF}
+    {$IFDEF OS_OS2} OPs: HPs; Pt: PointL; {$ENDIF}
+BEGIN
+   If (State AND sfVisible <> 0) AND                  { View is visible }
+   (State AND sfIconised = 0) AND                     { View is not icon}
+   (State AND sfExposed <> 0) AND (W > 0) AND (H > 0) { View is exposed }
+   {$IFNDEF OS_DOS} AND (HWindow <> 0) {$ENDIF}       { WIN/NT/OS2 CODE }
+   Then Begin
+     P := @TDrawBuffer(Buf);                          { Set draw buffer ptr }
+     If (GOptions AND (goGraphical + goGraphView)= 0) Then Begin     { Not raw graphical }
+       X := X * SysFontWidth;                         { X graphical adjust }
+       Y := Y * SysFontHeight;                        { Y graphical adjust }
+     End;
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+       GetViewSettings(ViewPort);                     { Get current viewport }
+       X := X + RawOrigin.X - ViewPort.X;             { Calc x position }
+       Y := Y + RawOrigin.Y - ViewPort.Y;             { Calc y position }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+       ODc := Dc;                                     { Hold device context }
+       If (Dc = 0) Then Dc := GetDC(HWindow);         { If needed get context }
+       SelectObject(Dc, DefGFVFont);                  { Select the font }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+       OPs := Ps;                                     { Hold pres space }
+       If (Ps = 0) Then Ps := WinGetPS(Client);       { If needed get PS }
+       GPISetCharSet(Ps, DefGFVFont);                 { Select the font }
+       GpiSetBackMix(Ps, bm_OverPaint);               { Set overpaint mode }
+     {$ENDIF}
+     For J := 1 To H Do Begin                         { For each line }
+       K := X;                                        { Reset x position }
+       For I := 0 To (W-1) Do Begin                   { For each character }
+         Cw := TextWidth(Chr(Lo(P^[I])));             { Width of this char }
+         {$IFDEF OS_DOS}                              { DOS/DPMI CODE }
+           SetFillStyle(SolidFill, Hi(P^[I]) AND $F0
+             SHR 4);                                  { Set back colour }
+           SetColor(Hi(P^[I]) AND $0F);               { Set text colour }
+           Bar(K, Y, K+Cw, Y+FontHeight-1);           { Clear text backing }
+           OutTextXY(K, Y+2, Chr(Lo(P^[I])));         { Write text char }
+         {$ENDIF}
+         {$IFDEF OS_WINDOWS}                          { WIN/NT CODE }
+           SetBkColor(Dc, ColRef[Hi(P^[I]) AND $F0
+             SHR 4]);                                 { Set back colour }
+           SetTextColor(Dc, ColRef[Hi(P^[I])
+             AND $0F]);                               { Set text colour }
+           TextOut(Dc, K, Y, @P^[I], 1);              { Write text char }
+         {$ENDIF}
+         {$IFDEF OS_OS2}                              { OS2 CODE }
+           GPISetBackColor(Ps, ColRef[Hi(P^[I])
+             AND $F0 SHR 4]);                         { Set back colour }
+           GpiSetColor(Ps, ColRef[Hi(P^[I])
+             AND $0F]);                               { Set text colour }
+           Pt.X := K;
+           Pt.Y := RawSize.Y - Y - FontHeight + 5;
+           GpiCharStringAt(Ps, Pt, 1, @P^[I]);        { Write text char }
+         {$ENDIF}
+         K := K + Cw;                                 { Add char width }
+       End;
+       Y := Y + SysFontHeight;                        { Next line down }
+     End;
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+       If (ODc = 0) Then ReleaseDC(HWindow, Dc);      { Release context }
+       Dc := ODc;                                     { Restore old context }
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+       If (OPs = 0) Then WinReleasePS(Ps);            { Release pres space }
+       Ps := OPs;                                     { Restore original PS }
+     {$ENDIF}
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  MakeLocal -> Platforms DOS/DPMI/WIN/OS2 - Checked 12Sep97 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.MakeLocal (Source: TPoint; Var Dest: TPoint);
+BEGIN
+   If (Options AND ofGFVModeView <> 0) Then Begin     { GFV MODE TVIEW }
+     Dest.X := (Source.X-RawOrigin.X) DIV FontWidth;  { Local x value }
+     Dest.Y := (Source.Y-RawOrigin.Y) DIV FontHeight; { Local y value }
+   End Else Begin                                     { OLD MODE TVIEW }
+     Dest.X := Source.X - Origin.X;                   { Local x value }
+     Dest.Y := Source.Y - Origin.Y;                   { Local y value }
+   End;
+END;
+
+{--TView--------------------------------------------------------------------}
+{  MakeGlobal -> Platforms DOS/DPMI/WIN/OS2 - Checked 12Sep97 LdB           }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.MakeGlobal (Source: TPoint; Var Dest: TPoint);
+BEGIN
+   If (Options AND ofGFVModeView <> 0) Then Begin     { GFV MODE TVIEW }
+     Dest.X := Source.X*FontWidth + RawOrigin.X;      { Global x value }
+     Dest.Y := Source.Y*FontHeight + RawOrigin.Y;     { Global y value }
+   End Else Begin                                     { OLD MODE TVIEW }
+     Dest.X := Source.X + Origin.X;                   { Global x value }
+     Dest.Y := Source.Y + Origin.Y;                   { Global y value }
+   End;
+END;
+
+PROCEDURE TView.WriteStr (X, Y: Integer; Str: String; Color: Byte);
+VAR Fc, Bc: Byte; X1, Y1, X2, Y2: Integer;
+    {$IFDEF OS_DOS} ViewPort: ViewPortType; {$ENDIF}
+    {$IFDEF OS_WINDOWS} ODc: HDc; P: Pointer; {$ENDIF}
+    {$IFDEF OS_OS2} OPs: HPs; P: Pointer; Pt: PointL; {$ENDIF}
+BEGIN
+   If (State AND sfVisible <> 0) AND                  { View is visible }
+   (State AND sfExposed <> 0) AND                     { View is exposed }
+   (State AND sfIconised = 0) AND                     { View not iconized }
+   (Length(Str) > 0) Then Begin                       { String is valid }
+
+     Fc := GetColor(Color);                           { Get view color }
+     Bc := Fc AND $F0 SHR 4;                          { Calc back colour }
+     Fc := Fc AND $0F;                                { Calc text colour }
+     {$IFDEF OS_DOS}
+     If (X >= 0) AND (Y >= 0) Then Begin
+       X := RawOrigin.X+X*FontWidth;                    { X position }
+       Y := RawOrigin.Y+Y*FontHeight;                   { Y position }
+     End Else Begin
+       X := RawOrigin.X + Abs(X);
+       Y := RawOrigin.Y + Abs(Y);
+     End;
+     GetViewSettings(ViewPort);
+     SetFillStyle(SolidFill, Bc);                     { Set fill style }
+     Bar(X-ViewPort.X1, Y-ViewPort.Y1,
+       X-ViewPort.X1+Length(Str)*FontWidth, Y-ViewPort.Y1+FontHeight-1);
+     SetColor(Fc);
+     OutTextXY(X-ViewPort.X1, Y-ViewPort.Y1+2, Str);    { Write text char }
+     {$ENDIF}
+     {$IFDEF OS_WINDOWS}
+     If (HWindow <> 0) Then Begin
+       ODc := Dc;                                     { Hold device handle }
+       If (Dc = 0) Then Dc := GetDC(HWindow);         { Chk capture context }
+       SelectObject(Dc, DefGFVFont);
+       SetTextColor(Dc, ColRef[Fc]);                  { Set text colour }
+       SetBkColor(Dc, ColRef[Bc]);                    { Set back colour }
+       If (GOptions AND goGraphView <> 0) OR (X < 0)
+       OR (Y < 0) Then Begin
+         X := Abs(X);
+         Y := Abs(Y);
+         X1 := X - FrameSize;               { Left position }
+         Y1 := Y - CaptSize;               { Top position }
+         X2 := X1 + TextWidth(Str);              { Right position }
+       End Else Begin
+         X1 := X * FontWidth - FrameSize;               { Left position }
+         Y1 := Y * FontHeight - CaptSize;               { Top position }
+         X2 := X1 + Length(Str)*FontWidth;              { Right position }
+       End;
+       Y2 := Y1 + FontHeight;                         { Bottom position }
+       SelectObject(Dc, ColPen[Bc]);                  { Select pen }
+       SelectObject(Dc, ColBrush[Bc]);                { Select brush }
+       P := @Str[1];
+       Rectangle(Dc, X1, Y1, X2, Y2);                 { Clear the area }
+       {$IFNDEF PPC_SPEED}
+       TextOut(Dc, X1, Y1, P, Length(Str));           { Write text data }
+       {$ELSE}                                        { SPEEDSOFT SYBIL2+ }
+       TextOut(Dc, X1, Y1, CString(P), Length(Str));  { Write text data }
+       {$ENDIF}
+       If (ODc = 0) Then ReleaseDC(HWindow, Dc);      { Release context }
+       Dc := ODc;                                     { Clear device handle }
+     End;
+     {$ENDIF}
+     {$IFDEF OS_OS2}
+     If (HWindow <> 0) Then Begin
+       OPs := Ps;                                     { Hold device handle }
+       If (Ps = 0) Then Ps := WinGetPs(Client);      { Chk capture context }
+       {SelectObject(Dc, DefGFVFont);}
+       If (GOptions AND goGraphView <> 0) OR (X < 0)
+       OR (Y < 0) Then Begin
+         X := Abs(X);
+         Y := Abs(Y);
+         X1 := X - FrameSize;               { Left position }
+         Y1 := Y - CaptSize;               { Top position }
+         X2 := X1 + TextWidth(Str);              { Right position }
+       End Else Begin
+         X1 := X * FontWidth - FrameSize;               { Left position }
+         Y1 := Y * FontHeight - CaptSize;               { Top position }
+         X2 := X1 + Length(Str)*FontWidth;              { Right position }
+       End;
+       Y2 := Y1 + FontHeight;                         { Bottom position }
+       {SelectObject(Dc, ColPen[Bc]);}                  { Select pen }
+       {SelectObject(Dc, ColBrush[Bc]);}                { Select brush }
+       P := @Str[1];
+       (*Pt.X := X1;
+       Pt.Y := RawSize.Y - Y1;
+       GpiMove(Ps, Pt);
+       Pt.X := X2;
+       Pt.Y := RawSize.Y - Y2;
+       GpiSetColor(Ps, ColRef[Bc]);                   { Set text colour }
+       GpiBox(Ps, dro_Fill, Pt, 0, 0);*)
+
+       GpiSetColor(Ps, ColRef[Fc]);                   { Set text colour }
+       GpiSetBackColor(Ps, ColRef[Bc]);               { Set back colour }
+           GpiSetBackMix(Ps, bm_OverPaint );
+       Pt.X := X1;
+       Pt.Y := RawSize.Y - Y1 - FontHeight + 5;
+       GpiCharStringAt(Ps, Pt, Length(Str), P);   { Write text char }
+       If (OPs = 0) Then WinReleasePs(Ps);        { Release context }
+       Ps := OPs;                                 { Clear device handle }
+     End;
+     {$ENDIF}
+
+   End;
+END;
+
+PROCEDURE TView.WriteChar (X, Y: Integer; C: Char; Color: Byte;
+  Count: Integer);
+VAR Fc, Bc: Byte; I: Integer; Col: Word; S: String; ViewPort: ViewPortType;
+BEGIN
+   {$IFDEF OS_DOS}
+   If (State AND sfVisible <> 0) AND                  { View visible }
+   (State AND sfExposed <> 0) Then Begin              { View exposed }
+     GetViewSettings(ViewPort);
+     Col := GetColor(Color);                          { Get view color }
+     Fc := Col AND $0F;                               { Foreground colour }
+     Bc := Col AND $F0 SHR 4;                         { Background colour }
+     X := RawOrigin.X + X*FontWidth;                  { X position }
+     Y := RawOrigin.Y + Y*FontHeight;                 { Y position }
+     FillChar(S[1], 255, C);                          { Fill the string }
+     While (Count>0) Do Begin
+       If (Count>255) Then I := 255 Else I := Count;  { Size to make }
+       S[0] := Chr(I);                                { Set string length }
+       SetFillStyle(SolidFill, Bc);                   { Set fill style }
+       Bar(X-ViewPort.X1, Y-ViewPort.Y1,
+         X-ViewPort.X1+Length(S)*FontWidth, Y-ViewPort.Y1+FontHeight-1);
+       SetColor(Fc);
+       OutTextXY(X-ViewPort.X1, Y-ViewPort.Y1, S);    { Write text char }
+       Count := Count - I;                            { Subtract count }
+       X := X + I*FontWidth;                          { Move x position }
+     End;
+   End;
+   {$ENDIF}
+END;
+
+PROCEDURE TView.DragView (Event: TEvent; Mode: Byte; Var Limits: TRect;
+  MinSize, MaxSize: TPoint);
+VAR PState: Word; Mouse, Q, R, P, S, Op1, Op2: TPoint; SaveBounds: TRect;
+
+   FUNCTION Min (I, J: Integer): Integer;
+   BEGIN
+     If (I < J) Then Min := I Else Min := J;          { Select minimum }
+   END;
+
+   FUNCTION Max (I, J: Integer): Integer;
+   BEGIN
+     If (I > J) Then Max := I Else Max := J;          { Select maximum }
+   END;
+
+   PROCEDURE MoveGrow (P, S: TPoint);
+   VAR R: TRect;
+   BEGIN
+     S.X := Min(Max(S.X, MinSize.X), MaxSize.X);      { Minimum S.X value }
+     S.Y := Min(Max(S.Y, MinSize.Y), MaxSize.Y);      { Minimum S.Y value }
+     P.X := Min(Max(P.X, Limits.A.X - S.X + 1),
+       Limits.B.X - 1);                               { Minimum P.X value }
+     P.Y := Min(Max(P.Y, Limits.A.Y - S.Y + 1),
+       Limits.B.Y - 1);                               { Mimimum P.Y value }
+     If (Mode AND dmLimitLoX <> 0) Then
+       P.X := Max(P.X, Limits.A.X);                   { Left side move }
+     If (Mode AND dmLimitLoY <> 0) Then
+       P.Y := Max(P.Y, Limits.A.Y);                   { Top side move }
+     If (Mode AND dmLimitHiX <> 0) Then
+       P.X := Min(P.X, Limits.B.X - S.X);             { Right side move }
+     If (Mode AND dmLimitHiY <> 0) Then
+       P.Y := Min(P.Y, Limits.B.Y - S.Y);             { Bottom side move }
+     R.Assign(P.X, P.Y, P.X + S.X, P.Y + S.Y);        { Assign area }
+     Locate(R);                                       { Locate view }
+   END;
+
+   PROCEDURE Change (DX, DY: Integer);
+   BEGIN
+     If (Mode AND dmDragMove <> 0) AND
+     (GetShiftState AND $03 = 0) Then Begin
+       Inc(P.X, DX); Inc(P.Y, DY);                    { Adjust values }
+     End Else If (Mode AND dmDragGrow <> 0) AND
+     (GetShiftState AND $03 <> 0) Then Begin
+       Inc(S.X, DX); Inc(S.Y, DY);                    { Adjust values }
+     End;
+   END;
+
+   PROCEDURE Update (X, Y: Integer);
+   BEGIN
+     If (Mode AND dmDragMove <> 0) Then Begin
+       P.X := X; P.Y := Y;                            { Adjust values }
+     End;
+   END;
+
+BEGIN
+   SetState(sfDragging, True);                        { Set drag state }
+   If (Event.What = evMouseDown) Then Begin           { Mouse down event }
+     Q.X := Event.Where.X DIV FontWidth - Origin.X;   { Offset mouse x origin }
+     Q.Y := Event.Where.Y DIV FontHeight - Origin.Y;  { Offset mouse y origin }
+     Op1.X := RawOrigin.X; Op1.Y := RawOrigin.Y;      { Hold origin point }
+     Op2.X := RawOrigin.X+RawSize.X;                  { Right side x value }
+     Op2.Y := RawOrigin.Y+RawSize.Y;                  { Right side y value }
+     PState := State;                                 { Hold current state }
+     State := State AND NOT sfVisible;                { Temp not visible }
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+     HideMouseCursor;                                 { Hide the mouse }
+     {$ENDIF}
+     SetWriteMode(XORPut);
+     GraphRectangle(0, 0, RawSize.X, RawSize.Y, Red);
+     SetWriteMode(NormalPut);
+     {$IFDEF OS_DOS}                                  { DOS/DPMI CODE }
+     ShowMouseCursor;                                 { Show the mouse }
+     {$ENDIF}
+     Repeat
+       Mouse.X := Round(Event.Where.X/FontWidth)-Q.X; { New x origin point }
+       Mouse.Y := Round(Event.Where.Y/FontHeight)-Q.Y;{ New y origin point }
+       If (Mode AND dmDragMove<>0) Then Begin
+         If (Owner<>Nil) Then Begin
+           Dec(Mouse.X, Owner^.Origin.X);             { Sub owner x origin }
+           Dec(Mouse.Y, Owner^.Origin.Y);             { Sub owner y origin }
+         End;
+         R := Mouse; Mouse := Size;                   { Exchange values }
+       End Else Begin
+         R := Origin;                                 { Start at origin }
+         If (Owner<>Nil) Then Begin
+           Dec(R.X, Owner^.Origin.X);                 { Sub owner x origin }
+           Dec(R.Y, Owner^.Origin.Y);                 { Sub owner y origin }
+         End;
+         Mouse.X := Mouse.X+Q.X-Origin.X;
+         Mouse.Y := Mouse.Y+Q.Y-Origin.Y;
+       End;
+       {$IFDEF OS_DOS}                                { DOS/DPMI CODE }
+       HideMouseCursor;                               { Hide the mouse }
+       {$ENDIF}
+       SetWriteMode(XORPut);
+       GraphRectangle(0, 0, RawSize.X, RawSize.Y, Red);
+       SetWriteMode(NormalPut);
+       MoveGrow(R, Mouse);                            { Resize the view }
+       SetWriteMode(XORPut);
+       GraphRectangle(0, 0, RawSize.X, RawSize.Y, Red);
+       SetWriteMode(NormalPut);
+       {$IFDEF OS_DOS}                                { DOS/DPMI CODE }
+       ShowMouseCursor;                               { Show the mouse }
+       {$ENDIF}
+     Until NOT MouseEvent(Event, evMouseMove);        { Finished moving }
+     State := PState;                                 { Restore view state }
+     If (Owner<>Nil) Then
+       Owner^.ReDrawArea(Op1.X, Op1.Y, Op2.X, Op2.Y); { Redraw old area }
+     SetState(sfDragging, False);                     { Clr dragging flag }
+     DrawView;                                        { Now redraw the view }
+   End Else Begin
+     GetBounds(SaveBounds);                           { Get current bounds }
+     Repeat
+       P := Origin; S := Size;                        { Set values }
+       KeyEvent(Event);                               { Get key event }
+       Case Event.KeyCode AND $FF00 Of
+         kbLeft: Change(-1, 0);                       { Move left }
+         kbRight: Change(1, 0);                       { Move right }
+         kbUp: Change(0, -1);                         { Move up }
+         kbDown: Change(0, 1);                        { Move down }
+         kbCtrlLeft: Change(-8, 0);
+         kbCtrlRight: Change(8, 0);
+         kbHome: Update(Limits.A.X, P.Y);
+         kbEnd: Update(Limits.B.X - S.X, P.Y);
+         kbPgUp: Update(P.X, Limits.A.Y);
+         kbPgDn: Update(P.X, Limits.B.Y - S.Y);
+       End;
+       MoveGrow(P, S);                                { Now move the view }
+     Until (Event.KeyCode = kbEnter) OR
+     (Event.KeyCode = kbEsc);
+     If (Event.KeyCode=kbEsc) Then Locate(SaveBounds);{ Restore original }
+   End;
+   SetState(sfDragging, False);                       { Clr dragging flag }
+END;
+
+
+
+
+
+FUNCTION TView.FontWidth: Integer;
+BEGIN
+   FontWidth := SysFontWidth;
+END;
+
+FUNCTION TView.FontHeight: Integer;
+BEGIN
+   FontHeight := SysFontHeight;
+END;
+
+
+{$IFNDEF OS_DOS}
+{***************************************************************************}
+{                      TView OBJECT WIN/NT ONLY METHODS                     }
+{***************************************************************************}
+
+{--TView--------------------------------------------------------------------}
+{  CreateWindowNow -> Platforms WIN/NT/OS2 - Updated 17Mar98 LdB            }
+{---------------------------------------------------------------------------}
+PROCEDURE TView.CreateWindowNow (CmdShow: Integer);
+VAR Li: LongInt; S: String; Cp, Ct: Array[0..256] Of Char;
+{$IFDEF OS_WINDOWS} VAR WndClass: TWndClass; {$ENDIF}
+{$IFDEF OS_OS2} VAR P: Pointer; WndClass: ClassInfo; {$ENDIF}
+BEGIN
+   If (HWindow = 0) Then Begin                        { Window not created }
+     S := GetClassName;                               { Fetch classname }
+     FillChar(Cp, SizeOf(Cp), #0);                    { Clear buffer }
+     Move(S[1], Cp, Length(S));                       { Transfer classname }
+     S := GetClassText;                               { Fetch class text }
+     FillChar(Ct, SizeOf(Ct), #0);                    { Clear buffer }
+     Move(S[1], Ct, Length(S));                       { Transfer class text }
+     If (GOptions AND goNativeClass = 0) AND          { Not native class }
+     {$IFDEF OS_WINDOWS}                              { WIN/NT CODE }
+     {$IFNDEF PPC_SPEED}
+       {$IFDEF PPC_FPC}
+       NOT GetClassInfo(HInstance, Cp, @WndClass)
+       {$ELSE}
+       NOT GetClassInfo(HInstance, Cp, WndClass)
+       {$ENDIF}
+     {$ELSE}                                          { SPEEDSOFT SYBIL2+ }
+     NOT GetClassInfo(0, CString(Cp), WndClass)
+     {$ENDIF}
+     Then Begin                                       { Class not registered }
+       WndClass.Style := CS_HRedraw OR CS_VReDraw OR
+         CS_DBLClks;                                  { Class styles }
+       {$IFDEF PPC_SPEED}
+       WndClass.lpfnWndProc:= WndProc(GetMsgHandler); { Message handler }
+       {$ELSE}
+       Pointer(WndClass.lpfnWndProc) := GetMsgHandler;{ Message handler }
+       {$ENDIF}
+       WndClass.cbClsExtra := 0;                      { No extra data }
+       WndClass.cbWndExtra := 0;                      { No extra data }
+       {$IFDEF PPC_SPEED}                             { SPEEDSOFT SYBIL2+ }
+       WndClass.hInstance := 0;
+       WndClass.hIcon := Idi_Application;             { Set icon }
+       {$ELSE}
+       WndClass.hInstance := HInstance;               { Set instance }
+       WndClass.hIcon := LoadIcon(0, Idi_Application);{ Set icon }
+       {$ENDIF}
+       WndClass.hCursor := LoadCursor(0, Idc_Arrow);  { Set cursor }
+       WndClass.hbrBackground := GetStockObject(
+         Null_Brush);                                 { Class brush }
+       WndClass.lpszMenuName := Nil;                  { No menu }
+       {$IFDEF PPC_SPEED}                             { SPEEDSOFT SYBIL2+ }
+       WndClass.lpszClassName := @Cp;                 { Set class name }
+       {$ELSE}                                        { OTHER COMPILERS }
+       WndClass.lpszClassName := Cp;                  { Set class name }
+       {$ENDIF}
+       {$IFDEF BIT_32}                                { 32 BIT CODE }
+       If (RegisterClass(WndClass) = 0)
+       {$ENDIF}
+       {$IFDEF BIT_16}                                { 16 BIT CODE }
+       If (RegisterClass(WndClass) = False)
+       {$ENDIF}
+       Then Begin
+         MessageBox(GetFocus, 'Can not Register Class',
+           'UnKnown Error Cause?', mb_OK);            { Failed to register }
+         Halt;                                        { Halt on failure }
+       End;
+     End;
+     If (GOptions AND goNativeClass <> 0) Then
+       Li := 1 Else Li := 0;
+     If (Owner <> Nil) AND (Owner^.HWindow <> 0)      { Valid owner window }
+     Then HWindow := CreateWindowEx(ExStyle,
+       {$IFDEF PPC_SPEED}                             { SPEEDSOFT SYBIL2+ }
+       CString(Cp), Ct, GetClassAttr OR ws_Child,
+       RawOrigin.X-Owner^.RawOrigin.X-Owner^.FrameSize,
+       RawOrigin.Y-Owner^.RawOrigin.Y-Owner^.CaptSize+Li,
+       RawSize.X+1,
+       RawSize.Y+1, Owner^.HWindow, GetClassId, 0, Nil)
+       {$ELSE}
+       Cp, Ct, GetClassAttr OR ws_Child,
+       RawOrigin.X-Owner^.RawOrigin.X-Owner^.FrameSize,
+       RawOrigin.Y-Owner^.RawOrigin.Y-Owner^.CaptSize+Li,
+       RawSize.X+1,
+       RawSize.Y+1, Owner^.HWindow, GetClassId, hInstance, Nil)
+       {$ENDIF}
+     Else HWindow := CreateWindowEx(ExStyle,
+       {$IFDEF PPC_SPEED}                             { SPEEDSOFT SYBIL2+ }
+       CString(Cp), Ct, GetClassAttr,
+       RawOrigin.X, RawOrigin.Y, RawSize.X+1, RawSize.Y+1,
+       AppWindow, GetClassId, 0, Nil);        { Create the window }
+       {$ELSE}
+       Cp, Ct, GetClassAttr,
+       RawOrigin.X, RawOrigin.Y, RawSize.X+1, RawSize.Y+1,
+       AppWindow, GetClassId, hInstance, Nil);        { Create the window }
+       {$ENDIF}
+     If (HWindow <> 0) Then Begin                     { Window created ok }
+       SendMessage(HWindow, WM_SetFont, DefGFVFont, 1);
+       Li := LongInt(@Self);                          { Address of  self }
+       {$IFDEF BIT_16}                                { 16 BIT CODE }
+       SetProp(HWindow, ViewSeg, Li AND $FFFF0000
+         SHR 16);                                     { Set seg property }
+       SetProp(HWindow, ViewOfs, Li AND $FFFF);       { Set ofs propertry }
+       {$ENDIF}
+       {$IFDEF BIT_32}                                { 32 BIT CODE }
+       SetProp(HWindow, ViewPtr, Li );                { Set view property }
+       {$ENDIF}
+       If (CmdShow <> 0) Then
+         ShowWindow(HWindow, cmdShow);                { Execute show cmd }
+       If (State AND sfVisible <> 0) Then Begin
+         UpdateWindow(HWindow);                       { Update the window }
+         BringWindowToTop(HWindow);                   { Bring window to top }
+       End;
+       If (State AND sfDisabled <> 0) Then
+         EnableWindow(HWindow, False);                { Disable the window }
+     End;
+     {$ENDIF}
+     {$IFDEF OS_OS2}                                  { OS2 CODE }
+     (WinQueryClassInfo(Anchor, Cp, WndClass) = False)
+     Then Begin                                       { Class not registered }
+       P := GetMsgHandler;                            { Message handler }
+       If (WinRegisterClass(Anchor, Cp, P,
+         cs_SizeRedraw, SizeOf(Pointer))= False)      { Register the class }
+       Then Begin
+         WinMessageBox(0, 0, 'Can not Register Class',
+           'UnKnown Error Cause?', 0, mb_OK);         { Failed to register }
+         Halt;                                        { Halt on failure }
+       End;
+     End;
+     Li := GetClassAttr;                              { Class attributes }
+     If (Owner <> Nil) AND (Owner^.HWindow <> 0)      { Valid owner window }
+     Then Begin
+       HWindow := WinCreateStdWindow(Owner^.Client,
+       0, Li, Cp, Ct, lStyle, 0, 0, @Client);
+       If (HWindow <> 0) Then Begin                   { Window created ok }
+         Li := LongInt(@Self);                        { Address of  self }
+         WinSetPresParam(Client, PP_User,
+           SizeOf(Pointer), @Li);                     { Hold as property }
+         WinSetWindowPos(HWindow, 0, RawOrigin.X-Owner^.RawOrigin.X,
+           (Owner^.RawOrigin.Y + Owner^.RawSize.Y) -
+           (RawOrigin.Y + RawSize.Y),
+           RawSize.X+1, RawSize.Y+1,
+           swp_Move + swp_Size + swp_Activate + swp_Show);
+         If (GOptions AND goNativeClass <> 0) Then Begin
+           WinSetOwner(Client, Owner^.Client);
+         End;
+         If (State AND sfDisabled <> 0) Then
+           WinEnableWindow(HWindow, False);           { Disable the window }
+       End;
+     End Else Begin
+       HWindow := WinCreateStdWindow(HWND_Desktop,
+        0, Li, Cp, Ct, lStyle, 0, 0, @Client);
+       If (HWindow <> 0) Then Begin                   { Window created ok }
+         Li := LongInt(@Self);                        { Address of  self }
+         WinSetPresParam(Client, PP_User,
+           SizeOf(Pointer), @Li);                     { Hold as property }
+         WinSetWindowPos(HWindow, 0, RawOrigin.X,
+           WinQuerySysValue(hwnd_Desktop, sv_CyScreen)-RawSize.Y,
+           RawSize.X, RawSize.Y,
+           swp_Move + swp_Size + swp_Activate OR cmdShow);
+       End;
+     End;
+     {$ENDIF}
+   End;
+END;
+
+{$ENDIF}
+
+
+
+
+{ÞßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßÝ}
+{Þ                        TScroller OBJECT METHODS                         Ý}
+{ÞÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÝ}
+
+
+PROCEDURE TScroller.ScrollDraw;
+VAR D: TPoint;
+BEGIN
+   If (HScrollBar<>Nil) Then D.X := HScrollBar^.Value
+     Else D.X := 0;                                   { Horz scroll value }
+   If (VScrollBar<>Nil) Then D.Y := VScrollBar^.Value
+     Else D.Y := 0;                                   { Vert scroll value }
+   If (D.X<>Delta.X) OR (D.Y<>Delta.Y) Then Begin     { View has moved }
+     SetCursor(Cursor.X+Delta.X-D.X,
+       Cursor.Y+Delta.Y-D.Y);                         { Move the cursor }
+     Delta := D;                                      { Set new delta }
+     If (DrawLock<>0) Then DrawFlag := True           { Draw will need draw }
+       Else DrawView;                                 { Redraw the view }
+   End;
+END;
+
+PROCEDURE TScroller.SetLimit (X, Y: Integer);
+VAR PState: Word;
+BEGIN
+   Limit.X := X;                                      { Hold x limit }
+   Limit.Y := Y;                                      { Hold y limit }
+   Inc(DrawLock);                                     { Set draw lock }
+   If (HScrollBar<>Nil) Then Begin
+     PState := HScrollBar^.State;                     { Hold bar state }
+     HScrollBar^.State := PState AND NOT sfVisible;   { Temp not visible }
+     HScrollBar^.SetParams(HScrollBar^.Value, 0,
+       X-Size.X, Size.X-1, HScrollBar^.ArStep);       { Set horz scrollbar }
+     HScrollBar^.State := PState;                     { Restore bar state }
+   End;
+   If (VScrollBar<>Nil) Then Begin
+     PState := VScrollBar^.State;                     { Hold bar state }
+     VScrollBar^.State := PState AND NOT sfVisible;   { Temp not visible }
+     VScrollBar^.SetParams(VScrollBar^.Value, 0,
+       Y-Size.Y, Size.Y-1, VScrollBar^.ArStep);       { Set vert scrollbar }
+     VScrollBar^.State := PState;                     { Restore bar state }
+   End;
+   Dec(DrawLock);                                     { Release draw lock }
+   CheckDraw;                                         { Check need to draw }
+END;
+
+{***************************************************************************}
+{                      TScroller OBJECT PRIVATE METHODS                     }
+{***************************************************************************}
+PROCEDURE TScroller.CheckDraw;
+BEGIN
+   If (DrawLock = 0) AND DrawFlag Then Begin          { Clear & draw needed }
+     DrawFlag := False;                               { Clear draw flag }
+     DrawView;                                        { Draw now }
+   End;
+END;
+
+
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                          TGroup OBJECT METHODS                            }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+
+
+
+{--TGroup-------------------------------------------------------------------}
+{  Lock -> Platforms DOS/DPMI/WIN/OS2 - Checked 23Sep97 LdB                 }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.Lock;
+BEGIN
+   If (Buffer <> Nil) OR (LockFlag <> 0)
+     Then Inc(LockFlag);                              { Increment count }
+END;
+
+{--TGroup-------------------------------------------------------------------}
+{  UnLock -> Platforms DOS/DPMI/WIN/OS2 - Checked 23Sep97 LdB               }
+{---------------------------------------------------------------------------}
+PROCEDURE TGroup.Unlock;
+BEGIN
+   If (LockFlag <> 0) Then Begin
+     Dec(LockFlag);                                   { Decrement count }
+     {If (LockFlag = 0) Then DrawView;}                 { Lock release draw }
+   End;
+END;
+
+PROCEDURE TWindow.DrawBorder;
+VAR Fc, Bc: Byte; X, Y: Integer; S: String; ViewPort: ViewPortType;
+BEGIN
+   {$IFDEF OS_DOS}
+   Fc := GetColor(2) AND $0F;                        { Foreground colour }
+   Bc := 9;                                           { Background colour }
+   If (Options AND ofFramed<>0) Then Y := 1
+     Else Y := 0;                                     { Initial value }
+   If (GOptions AND goThickFramed<>0) Then Inc(Y, 3); { Adjust position }
+   ClearArea(0, Y, RawSize.X, Y+FontHeight, Bc);      { Clear background }
+   If (Title<>Nil) AND (GOptions AND goTitled<>0)
+   Then Begin                                         { View has a title }
+     GetViewSettings(ViewPort);
+     X := (RawSize.X DIV 2);                          { Half way point }
+     X := X - (Length(Title^)*FontWidth) DIV 2;       { Calc start point }
+     SetColor(Fc);
+     OutTextXY(RawOrigin.X+X-ViewPort.X1,
+       RawOrigin.Y+Y+1-ViewPort.Y1+2, Title^);          { Write the title }
+   End;
+   If (Number>0) AND (Number<10) Then Begin           { Valid number }
+     Str(Number, S);                                  { Make number string }
+     SetColor(GetColor(2) AND $0F);
+     OutTextXY(RawOrigin.X+RawSize.X-2*FontWidth-ViewPort.X1,
+       RawOrigin.Y+Y+1-ViewPort.Y1+2, S);               { Write number }
+   End;
+   If (Flags AND wfClose<>0) Then Begin               { Close icon request }
+     SetColor(Fc);
+     OutTextXY(RawOrigin.X+Y+FontWidth-ViewPort.X1,
+       RawOrigin.Y+Y+1-ViewPort.Y1+2, '[*]');           { Write close icon }
+   End;
+   If (Flags AND wfZoom<>0) Then Begin
+     SetColor(GetColor(2) AND $0F);
+     OutTextXY(RawOrigin.X+RawSize.X-4*FontWidth-Y-ViewPort.X1,
+       RawOrigin.Y+Y+1-ViewPort.Y1+2, '['+#24+']');     { Write zoom icon }
+   End;
+   BiColorRectangle(Y+1, Y+1, RawSize.X-Y-1, Y+FontHeight,
+     White, DarkGray, False);                         { Draw 3d effect }
+   BiColorRectangle(Y+1, Y+1, RawSize.X-Y-2, Y+FontHeight-1,
+     White, DarkGray, False);                         { Draw 3d effect }
+   Inherited DrawBorder;
+   {$ENDIF}
+END;
+
+
+{***************************************************************************}
+{                            INTERFACE ROUTINES                             }
+{***************************************************************************}
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                         WINDOW MESSAGE ROUTINES                           }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  Message -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 12Sep97 LdB           }
+{---------------------------------------------------------------------------}
+FUNCTION Message (Receiver: PView; What, Command: Word;
+  InfoPtr: Pointer): Pointer;
+VAR Event: TEvent;
+BEGIN
+   Message := Nil;                                    { Preset nil }
+   If (Receiver <> Nil) Then Begin                    { Valid receiver }
+     Event.What := What;                              { Set what }
+     Event.Command := Command;                        { Set command }
+     Event.Id := 0;                                   { Zero id field }
+     Event.Data := 0;                                 { Zero data field }
+     Event.InfoPtr := InfoPtr;                        { Set info ptr }
+     Receiver^.HandleEvent(Event);                    { Pass to handler }
+     If (Event.What = evNothing) Then
+       Message := Event.InfoPtr;                      { Return handler }
+   End;
+END;
+
+{---------------------------------------------------------------------------}
+{  NewMessage -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 19Sep97 LdB        }
+{---------------------------------------------------------------------------}
+FUNCTION NewMessage (P: PView; What, Command: Word; Id: Integer;
+  Data: Real; InfoPtr: Pointer): Pointer;
+VAR Event: TEvent;
+BEGIN
+   NewMessage := Nil;                                 { Preset failure }
+   If (P <> Nil) Then Begin
+     Event.What := What;                              { Set what }
+     Event.Command := Command;                        { Set event command }
+     Event.Id := Id;                                  { Set up Id }
+     Event.Data := Data;                              { Set up data }
+     Event.InfoPtr := InfoPtr;                        { Set up event ptr }
+     P^.HandleEvent(Event);                           { Send to view }
+     If (Event.What = evNothing) Then
+       NewMessage := Event.InfoPtr;                   { Return handler }
+   End;
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                            NEW VIEW ROUTINES                              }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  CreateIdScrollBar -> Platforms DOS/DPMI/WIN/NT/OS2 - Checked 22May97 LdB }
+{---------------------------------------------------------------------------}
+FUNCTION CreateIdScrollBar (X, Y, Size, Id: Integer; Horz: Boolean): PScrollBar;
+VAR R: TRect; P: PScrollBar;
+BEGIN
+   If Horz Then R.Assign(X, Y, X+Size, Y+1) Else      { Horizontal bar }
+     R.Assign(X, Y, X+1, Y+Size);                     { Vertical bar }
+   P := New(PScrollBar, Init(R));                     { Create scrollbar }
+   If (P <> Nil) Then Begin
+     P^.Id := Id;                                     { Set scrollbar id }
+     P^.Options := P^.Options OR ofPostProcess;       { Set post processing }
+   End;
+   CreateIdScrollBar := P;                            { Return scrollbar }
+END;
+
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+{                      OBJECT REGISTRATION PROCEDURES                       }
+{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
+
+{---------------------------------------------------------------------------}
+{  RegisterViews -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 28May97 LdB     }
+{---------------------------------------------------------------------------}
+PROCEDURE RegisterViews;
+BEGIN
+   RegisterType(RView);                               { Register views }
+   RegisterType(RFrame);                              { Register frame }
+   RegisterType(RScrollBar);                          { Register scrollbar }
+   RegisterType(RScroller);                           { Register scroller }
+   RegisterType(RListViewer);                         { Register listview }
+   RegisterType(RGroup);                              { Register group }
+   RegisterType(RWindow);                             { Register window }
+END;
+
+END.

+ 4 - 1
ide/fake/compiler/browcol.pas

@@ -501,7 +501,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.5  2000-01-27 23:42:33  peter
+  Revision 1.1  2000-07-13 09:48:33  michael
+  + Initial import
+
+  Revision 1.5  2000/01/27 23:42:33  peter
     * storebrowsercol returns boolean now
 
   Revision 1.4  1999/08/17 13:25:16  peter

+ 4 - 1
ide/fake/compiler/comphook.pas

@@ -244,7 +244,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.1  1999-01-28 19:56:12  peter
+  Revision 1.1  2000-07-13 09:48:33  michael
+  + Initial import
+
+  Revision 1.1  1999/01/28 19:56:12  peter
     * moved to include compiler/gdb independent of each other
 
   Revision 1.2  1999/01/14 21:43:08  peter

+ 4 - 1
ide/fake/compiler/compiler.pas

@@ -28,7 +28,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.2  1999-11-18 13:38:11  pierre
+  Revision 1.1  2000-07-13 09:48:33  michael
+  + Initial import
+
+  Revision 1.2  1999/11/18 13:38:11  pierre
    + IsExe var added
 
   Revision 1.1  1999/01/28 19:56:12  peter

+ 4 - 1
ide/fake/compiler/globtype.pas

@@ -179,7 +179,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.2  1999-09-17 09:16:12  peter
+  Revision 1.1  2000-07-13 09:48:33  michael
+  + Initial import
+
+  Revision 1.2  1999/09/17 09:16:12  peter
     * updated with compiler versions
 
 }

+ 4 - 1
ide/fake/compiler/systems.pas

@@ -1734,7 +1734,10 @@ begin
 end.
 {
   $Log$
-  Revision 1.2  1999-09-17 09:16:13  peter
+  Revision 1.1  2000-07-13 09:48:33  michael
+  + Initial import
+
+  Revision 1.2  1999/09/17 09:16:13  peter
     * updated with compiler versions
 
 }

+ 4 - 1
ide/fake/compiler/tokens.pas

@@ -511,7 +511,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.5  2000-02-12 23:55:26  carl
+  Revision 1.1  2000-07-13 09:48:33  michael
+  + Initial import
+
+  Revision 1.5  2000/02/12 23:55:26  carl
     * bugfix of reading file with TP conditional
 
   Revision 1.20  2000/02/09 13:23:08  peter

+ 4 - 1
ide/fake/compiler/version.pas

@@ -65,7 +65,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.1  1999-01-28 19:56:12  peter
+  Revision 1.1  2000-07-13 09:48:33  michael
+  + Initial import
+
+  Revision 1.1  1999/01/28 19:56:12  peter
     * moved to include compiler/gdb independent of each other
 
   Revision 1.1  1998/12/22 14:27:54  peter

+ 4 - 1
ide/fake/gdb/gdbcon.pas

@@ -149,7 +149,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.11  1999-02-19 16:54:41  peter
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.11  1999/02/19 16:54:41  peter
     * removed step tests
 
   Revision 1.10  1999/02/16 10:44:14  peter

+ 4 - 1
ide/fake/gdb/gdbint.pas

@@ -298,7 +298,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.9  2000-03-07 10:39:59  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.9  2000/03/07 10:39:59  pierre
    + inferior_pid moved to interface
 
   Revision 1.8  2000/02/13 00:01:18  carl

+ 4 - 1
ide/text/fp.pas

@@ -270,7 +270,10 @@ BEGIN
 END.
 {
   $Log$
-  Revision 1.47  2000-06-16 08:50:40  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.47  2000/06/16 08:50:40  pierre
    + new bunch of Gabor's changes
 
   Revision 1.46  2000/05/29 10:44:56  pierre

+ 4 - 1
ide/text/fpcalc.pas

@@ -463,7 +463,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.10  2000-05-02 08:42:26  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.10  2000/05/02 08:42:26  pierre
    * new set of Gabor changes: see fixes.txt
 
   Revision 1.9  2000/04/18 11:42:36  pierre

+ 4 - 1
ide/text/fpcatch.pas

@@ -112,7 +112,10 @@ end.
 
 {
   $Log$
-  Revision 1.6  2000-06-22 09:07:11  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.6  2000/06/22 09:07:11  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.5  2000/05/02 08:42:26  pierre

+ 4 - 1
ide/text/fpcompil.pas

@@ -911,7 +911,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.60  2000-06-22 09:07:11  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.60  2000/06/22 09:07:11  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.59  2000/06/16 08:50:40  pierre

+ 4 - 1
ide/text/fpconst.pas

@@ -407,7 +407,10 @@ implementation
 END.
 {
   $Log$
-  Revision 1.42  2000-06-26 07:29:22  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.42  2000/06/26 07:29:22  pierre
    * new bunch of Gabor's changes
 
   Revision 1.41  2000/06/22 09:07:11  pierre

+ 4 - 1
ide/text/fpdebug.pas

@@ -3346,7 +3346,10 @@ end.
 
 {
   $Log$
-  Revision 1.63  2000-06-22 09:07:11  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.63  2000/06/22 09:07:11  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.62  2000/06/11 07:01:32  peter

+ 4 - 1
ide/text/fpdesk.pas

@@ -795,7 +795,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.29  2000-06-22 09:07:12  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.29  2000/06/22 09:07:12  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.28  2000/05/02 08:42:27  pierre

+ 4 - 1
ide/text/fphelp.pas

@@ -518,7 +518,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.35  2000-06-26 07:29:23  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.35  2000/06/26 07:29:23  pierre
    * new bunch of Gabor's changes
 
   Revision 1.34  2000/06/22 09:07:12  pierre

+ 4 - 1
ide/text/fpide.pas

@@ -1060,7 +1060,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.65  2000-06-22 09:07:12  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.65  2000/06/22 09:07:12  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.64  2000/06/16 21:19:41  pierre

+ 4 - 1
ide/text/fpini.pas

@@ -528,7 +528,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.30  2000-06-22 09:07:12  pierre
+  Revision 1.1  2000-07-13 09:48:34  michael
+  + Initial import
+
+  Revision 1.30  2000/06/22 09:07:12  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.29  2000/06/16 08:50:41  pierre

+ 4 - 1
ide/text/fpintf.pas

@@ -212,7 +212,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.12  2000-06-22 09:07:12  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.12  2000/06/22 09:07:12  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.11  2000/05/29 10:44:56  pierre

+ 4 - 1
ide/text/fpmcomp.inc

@@ -128,7 +128,10 @@ end;
 
 {
   $Log$
-  Revision 1.9  2000-05-02 08:42:28  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.9  2000/05/02 08:42:28  pierre
    * new set of Gabor changes: see fixes.txt
 
   Revision 1.8  2000/03/07 21:45:33  pierre

+ 4 - 1
ide/text/fpmdebug.inc

@@ -141,7 +141,10 @@ end;
 
 {
   $Log$
-  Revision 1.13  2000-05-17 10:17:49  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.13  2000/05/17 10:17:49  pierre
    * Reinit the keyboard in ShowUserScreen
 
   Revision 1.12  2000/05/02 08:42:28  pierre

+ 4 - 1
ide/text/fpmedit.inc

@@ -22,7 +22,10 @@ end;
 
 {
   $Log$
-  Revision 1.1  1998-12-22 14:27:54  peter
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.1  1998/12/22 14:27:54  peter
     * moved
 
   Revision 1.2  1998/12/22 10:39:45  peter

+ 4 - 1
ide/text/fpmfile.inc

@@ -199,7 +199,10 @@ end;
 
 {
   $Log$
-  Revision 1.21  2000-06-16 08:50:41  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.21  2000/06/16 08:50:41  pierre
    + new bunch of Gabor's changes
 
   Revision 1.20  2000/05/02 08:42:28  pierre

+ 4 - 1
ide/text/fpmhelp.inc

@@ -252,7 +252,10 @@ end;
 
 {
   $Log$
-  Revision 1.11  2000-05-29 10:44:57  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.11  2000/05/29 10:44:57  pierre
    + New bunch of Gabor's changes: see fixes.txt
 
   Revision 1.10  2000/05/02 08:42:28  pierre

+ 4 - 1
ide/text/fpmopts.inc

@@ -1214,7 +1214,10 @@ end;
 
 {
   $Log$
-  Revision 1.35  2000-06-16 08:50:41  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.35  2000/06/16 08:50:41  pierre
    + new bunch of Gabor's changes
 
   Revision 1.34  2000/05/30 07:18:33  pierre

+ 4 - 1
ide/text/fpmrun.inc

@@ -270,7 +270,10 @@ end;
 
 {
   $Log$
-  Revision 1.32  2000-05-02 08:42:28  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.32  2000/05/02 08:42:28  pierre
    * new set of Gabor changes: see fixes.txt
 
   Revision 1.31  2000/04/18 11:42:37  pierre

+ 4 - 1
ide/text/fpmsrch.inc

@@ -137,7 +137,10 @@ end;
 
 {
   $Log$
-  Revision 1.13  2000-05-02 08:42:28  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.13  2000/05/02 08:42:28  pierre
    * new set of Gabor changes: see fixes.txt
 
   Revision 1.12  2000/03/07 21:57:01  pierre

+ 4 - 1
ide/text/fpmtools.inc

@@ -294,7 +294,10 @@ end;
 
 {
   $Log$
-  Revision 1.21  2000-06-16 08:50:41  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.21  2000/06/16 08:50:41  pierre
    + new bunch of Gabor's changes
 
   Revision 1.20  2000/05/02 08:42:28  pierre

+ 4 - 1
ide/text/fpmwnd.inc

@@ -227,7 +227,10 @@ end;
 
 {
   $Log$
-  Revision 1.18  2000-06-16 08:50:41  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.18  2000/06/16 08:50:41  pierre
    + new bunch of Gabor's changes
 
   Revision 1.17  2000/05/02 08:42:28  pierre

+ 4 - 1
ide/text/fpredir.pas

@@ -718,7 +718,10 @@ Begin
 End.
 {
   $Log$
-  Revision 1.25  2000-05-17 10:19:53  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.25  2000/05/17 10:19:53  pierre
    * Reset DosError to zero !
 
   Revision 1.24  1999/11/10 17:10:59  pierre

+ 4 - 1
ide/text/fpstre.inc

@@ -961,7 +961,10 @@ const
 
 {
   $Log$
-  Revision 1.4  2000-06-16 08:50:41  pierre
+  Revision 1.1  2000-07-13 09:48:35  michael
+  + Initial import
+
+  Revision 1.4  2000/06/16 08:50:41  pierre
    + new bunch of Gabor's changes
 
   Revision 1.3  2000/05/30 07:18:33  pierre

+ 4 - 1
ide/text/fpstrh.inc

@@ -961,7 +961,10 @@ const
 
 {
   $Log$
-  Revision 1.4  2000-06-16 08:50:42  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.4  2000/06/16 08:50:42  pierre
    + new bunch of Gabor's changes
 
   Revision 1.3  2000/05/30 07:18:33  pierre

+ 4 - 1
ide/text/fpstring.pas

@@ -37,7 +37,10 @@ unit fpstring;
 end.
 {
   $Log$
-  Revision 1.4  2000-05-02 08:42:28  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.4  2000/05/02 08:42:28  pierre
    * new set of Gabor changes: see fixes.txt
 
   Revision 1.3  2000/04/18 11:42:37  pierre

+ 4 - 1
ide/text/fpswitch.pas

@@ -1113,7 +1113,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.23  2000-06-22 09:07:12  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.23  2000/06/22 09:07:12  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.22  2000/05/02 08:42:28  pierre

+ 4 - 1
ide/text/fpsymbol.pas

@@ -1695,7 +1695,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.30  2000-07-05 10:19:07  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.30  2000/07/05 10:19:07  pierre
    + display 'variable' for open array size
 
   Revision 1.29  2000/06/22 09:07:12  pierre

+ 4 - 1
ide/text/fptemplt.pas

@@ -289,7 +289,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.10  2000-06-22 09:07:12  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.10  2000/06/22 09:07:12  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.9  2000/05/02 08:42:28  pierre

+ 4 - 1
ide/text/fptools.pas

@@ -1507,7 +1507,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.20  2000-06-22 09:07:12  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.20  2000/06/22 09:07:12  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.19  2000/05/02 08:42:29  pierre

+ 4 - 1
ide/text/fpusrscr.pas

@@ -715,7 +715,10 @@ end;
 end.
 {
   $Log$
-  Revision 1.13  2000-06-16 15:00:20  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.13  2000/06/16 15:00:20  pierre
    * accord to new WriteConsoleOuput declarations
 
   Revision 1.12  2000/04/25 08:42:33  pierre

+ 4 - 1
ide/text/fputils.pas

@@ -664,7 +664,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.16  2000-06-22 09:07:13  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.16  2000/06/22 09:07:13  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.15  2000/04/18 11:42:37  pierre

+ 4 - 1
ide/text/fpvars.pas

@@ -102,7 +102,10 @@ implementation
 END.
 {
   $Log$
-  Revision 1.33  2000-06-16 08:50:42  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.33  2000/06/16 08:50:42  pierre
    + new bunch of Gabor's changes
 
   Revision 1.32  2000/04/25 08:42:33  pierre

+ 4 - 1
ide/text/fpviews.pas

@@ -3471,7 +3471,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.73  2000-06-22 09:07:13  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.73  2000/06/22 09:07:13  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.72  2000/06/16 08:50:42  pierre

+ 4 - 1
ide/text/gplprog.pt

@@ -21,7 +21,10 @@ BEGIN
 END.
 {
   $Log$
-  Revision 1.4  2000-06-07 06:17:14  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.4  2000/06/07 06:17:14  pierre
    * New templates from Gabor
 
   Revision 1.1  1999/02/19 15:37:26  peter

+ 4 - 1
ide/text/gplunit.pt

@@ -30,7 +30,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.4  2000-06-07 06:17:14  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.4  2000/06/07 06:17:14  pierre
    * New templates from Gabor
 
   Revision 1.1  1999/02/19 15:37:26  peter

+ 4 - 1
ide/text/pmode.pas

@@ -717,7 +717,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.2  2000-06-22 09:07:13  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.2  2000/06/22 09:07:13  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.1  2000/04/20 08:47:39  pierre

+ 4 - 1
ide/text/vesa.pas

@@ -264,7 +264,10 @@ BEGIN
 END.
 {
   $Log$
-  Revision 1.8  2000-06-22 09:07:13  pierre
+  Revision 1.1  2000-07-13 09:48:36  michael
+  + Initial import
+
+  Revision 1.8  2000/06/22 09:07:13  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.7  2000/03/21 23:22:37  pierre

+ 4 - 1
ide/text/wconsts.pas

@@ -32,7 +32,10 @@ unit wconsts;
 end.
 {
   $Log$
-  Revision 1.1  2000-06-16 09:30:01  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.1  2000/06/16 09:30:01  pierre
    * new files from Gabor
 
 }

+ 4 - 1
ide/text/wconstse.inc

@@ -101,7 +101,10 @@
 
 {
   $Log$
-  Revision 1.1  2000-06-16 09:30:01  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.1  2000/06/16 09:30:01  pierre
    * new files from Gabor
 
 

+ 4 - 1
ide/text/wconstsh.inc

@@ -101,7 +101,10 @@
 
 {
   $Log$
-  Revision 1.1  2000-06-16 09:30:01  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.1  2000/06/16 09:30:01  pierre
    * new files from Gabor
 
 

+ 4 - 1
ide/text/weditor.pas

@@ -5858,7 +5858,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.95  2000-06-22 09:07:13  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.95  2000/06/22 09:07:13  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.94  2000/06/16 21:17:39  pierre

+ 4 - 1
ide/text/whelp.pas

@@ -1267,7 +1267,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.26  2000-07-03 08:54:54  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.26  2000/07/03 08:54:54  pierre
    * Some enhancements for WinHelp support by G	abor
 
   Revision 1.25  2000/06/26 07:29:23  pierre

+ 4 - 1
ide/text/whlpview.pas

@@ -1318,7 +1318,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.18  2000-06-22 09:07:14  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.18  2000/06/22 09:07:14  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.17  2000/06/16 08:50:45  pierre

+ 4 - 1
ide/text/whtml.pas

@@ -711,7 +711,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.7  2000-06-22 09:07:15  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.7  2000/06/22 09:07:15  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.6  2000/04/25 08:42:35  pierre

+ 4 - 1
ide/text/whtmlhlp.pas

@@ -743,7 +743,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.15  2000-06-22 09:07:15  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.15  2000/06/22 09:07:15  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.14  2000/06/16 08:50:45  pierre

+ 4 - 1
ide/text/whtmlscn.pas

@@ -453,7 +453,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.7  2000-06-22 09:07:15  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.7  2000/06/22 09:07:15  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.6  2000/05/29 11:09:14  pierre

+ 4 - 1
ide/text/winclip.pas

@@ -234,7 +234,10 @@ end.
 
 {
  $Log$
- Revision 1.7  2000-06-16 08:50:45  pierre
+ Revision 1.1  2000-07-13 09:48:37  michael
+ + Initial import
+
+ Revision 1.7  2000/06/16 08:50:45  pierre
   + new bunch of Gabor's changes
 
  Revision 1.6  2000/04/25 08:42:35  pierre

+ 4 - 1
ide/text/wini.pas

@@ -478,7 +478,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.10  2000-06-22 09:07:15  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.10  2000/06/22 09:07:15  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.9  2000/04/18 11:42:39  pierre

+ 4 - 1
ide/text/wnghelp.pas

@@ -508,7 +508,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.3  2000-07-03 08:54:54  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.3  2000/07/03 08:54:54  pierre
    * Some enhancements for WinHelp support by G	abor
 
   Revision 1.2  2000/06/26 07:29:23  pierre

+ 4 - 1
ide/text/wresourc.pas

@@ -797,7 +797,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.11  2000-07-03 08:54:54  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.11  2000/07/03 08:54:54  pierre
    * Some enhancements for WinHelp support by G	abor
 
   Revision 1.10  2000/05/16 21:48:13  pierre

+ 4 - 1
ide/text/wtphwrit.pas

@@ -274,7 +274,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.1  1999-03-16 12:38:18  peter
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.1  1999/03/16 12:38:18  peter
     * tools macro fixes
     + tph writer
     + first things for resource files

+ 4 - 1
ide/text/wutils.pas

@@ -1041,7 +1041,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.27  2000-07-03 08:54:54  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.27  2000/07/03 08:54:54  pierre
    * Some enhancements for WinHelp support by G	abor
 
   Revision 1.26  2000/06/26 07:29:23  pierre

+ 4 - 1
ide/text/wviews.pas

@@ -2189,7 +2189,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.15  2000-06-22 09:07:15  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.15  2000/06/22 09:07:15  pierre
    * Gabor changes: see fixes.txt
 
   Revision 1.14  2000/06/16 08:50:45  pierre

+ 4 - 1
ide/text/wwinhelp.pas

@@ -1665,7 +1665,10 @@ end;
 END.
 {
   $Log$
-  Revision 1.2  2000-07-03 08:54:54  pierre
+  Revision 1.1  2000-07-13 09:48:37  michael
+  + Initial import
+
+  Revision 1.2  2000/07/03 08:54:54  pierre
    * Some enhancements for WinHelp support by G	abor
 
   Revision 1.1  2000/06/26 07:29:23  pierre