home *** CD-ROM | disk | FTP | other *** search
/ BBS 1 / BBS#1.iso / for-dos / newtvsrc.arj / VIEWS.PAS < prev    next >
Pascal/Delphi Source File  |  1994-04-04  |  97KB  |  3,902 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Turbo Pascal Version 7.0                        }
  5. {       Turbo Vision Unit                               }
  6. {                                                       }
  7. {       Copyright (c) 1992 Borland International        }
  8. {       Copyright (c) 1993 ACD Group                    }
  9. {*******************************************************}
  10.  
  11. unit Views;
  12.  
  13. {$O+,F+,X+,I-,S-}
  14.  
  15. interface
  16.  
  17. uses Objects, Drivers, Memory;
  18.  
  19. const
  20.  
  21. { TView State masks }
  22.  
  23.   sfVisible     = $0001;
  24.   sfCursorVis   = $0002;
  25.   sfCursorIns   = $0004;
  26.   sfShadow      = $0008;
  27.   sfActive      = $0010;
  28.   sfSelected    = $0020;
  29.   sfFocused     = $0040;
  30.   sfDragging    = $0080;
  31.   sfDisabled    = $0100;
  32.   sfModal       = $0200;
  33.   sfDefault     = $0400;
  34.   sfExposed     = $0800;
  35.  
  36. { TView Option masks }
  37.  
  38.   ofSelectable  = $0001;
  39.   ofTopSelect   = $0002;
  40.   ofFirstClick  = $0004;
  41.   ofFramed      = $0008;
  42.   ofPreProcess  = $0010;
  43.   ofPostProcess = $0020;
  44.   ofBuffered    = $0040;
  45.   ofTileable    = $0080;
  46.   ofCenterX     = $0100;
  47.   ofCenterY     = $0200;
  48.   ofCentered    = $0300;
  49.   ofValidate    = $0400;
  50.   ofVersion     = $3000;
  51.   ofVersion10   = $0000;
  52.   ofVersion20   = $1000;
  53.  
  54. { TView GrowMode masks }
  55.  
  56.   gfGrowLoX = $01;
  57.   gfGrowLoY = $02;
  58.   gfGrowHiX = $04;
  59.   gfGrowHiY = $08;
  60.   gfGrowAll = $0F;
  61.   gfGrowRel = $10;
  62.  
  63. { TView DragMode masks }
  64.  
  65.   dmDragMove = $01;
  66.   dmDragGrow = $02;
  67.   dmLimitLoX = $10;
  68.   dmLimitLoY = $20;
  69.   dmLimitHiX = $40;
  70.   dmLimitHiY = $80;
  71.   dmLimitAll = $F0;
  72.  
  73. { TView Help context codes }
  74.  
  75.   hcNoContext = 0;
  76.   hcDragging  = 1;
  77.  
  78. { TScrollBar part codes }
  79.  
  80.   sbLeftArrow  = 0;
  81.   sbRightArrow = 1;
  82.   sbPageLeft   = 2;
  83.   sbPageRight  = 3;
  84.   sbUpArrow    = 4;
  85.   sbDownArrow  = 5;
  86.   sbPageUp     = 6;
  87.   sbPageDown   = 7;
  88.   sbIndicator  = 8;
  89.  
  90. { TScrollBar options for TWindow.StandardScrollBar }
  91.  
  92.   sbHorizontal     = $0000;
  93.   sbVertical       = $0001;
  94.   sbHandleKeyboard = $0002;
  95.  
  96. { TWindow Flags masks }
  97.  
  98.   wfMove       = $01;
  99.   wfGrow       = $02;
  100.   wfClose      = $04;
  101.   wfZoom       = $08;
  102.   wfBottomLine = $10;
  103.  
  104. { TWindow number constants }
  105.  
  106.   wnNoNumber = 0;
  107.  
  108. { TWindow palette entries }
  109.  
  110.   wpBlueWindow = 0;
  111.   wpCyanWindow = 1;
  112.   wpGrayWindow = 2;
  113.  
  114. { Standard command codes }
  115.  
  116.   cmValid   = 0;
  117.   cmQuit    = 1;
  118.   cmError   = 2;
  119.   cmMenu    = 3;
  120.   cmClose   = 4;
  121.   cmZoom    = 5;
  122.   cmResize  = 6;
  123.   cmNext    = 7;
  124.   cmPrev    = 8;
  125.   cmHelp    = 9;
  126.  
  127. { Application command codes }
  128.  
  129.   cmCut     = 20;
  130.   cmCopy    = 21;
  131.   cmPaste   = 22;
  132.   cmUndo    = 23;
  133.   cmClear   = 24;
  134.   cmTile    = 25;
  135.   cmCascade = 26;
  136.  
  137. { TDialog standard commands }
  138.  
  139.   cmOK      = 10;
  140.   cmCancel  = 11;
  141.   cmYes     = 12;
  142.   cmNo      = 13;
  143.   cmDefault = 14;
  144.  
  145. { Standard messages }
  146.  
  147.   cmReceivedFocus     = 50;
  148.   cmReleasedFocus     = 51;
  149.   cmCommandSetChanged = 52;
  150.  
  151. { TScrollBar messages }
  152.  
  153.   cmScrollBarChanged  = 53;
  154.   cmScrollBarClicked  = 54;
  155.  
  156. { TWindow select messages }
  157.  
  158.   cmSelectWindowNum   = 55;
  159.  
  160. { TWindow popup-menu message }
  161.  
  162.   cmWindowMenu        = 57;
  163.  
  164. { TListViewer messages }
  165.  
  166.   cmListItemSelected  = 56;
  167.  
  168. { Color palettes }
  169.  
  170.   CFrame       = #1#9#2#10#3;
  171.   CScrollBar   = #4#5#5;
  172.   CScroller    = #6#7;
  173.   CListViewer  = #36#36#37#38#39;
  174.  
  175.   CBlueWindow = #8#9#10#11#12#13#14#15#129#130#2#3#4#5#6#7;
  176.   CCyanWindow = #16#17#18#19#20#21#22#23#131#132#2#3#4#5#6#7;
  177.   CGrayWindow = #24#25#26#27#28#29#30#31#133#134#2#3#4#5#6#7;
  178.  
  179. { TDrawBuffer maximum view width }
  180.  
  181.   MaxViewWidth = 132;
  182.  
  183. type
  184.  
  185. { Command sets }
  186.  
  187.   PCommandSet = ^TCommandSet;
  188.   TCommandSet = set of Byte;
  189.  
  190. { Color palette type }
  191.  
  192.   PPalette = ^TPalette;
  193.   TPalette = String;
  194.  
  195. { TDrawBuffer, buffer used by draw methods }
  196.  
  197.   TDrawBuffer = array[0..MaxViewWidth - 1] of Word;
  198.  
  199. { TView object Pointer }
  200.  
  201.   PView = ^TView;
  202.  
  203. { TGroup object Pointer }
  204.  
  205.   PGroup = ^TGroup;
  206.  
  207. { TView object }
  208.  
  209.   TView = object(TObject)
  210.     Owner: PGroup;
  211.     Next: PView;
  212.     Origin: TPoint;
  213.     Size: TPoint;
  214.     Cursor: TPoint;
  215.     GrowMode: Byte;
  216.     DragMode: Byte;
  217.     HelpCtx: Word;
  218.     State: Word;
  219.     Options: Word;
  220.     EventMask: Word;
  221.     constructor Init(var Bounds: TRect);
  222.     constructor Load(var S: TStream);
  223.     destructor Done; virtual;
  224.     procedure Awaken; virtual;
  225.     procedure BlockCursor;
  226.     procedure CalcBounds(var Bounds: TRect; Delta: TPoint); virtual;
  227.     procedure ChangeBounds(var Bounds: TRect); virtual;
  228.     procedure ClearEvent(var Event: TEvent);
  229.     function CommandEnabled(Command: Word): Boolean;
  230.     function DataSize: Word; virtual;
  231.     procedure DisableCommands(Commands: TCommandSet);
  232.     procedure DragView(Event: TEvent; Mode: Byte;
  233.       var Limits: TRect; MinSize, MaxSize: TPoint);
  234.     procedure Draw; virtual;
  235.     procedure DrawView;
  236.     procedure EnableCommands(Commands: TCommandSet);
  237.     procedure EndModal(Command: Word); virtual;
  238.     function EventAvail: Boolean;
  239.     function Execute: Word; virtual;
  240.     function Exposed: Boolean;
  241.     function Focus: Boolean;
  242.     procedure GetBounds(var Bounds: TRect);
  243.     procedure GetClipRect(var Clip: TRect);
  244.     function GetColor(Color: Word): Word;
  245.     procedure GetCommands(var Commands: TCommandSet);
  246.     procedure GetData(var Rec); virtual;
  247.     procedure GetEvent(var Event: TEvent); virtual;
  248.     procedure GetExtent(var Extent: TRect);
  249.     function GetHelpCtx: Word; virtual;
  250.     function GetPalette: PPalette; virtual;
  251.     procedure GetPeerViewPtr(var S: TStream; var P);
  252.     function GetState(AState: Word): Boolean;
  253.     procedure GrowTo(X, Y: Integer);
  254.     procedure HandleEvent(var Event: TEvent); virtual;
  255.     procedure Hide;
  256.     procedure HideCursor;
  257.     procedure KeyEvent(var Event: TEvent);
  258.     procedure Locate(var Bounds: TRect);
  259.     procedure MakeFirst;
  260.     procedure MakeGlobal(Source: TPoint; var Dest: TPoint);
  261.     procedure MakeLocal(Source: TPoint; var Dest: TPoint);
  262.     function MouseEvent(var Event: TEvent; Mask: Word): Boolean;
  263.     function MouseInView(Mouse: TPoint): Boolean;
  264.     procedure MoveTo(X, Y: Integer);
  265.     function NextView: PView;
  266.     procedure NormalCursor;
  267.     function Prev: PView;
  268.     function PrevView: PView;
  269.     procedure PutEvent(var Event: TEvent); virtual;
  270.     procedure PutInFrontOf(Target: PView);
  271.     procedure PutPeerViewPtr(var S: TStream; P: PView);
  272.     procedure Select;
  273.     procedure SetBounds(var Bounds: TRect);
  274.     procedure SetCommands(Commands: TCommandSet);
  275.     procedure SetCmdState(Commands: TCommandSet; Enable: Boolean);
  276.     procedure SetCursor(X, Y: Integer);
  277.     procedure SetData(var Rec); virtual;
  278.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  279.     procedure Show;
  280.     procedure ShowCursor;
  281.     procedure SizeLimits(var Min, Max: TPoint); virtual;
  282.     procedure Store(var S: TStream);
  283.     function TopView: PView;
  284.     function Valid(Command: Word): Boolean; virtual;
  285.     procedure WriteBuf(X, Y, W, H: Integer; var Buf);
  286.     procedure WriteChar(X, Y: Integer; C: Char; Color: Byte;
  287.       Count: Integer);
  288.     procedure WriteLine(X, Y, W, H: Integer; var Buf);
  289.     procedure WriteStr(X, Y: Integer; Str: String; Color: Byte);
  290.   private
  291.     procedure DrawCursor;
  292.     procedure DrawHide(LastView: PView);
  293.     procedure DrawShow(LastView: PView);
  294.     procedure DrawUnderRect(var R: TRect; LastView: PView);
  295.     procedure DrawUnderView(DoShadow: Boolean; LastView: PView);
  296.     procedure ResetCursor; virtual;
  297.   end;
  298.  
  299. { TFrame types }
  300.  
  301.   TTitleStr = string[80];
  302.  
  303. { TFrame object }
  304.  
  305.   { Palette layout }
  306.   { 1 = Passive frame }
  307.   { 2 = Passive title }
  308.   { 3 = Active frame }
  309.   { 4 = Active title }
  310.   { 5 = Icons }
  311.  
  312.   PFrame = ^TFrame;
  313.   TFrame = object(TView)
  314.     constructor Init(var Bounds: TRect);
  315.     procedure Draw; virtual;
  316.     function GetPalette: PPalette; virtual;
  317.     procedure HandleEvent(var Event: TEvent); virtual;
  318.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  319.   private
  320.     FrameMode: Word;
  321.     procedure FrameLine(var FrameBuf; Y, N: Integer; Color: Byte); virtual;
  322.   end;
  323.  
  324. { ScrollBar characters }
  325.  
  326.   TScrollChars = array[0..9] of Char;
  327.  
  328. { TScrollBar object }
  329.  
  330.   { Palette layout }
  331.   { 1 = Page areas }
  332.   { 2 = Arrows }
  333.   { 3 = Indicator }
  334.  
  335.   PScrollBar = ^TScrollBar;
  336.   TScrollBar = object(TView)
  337.     Value: Integer;
  338.     Min: Integer;
  339.     Max: Integer;
  340.     PgStep: Integer;
  341.     ArStep: Integer;
  342.     constructor Init(var Bounds: TRect);
  343.     constructor Load(var S: TStream);
  344.     procedure Draw; virtual;
  345.     function GetPalette: PPalette; virtual;
  346.     procedure HandleEvent(var Event: TEvent); virtual;
  347.     procedure ScrollDraw; virtual;
  348.     function ScrollStep(Part: Integer): Integer; virtual;
  349.     procedure SetParams(AValue, AMin, AMax, APgStep, AArStep: Integer);
  350.     procedure SetRange(AMin, AMax: Integer);
  351.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  352.     procedure SetStep(APgStep, AArStep: Integer);
  353.     procedure SetValue(AValue: Integer);
  354.     procedure Store(var S: TStream);
  355.   private
  356.     Chars: TScrollChars;
  357.     PrevSize: TPoint;
  358.     procedure DrawPos(Pos: Integer);
  359.     function GetPos: Integer;
  360.     function GetSize: Integer;
  361.   end;
  362.  
  363. { TScroller object }
  364.  
  365.   { Palette layout }
  366.   { 1 = Normal text }
  367.   { 2 = Selected text }
  368.  
  369.   PScroller = ^TScroller;
  370.   TScroller = object(TView)
  371.     HScrollBar: PScrollBar;
  372.     VScrollBar: PScrollBar;
  373.     Delta: TPoint;
  374.     Limit: TPoint;
  375.     constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  376.     constructor Load(var S: TStream);
  377.     procedure ChangeBounds(var Bounds: TRect); virtual;
  378.     function GetPalette: PPalette; virtual;
  379.     procedure HandleEvent(var Event: TEvent); virtual;
  380.     procedure ScrollDraw; virtual;
  381.     procedure ScrollTo(X, Y: Integer);
  382.     procedure SetLimit(X, Y: Integer);
  383.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  384.     procedure Store(var S: TStream);
  385.   private
  386.     DrawLock: Byte;
  387.     DrawFlag: Boolean;
  388.     procedure CheckDraw;
  389.   end;
  390.  
  391. { TListViewer }
  392.  
  393.   { Palette layout }
  394.   { 1 = Active }
  395.   { 2 = Inactive }
  396.   { 3 = Focused }
  397.   { 4 = Selected }
  398.   { 5 = Divider }
  399.  
  400.   PListViewer = ^TListViewer;
  401.  
  402.   TListViewer = object(TView)
  403.     HScrollBar: PScrollBar;
  404.     VScrollBar: PScrollBar;
  405.     NumCols: Integer;
  406.     TopItem: Integer;
  407.     Focused: Integer;
  408.     Range: Integer;
  409.     constructor Init(var Bounds: TRect; ANumCols: Word;
  410.       AHScrollBar, AVScrollBar: PScrollBar);
  411.     constructor Load(var S: TStream);
  412.     procedure ChangeBounds(var Bounds: TRect); virtual;
  413.     procedure Draw; virtual;
  414.     procedure FocusItem(Item: Integer); virtual;
  415.     function GetPalette: PPalette; virtual;
  416.     function GetText(Item: Integer; MaxLen: Integer): String; virtual;
  417.     function IsSelected(Item: Integer): Boolean; virtual;
  418.     procedure HandleEvent(var Event: TEvent); virtual;
  419.     procedure SelectItem(Item: Integer); virtual;
  420.     procedure SetRange(ARange: Integer);
  421.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  422.     procedure Store(var S: TStream);
  423.   private
  424.     procedure FocusItemNum(Item: Integer); virtual;
  425.   end;
  426.  
  427. { Video buffer }
  428.  
  429.   PVideoBuf = ^TVideoBuf;
  430.   TVideoBuf = array[0..3999] of Word;
  431.  
  432. { Selection modes }
  433.  
  434.   SelectMode = (NormalSelect, EnterSelect, LeaveSelect);
  435.  
  436. { TGroup object }
  437.  
  438.   TGroup = object(TView)
  439.     Last: PView;
  440.     Current: PView;
  441.     Phase: (phFocused, phPreProcess, phPostProcess);
  442.     Buffer: PVideoBuf;
  443.     EndState: Word;
  444.     constructor Init(var Bounds: TRect);
  445.     constructor Load(var S: TStream);
  446.     destructor Done; virtual;
  447.     procedure Awaken; virtual;
  448.     procedure ChangeBounds(var Bounds: TRect); virtual;
  449.     function DataSize: Word; virtual;
  450.     procedure Delete(P: PView);
  451.     procedure Draw; virtual;
  452.     procedure EndModal(Command: Word); virtual;
  453.     procedure EventError(var Event: TEvent); virtual;
  454.     function ExecView(P: PView): Word;
  455.     function Execute: Word; virtual;
  456.     function First: PView;
  457.     function FirstThat(P: Pointer): PView;
  458.     function FocusNext(Forwards: Boolean): Boolean;
  459.     procedure ForEach(P: Pointer);
  460.     procedure GetData(var Rec); virtual;
  461.     function GetHelpCtx: Word; virtual;
  462.     procedure GetSubViewPtr(var S: TStream; var P);
  463.     procedure HandleEvent(var Event: TEvent); virtual;
  464.     procedure Insert(P: PView);
  465.     procedure InsertBefore(P, Target: PView);
  466.     procedure Lock;
  467.     procedure PutSubViewPtr(var S: TStream; P: PView);
  468.     procedure Redraw;
  469.     procedure SelectNext(Forwards: Boolean);
  470.     procedure SetData(var Rec); virtual;
  471.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  472.     procedure Store(var S: TStream);
  473.     procedure Unlock;
  474.     function Valid(Command: Word): Boolean; virtual;
  475.   private
  476.     Clip: TRect;
  477.     LockFlag: Byte;
  478.     function At(Index: Integer): PView;
  479.     procedure DrawSubViews(P, Bottom: PView);
  480.     function FirstMatch(AState: Word; AOptions: Word): PView;
  481.     function FindNext(Forwards: Boolean): PView;
  482.     procedure FreeBuffer;
  483.     procedure GetBuffer;
  484.     function IndexOf(P: PView): Integer;
  485.     procedure InsertView(P, Target: PView);
  486.     procedure RemoveView(P: PView);
  487.     procedure ResetCurrent;
  488.     procedure ResetCursor; virtual;
  489.     procedure SetCurrent(P: PView; Mode: SelectMode);
  490.   end;
  491.  
  492. { TWindow object }
  493.  
  494.   { Palette layout }
  495.   { 1 = Frame passive }
  496.   { 2 = Frame active }
  497.   { 3 = Frame icon }
  498.   { 4 = ScrollBar page area }
  499.   { 5 = ScrollBar controls }
  500.   { 6 = Scroller normal text }
  501.   { 7 = Scroller selected text }
  502.   { 8 = Reserved }
  503.  
  504.   PWindow = ^TWindow;
  505.   TWindow = object(TGroup)
  506.     Flags: Byte;
  507.     ZoomRect: TRect;
  508.     Number: Integer;
  509.     Palette: Integer;
  510.     Frame: PFrame;
  511.     Title: PString;
  512.     constructor Init(var Bounds: TRect; ATitle: TTitleStr; ANumber: Integer);
  513.     constructor Load(var S: TStream);
  514.     destructor Done; virtual;
  515.     procedure Close; virtual;
  516.     function GetPalette: PPalette; virtual;
  517.     function GetTitle(MaxSize: Integer): TTitleStr; virtual;
  518.     procedure HandleEvent(var Event: TEvent); virtual;
  519.     procedure InitFrame; virtual;
  520.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  521.     procedure SizeLimits(var Min, Max: TPoint); virtual;
  522.     function StandardScrollBar(AOptions: Word): PScrollBar;
  523.     procedure Store(var S: TStream);
  524.     procedure Zoom; virtual;
  525.   end;
  526.  
  527. { Message dispatch function }
  528.  
  529. function Message(Receiver: PView; What, Command: Word;
  530.   InfoPtr: Pointer): Pointer;
  531.  
  532. { Views registration procedure }
  533.  
  534. procedure RegisterViews;
  535.  
  536. const
  537.  
  538. { Event masks }
  539.  
  540.   PositionalEvents: Word = evMouse;
  541.   FocusedEvents: Word = evKeyboard + evCommand;
  542.  
  543. { Minimum window size }
  544.  
  545.   MinWinSize: TPoint = (X: 16; Y: 6);
  546.  
  547. { Shadow definitions }
  548.  
  549.   ShadowSize: TPoint = (X: 2; Y: 1);
  550.   ShadowAttr: Byte = $08;
  551.  
  552. { Markers control }
  553.  
  554.   ShowMarkers: Boolean = False;
  555.  
  556. { MapColor error return value }
  557.  
  558.   ErrorAttr: Byte = $CF;
  559.  
  560. { Stream Registration Records }
  561.  
  562. const
  563.   RView: TStreamRec = (
  564.      ObjType: 1;
  565.      VmtLink: Ofs(TypeOf(TView)^);
  566.      Load:    @TView.Load;
  567.      Store:   @TView.Store
  568.   );
  569.  
  570. const
  571.   RFrame: TStreamRec = (
  572.      ObjType: 2;
  573.      VmtLink: Ofs(TypeOf(TFrame)^);
  574.      Load:    @TFrame.Load;
  575.      Store:   @TFrame.Store
  576.   );
  577.  
  578. const
  579.   RScrollBar: TStreamRec = (
  580.      ObjType: 3;
  581.      VmtLink: Ofs(TypeOf(TScrollBar)^);
  582.      Load:    @TScrollBar.Load;
  583.      Store:   @TScrollBar.Store
  584.   );
  585.  
  586. const
  587.   RScroller: TStreamRec = (
  588.      ObjType: 4;
  589.      VmtLink: Ofs(TypeOf(TScroller)^);
  590.      Load:    @TScroller.Load;
  591.      Store:   @TScroller.Store
  592.   );
  593.  
  594. const
  595.   RListViewer: TStreamRec = (
  596.      ObjType: 5;
  597.      VmtLink: Ofs(TypeOf(TListViewer)^);
  598.      Load:    @TListViewer.Load;
  599.      Store:   @TLIstViewer.Store
  600.   );
  601.  
  602. const
  603.   RGroup: TStreamRec = (
  604.      ObjType: 6;
  605.      VmtLink: Ofs(TypeOf(TGroup)^);
  606.      Load:    @TGroup.Load;
  607.      Store:   @TGroup.Store
  608.   );
  609.  
  610. const
  611.   RWindow: TStreamRec = (
  612.      ObjType: 7;
  613.      VmtLink: Ofs(TypeOf(TWindow)^);
  614.      Load:    @TWindow.Load;
  615.      Store:   @TWindow.Store
  616.   );
  617.  
  618. { Characters used for drawing selected and default items in  }
  619. { monochrome color sets                                      }
  620.  
  621.   SpecialChars: array[0..5] of Char = (#16, #17, #26, #27, ' ', ' ');
  622.  
  623. { True if the command set has changed since being set to false }
  624.  
  625.   CommandSetChanged: Boolean = False;
  626.  
  627. procedure InvertColor(var Color: Byte);
  628.  
  629. implementation
  630.  
  631. uses
  632.   Menus;
  633.  
  634. type
  635.   PFixupList = ^TFixupList;
  636.   TFixupList = array[1..4096] of Pointer;
  637.  
  638. const
  639.   OwnerGroup: PGroup = nil;
  640.   FixupList: PFixupList = nil;
  641.   TheTopView: PView = nil;
  642.  
  643. const
  644.  
  645. { Bit flags to determine how to draw the frame icons }
  646.  
  647.   fmCloseClicked = $0001;
  648.   fmZoomClicked  = $0002;
  649.  
  650. { Current command set. All but window commands are active by default }
  651.  
  652.   CurCommandSet: TCommandSet =
  653.     [0..255] - [cmZoom, cmClose, cmResize, cmNext, cmPrev];
  654.  
  655. { Convert color into attribute                          }
  656. { In    AL = Color                                      }
  657. { Out   AL = Attribute                                  }
  658.  
  659. procedure MapColor; near; assembler;
  660. const
  661.   Self = 6;
  662.   TView_GetPalette = vmtHeaderSize + $2C;
  663. asm
  664.         OR      AL,AL
  665.         JE      @@3
  666.         LES     DI,[BP].Self
  667. @@1:    PUSH    ES
  668.         PUSH    DI
  669.         PUSH    AX
  670.         PUSH    ES
  671.         PUSH    DI
  672.         MOV     DI,ES:[DI]
  673.         CALL    DWORD PTR [DI].TView_GetPalette
  674.         MOV     BX,AX
  675.         MOV     ES,DX
  676.         OR      AX,DX
  677.         POP     AX
  678.         POP     DI
  679.         POP     DX
  680.         JE      @@2
  681.         CMP     AL,ES:[BX]
  682.         JA      @@3
  683.         SEGES   XLAT
  684.         OR      AL,AL
  685.         JE      @@3
  686. @@2:    MOV     ES,DX
  687.         LES     DI,ES:[DI].TView.Owner
  688.         MOV     SI,ES
  689.         OR      SI,DI
  690.         JNE     @@1
  691.         JMP     @@4
  692. @@3:    MOV     AL,ErrorAttr
  693. @@4:
  694. end;
  695.  
  696. { Convert color pair into attribute pair                }
  697. { In    AX = Color pair                                 }
  698. { Out   AX = Attribute pair                             }
  699.  
  700. procedure MapCPair; near; assembler;
  701. asm
  702.         OR      AH,AH
  703.         JE      @@1
  704.         XCHG    AL,AH
  705.         CALL    MapColor
  706.         XCHG    AL,AH
  707. @@1:    CALL    MapColor
  708. end;
  709.  
  710. { Write to view                                         }
  711. { In    AX    = Y coordinate                            }
  712. {       BX    = X coordinate                            }
  713. {       CX    = Count                                   }
  714. {       ES:DI = Buffer Pointer                          }
  715.  
  716. procedure WriteView; near; assembler;
  717. const
  718.   Self   =   6;
  719.   Target =  -4;
  720.   Buffer =  -8;
  721.   BufOfs = -10;
  722.   MW1: TPoint = (X:0;Y:0);
  723. asm
  724.         PUSH    AX
  725.         MOV     AX,MouseWhere.X
  726.         INC     AX
  727.         MOV     MW1.X,AX
  728.         MOV     AX,MouseWhere.Y
  729.         INC     AX
  730.         MOV     MW1.Y,AX
  731.         POP     AX
  732.         MOV     [BP].BufOfs,BX
  733.         MOV     [BP].Buffer[0],DI
  734.         MOV     [BP].Buffer[2],ES
  735.         ADD     CX,BX
  736.         XOR     DX,DX
  737.         LES     DI,[BP].Self
  738.         OR      AX,AX
  739.         JL      @@3
  740.         CMP     AX,ES:[DI].TView.Size.Y
  741.         JGE     @@3
  742.         OR      BX,BX
  743.         JGE     @@1
  744.         XOR     BX,BX
  745. @@1:    CMP     CX,ES:[DI].TView.Size.X
  746.         JLE     @@2
  747.         MOV     CX,ES:[DI].TView.Size.X
  748. @@2:    CMP     BX,CX
  749.         JL      @@10
  750. @@3:    RET
  751. @@10:   TEST    ES:[DI].TView.State,sfVisible
  752.         JE      @@3
  753.         CMP     ES:[DI].TView.Owner.Word[2],0
  754.         JE      @@3
  755.         MOV     [BP].Target[0],DI
  756.         MOV     [BP].Target[2],ES
  757.         ADD     AX,ES:[DI].TView.Origin.Y
  758.         MOV     SI,ES:[DI].TView.Origin.X
  759.         ADD     BX,SI
  760.         ADD     CX,SI
  761.         ADD     [BP].BufOfs,SI
  762.         LES     DI,ES:[DI].TView.Owner
  763.         CMP     AX,ES:[DI].TGroup.Clip.A.Y
  764.         JL      @@3
  765.         CMP     AX,ES:[DI].TGroup.Clip.B.Y
  766.         JGE     @@3
  767.         CMP     BX,ES:[DI].TGroup.Clip.A.X
  768.         JGE     @@11
  769.         MOV     BX,ES:[DI].TGroup.Clip.A.X
  770. @@11:   CMP     CX,ES:[DI].TGroup.Clip.B.X
  771.         JLE     @@12
  772.         MOV     CX,ES:[DI].TGroup.Clip.B.X
  773. @@12:   CMP     BX,CX
  774.         JGE     @@3
  775.         LES     DI,ES:[DI].TGroup.Last
  776. @@20:   LES     DI,ES:[DI].TView.Next
  777.         CMP     DI,[BP].Target[0]
  778.         JNE     @@21
  779.         MOV     SI,ES
  780.         CMP     SI,[BP].Target[2]
  781.         JNE     @@21
  782.         JMP     @@40
  783. @@21:   TEST    ES:[DI].TView.State,sfVisible
  784.         JE      @@20
  785.         MOV     SI,ES:[DI].TView.Origin.Y
  786.         CMP     AX,SI
  787.         JL      @@20
  788.         ADD     SI,ES:[DI].TView.Size.Y
  789.         CMP     AX,SI
  790.         JL      @@23
  791.         TEST    ES:[DI].TView.State,sfShadow
  792.         JE      @@20
  793.         ADD     SI,ShadowSize.Y
  794.         CMP     AX,SI
  795.         JGE     @@20
  796.         MOV     SI,ES:[DI].TView.Origin.X
  797.         ADD     SI,ShadowSize.X
  798.         CMP     BX,SI
  799.         JGE     @@22
  800.         CMP     CX,SI
  801.         JLE     @@20
  802.         CALL    @@30
  803. @@22:   ADD     SI,ES:[DI].TView.Size.X
  804.         JMP     @@26
  805. @@23:   MOV     SI,ES:[DI].TView.Origin.X
  806.         CMP     BX,SI
  807.         JGE     @@24
  808.         CMP     CX,SI
  809.         JLE     @@20
  810.         CALL    @@30
  811. @@24:   ADD     SI,ES:[DI].TView.Size.X
  812.         CMP     BX,SI
  813.         JGE     @@25
  814.         CMP     CX,SI
  815.         JLE     @@31
  816.         MOV     BX,SI
  817. @@25:   TEST    ES:[DI].TView.State,sfShadow
  818.         JE      @@20
  819.         PUSH    SI
  820.         MOV     SI,ES:[DI].TView.Origin.Y
  821.         ADD     SI,ShadowSize.Y
  822.         CMP     AX,SI
  823.         POP     SI
  824.         JL      @@27
  825.         ADD     SI,ShadowSize.X
  826. @@26:   CMP     BX,SI
  827.         JGE     @@27
  828.         INC     DX
  829.         CMP     CX,SI
  830.         JLE     @@27
  831.         CALL    @@30
  832.         DEC     DX
  833. @@27:   JMP     @@20
  834. @@30:   PUSH    [BP].Target.Word[2]
  835.         PUSH    [BP].Target.Word[0]
  836.         PUSH    [BP].BufOfs.Word[0]
  837.         PUSH    ES
  838.         PUSH    DI
  839.         PUSH    SI
  840.         PUSH    DX
  841.         PUSH    CX
  842.         PUSH    AX
  843.         MOV     CX,SI
  844.         CALL    @@20
  845.         POP     AX
  846.         POP     CX
  847.         POP     DX
  848.         POP     SI
  849.         POP     DI
  850.         POP     ES
  851.         POP     [BP].BufOfs.Word[0]
  852.         POP     [BP].Target.Word[0]
  853.         POP     [BP].Target.Word[2]
  854.         MOV     BX,SI
  855. @@31:   RET
  856. @@40:   LES     DI,ES:[DI].TView.Owner
  857.         MOV     SI,ES:[DI].TGroup.Buffer.Word[2]
  858.         OR      SI,SI
  859.         JE      @@44
  860.         CMP     SI,ScreenBuffer.Word[2]
  861.         JE      @@41
  862.         CALL    @@50
  863.         JMP     @@44
  864. @@41:   CLI
  865.         CMP     AX,MouseWhere.Y
  866.         JE      @@101
  867.         CMP     AX,MW1.Y
  868.         JNE     @@42
  869. @@101:  CMP     BX,MW1.X
  870.         JA      @@42
  871.         CMP     CX,MouseWhere.X
  872.         JA      @@43
  873. @@42:   MOV     MouseIntFlag,0
  874.         STI
  875.         CALL    @@50
  876.         CMP     MouseIntFlag,0
  877.         JE      @@44
  878. @@43:   STI
  879.         CALL    HideMouse
  880.         CALL    @@50
  881.         CALL    ShowMouse
  882. @@44:   CMP     ES:[DI].TGroup.LockFlag,0
  883.         JNE     @@31
  884.         JMP     @@10
  885. @@50:   PUSH    ES
  886.         PUSH    DS
  887.         PUSH    DI
  888.         PUSH    CX
  889.         PUSH    AX
  890.         MUL     ES:[DI].TView.Size.X.Byte[0]
  891.         ADD     AX,BX
  892.         SHL     AX,1
  893.         ADD     AX,ES:[DI].TGroup.Buffer.Word[0]
  894.         MOV     DI,AX
  895.         MOV     ES,SI
  896.         XOR     AL,AL
  897.         CMP     SI,ScreenBuffer.Word[2]
  898.         JNE     @@51
  899.         MOV     AL,CheckSnow
  900. @@51:   MOV     AH,ShadowAttr
  901.         SUB     CX,BX
  902.         MOV     SI,BX
  903.         SUB     SI,[BP].BufOfs
  904.         SHL     SI,1
  905.         ADD     SI,[BP].Buffer.Word[0]
  906.         MOV     DS,[BP].Buffer.Word[2]
  907.         CLD
  908.         OR      AL,AL
  909.         JNE     @@60
  910.         OR      DX,DX
  911.         JNE     @@52
  912.         REP     MOVSW
  913.         JMP     @@70
  914. @@52:   LODSB
  915.         INC     SI
  916.         STOSW
  917.         LOOP    @@52
  918.         JMP     @@70
  919. @@60:   PUSH    DX
  920.         PUSH    BX
  921.         OR      DX,DX
  922.         MOV     DX,03DAH
  923.         JNE     @@65
  924. @@61:   LODSW
  925.         MOV     BX,AX
  926. @@62:   IN      AL,DX
  927.         TEST    AL,1
  928.         JNE     @@62
  929.         CLI
  930. @@63:   IN      AL,DX
  931.         TEST    AL,1
  932.         JE      @@63
  933.         MOV     AX,BX
  934.         STOSW
  935.         STI
  936.         LOOP    @@61
  937.         JMP     @@68
  938. @@65:   LODSB
  939.         MOV     BL,AL
  940.         INC     SI
  941. @@66:   IN      AL,DX
  942.         TEST    AL,1
  943.         JNE     @@66
  944.         CLI
  945. @@67:   IN      AL,DX
  946.         TEST    AL,1
  947.         JE      @@67
  948.         MOV     AL,BL
  949.         STOSW
  950.         STI
  951.         LOOP    @@65
  952. @@68:   POP     BX
  953.         POP     DX
  954. @@70:   MOV     SI,ES
  955.         POP     AX
  956.         POP     CX
  957.         POP     DI
  958.         POP     DS
  959.         POP     ES
  960.         RET
  961. end;
  962.  
  963. { TView }
  964.  
  965. constructor TView.Init(var Bounds: TRect);
  966. begin
  967.   TObject.Init;
  968.   Owner := nil;
  969.   State := sfVisible;
  970.   SetBounds(Bounds);
  971.   DragMode := dmLimitLoY;
  972.   HelpCtx := hcNoContext;
  973.   EventMask := evMouseDown + evKeyDown + evCommand;
  974. end;
  975.  
  976. constructor TView.Load(var S: TStream);
  977. begin
  978.   TObject.Init;
  979.   S.Read(Origin,
  980.     SizeOf(TPoint) * 3 +
  981.     SizeOf(Byte) * 2 +
  982.     SizeOf(Word) * 4);
  983. end;
  984.  
  985. destructor TView.Done;
  986. begin
  987.   Hide;
  988.   if Owner <> nil then Owner^.Delete(@Self);
  989. end;
  990.  
  991. procedure TView.Awaken;
  992. begin
  993. end;
  994.  
  995. procedure TView.BlockCursor;
  996. begin
  997.   SetState(sfCursorIns, True);
  998. end;
  999.  
  1000. procedure TView.CalcBounds(var Bounds: TRect; Delta: TPoint);
  1001. var
  1002.   S, D: Integer;
  1003.   Min, Max: TPoint;
  1004.  
  1005. procedure Grow(var I: Integer);
  1006. begin
  1007.   if GrowMode and gfGrowRel = 0 then Inc(I, D) else
  1008.     I := (I * S + (S - D) shr 1) div (S - D);
  1009. end;
  1010.  
  1011. function Range(Val, Min, Max: Integer): Integer;
  1012. begin
  1013.   if Val < Min then Range := Min else
  1014.     if Val > Max then Range := Max else
  1015.       Range := Val;
  1016. end;
  1017.  
  1018. begin
  1019.   GetBounds(Bounds);
  1020.   S := Owner^.Size.X;
  1021.   D := Delta.X;
  1022.   if GrowMode and gfGrowLoX <> 0 then Grow(Bounds.A.X);
  1023.   if GrowMode and gfGrowHiX <> 0 then Grow(Bounds.B.X);
  1024.   if Bounds.B.X - Bounds.A.X > MaxViewWidth then
  1025.     Bounds.B.X := Bounds.A.X + MaxViewWidth;
  1026.   S := Owner^.Size.Y;
  1027.   D := Delta.Y;
  1028.   if GrowMode and gfGrowLoY <> 0 then Grow(Bounds.A.Y);
  1029.   if GrowMode and gfGrowHiY <> 0 then Grow(Bounds.B.Y);
  1030.   SizeLimits(Min, Max);
  1031.   Bounds.B.X := Bounds.A.X + Range(Bounds.B.X - Bounds.A.X, Min.X, Max.X);
  1032.   Bounds.B.Y := Bounds.A.Y + Range(Bounds.B.Y - Bounds.A.Y, Min.Y, Max.Y);
  1033. end;
  1034.  
  1035. procedure TView.ChangeBounds(var Bounds: TRect);
  1036. begin
  1037.   SetBounds(Bounds);
  1038.   DrawView;
  1039. end;
  1040.  
  1041. procedure TView.ClearEvent(var Event: TEvent);
  1042. begin
  1043.   Event.What := evNothing;
  1044.   Event.InfoPtr := @Self;
  1045. end;
  1046.  
  1047. function TView.CommandEnabled(Command: Word): Boolean;
  1048. begin
  1049.   CommandEnabled := (Command > 255) or (Command in CurCommandSet);
  1050. end;
  1051.  
  1052. function TView.DataSize: Word;
  1053. begin
  1054.   DataSize := 0;
  1055. end;
  1056.  
  1057. procedure TView.DisableCommands(Commands: TCommandSet);
  1058. begin
  1059.   CommandSetChanged := CommandSetChanged or (CurCommandSet * Commands <> []);
  1060.   CurCommandSet := CurCommandSet - Commands;
  1061. end;
  1062.  
  1063. procedure TView.DragView(Event: TEvent; Mode: Byte;
  1064.   var Limits: TRect; MinSize, MaxSize: TPoint);
  1065. var
  1066.   P, S: TPoint;
  1067.   SaveBounds: TRect;
  1068.  
  1069. function Min(I, J: Integer): Integer;
  1070. begin
  1071.   if I < J then Min := I else Min := J;
  1072. end;
  1073.  
  1074. function Max(I, J: Integer): Integer;
  1075. begin
  1076.   if I > J then Max := I else Max := J;
  1077. end;
  1078.  
  1079. procedure MoveGrow(P, S: TPoint);
  1080. var
  1081.   R: TRect;
  1082. begin
  1083.   S.X := Min(Max(S.X, MinSize.X), MaxSize.X);
  1084.   S.Y := Min(Max(S.Y, MinSize.Y), MaxSize.Y);
  1085.   P.X := Min(Max(P.X, Limits.A.X - S.X + 1), Limits.B.X - 1);
  1086.   P.Y := Min(Max(P.Y, Limits.A.Y - S.Y + 1), Limits.B.Y - 1);
  1087.   if Mode and dmLimitLoX <> 0 then P.X := Max(P.X, Limits.A.X);
  1088.   if Mode and dmLimitLoY <> 0 then P.Y := Max(P.Y, Limits.A.Y);
  1089.   if Mode and dmLimitHiX <> 0 then P.X := Min(P.X, Limits.B.X - S.X);
  1090.   if Mode and dmLimitHiY <> 0 then P.Y := Min(P.Y, Limits.B.Y - S.Y);
  1091.   R.Assign(P.X, P.Y, P.X + S.X, P.Y + S.Y);
  1092.   Locate(R);
  1093. end;
  1094.  
  1095. procedure Change(DX, DY: Integer);
  1096. begin
  1097.   if (Mode and dmDragMove <> 0) and (GetShiftState and $03 = 0) then
  1098.   begin
  1099.     Inc(P.X, DX);
  1100.     Inc(P.Y, DY);
  1101.   end else
  1102.   if (Mode and dmDragGrow <> 0) and (GetShiftState and $03 <> 0) then
  1103.   begin
  1104.     Inc(S.X, DX);
  1105.     Inc(S.Y, DY);
  1106.   end;
  1107. end;
  1108.  
  1109. procedure Update(X, Y: Integer);
  1110. begin
  1111.   if Mode and dmDragMove <> 0 then
  1112.   begin
  1113.     P.X := X;
  1114.     P.Y := Y;
  1115.   end;
  1116. end;
  1117.  
  1118. begin
  1119.   SetState(sfDragging, True);
  1120.   if Event.What = evMouseDown then
  1121.   begin
  1122.     if Mode and dmDragMove <> 0 then
  1123.     begin
  1124.       P.X := Origin.X - Event.Where.X;
  1125.       P.Y := Origin.Y - Event.Where.Y;
  1126.       repeat
  1127.         Inc(Event.Where.X, P.X);
  1128.         Inc(Event.Where.Y, P.Y);
  1129.         MoveGrow(Event.Where, Size);
  1130.       until not MouseEvent(Event, evMouseMove);
  1131.     end else
  1132.     begin
  1133.       P.X := Size.X - Event.Where.X;
  1134.       P.Y := Size.Y - Event.Where.Y;
  1135.       repeat
  1136.         Inc(Event.Where.X, P.X);
  1137.         Inc(Event.Where.Y, P.Y);
  1138.         MoveGrow(Origin, Event.Where);
  1139.       until not MouseEvent(Event, evMouseMove);
  1140.     end;
  1141.   end else
  1142.   begin
  1143.     GetBounds(SaveBounds);
  1144.     repeat
  1145.       P := Origin;
  1146.       S := Size;
  1147.       KeyEvent(Event);
  1148.       case Event.KeyCode and $FF00 of
  1149.         kbLeft: Change(-1, 0);
  1150.         kbRight: Change(1, 0);
  1151.         kbUp: Change(0, -1);
  1152.         kbDown: Change(0, 1);
  1153.         kbCtrlLeft: Change(-8, 0);
  1154.         kbCtrlRight: Change(8, 0);
  1155.         kbHome: Update(Limits.A.X, P.Y);
  1156.         kbEnd: Update(Limits.B.X - S.X, P.Y);
  1157.         kbPgUp: Update(P.X, Limits.A.Y);
  1158.         kbPgDn: Update(P.X, Limits.B.Y - S.Y);
  1159.       end;
  1160.       MoveGrow(P, S);
  1161.     until (Event.KeyCode = kbEnter) or (Event.KeyCode = kbEsc);
  1162.     if Event.KeyCode = kbEsc then Locate(SaveBounds);
  1163.   end;
  1164.   SetState(sfDragging, False);
  1165. end;
  1166.  
  1167. procedure TView.Draw;
  1168. var
  1169.   B: TDrawBuffer;
  1170. begin
  1171.   MoveChar(B, ' ', GetColor(1), Size.X);
  1172.   WriteLine(0, 0, Size.X, Size.Y, B);
  1173. end;
  1174.  
  1175. procedure TView.DrawCursor;
  1176. begin
  1177.   if State and sfFocused <> 0 then ResetCursor;
  1178. end;
  1179.  
  1180. procedure TView.DrawHide(LastView: PView);
  1181. begin
  1182.   DrawCursor;
  1183.   DrawUnderView(State and sfShadow <> 0, LastView);
  1184. end;
  1185.  
  1186. procedure TView.DrawShow(LastView: PView);
  1187. begin
  1188.   DrawView;
  1189.   if State and sfShadow <> 0 then DrawUnderView(True, LastView);
  1190. end;
  1191.  
  1192. procedure TView.DrawUnderRect(var R: TRect; LastView: PView);
  1193. begin
  1194.   Owner^.Clip.Intersect(R);
  1195.   Owner^.DrawSubViews(NextView, LastView);
  1196.   Owner^.GetExtent(Owner^.Clip);
  1197. end;
  1198.  
  1199. procedure TView.DrawUnderView(DoShadow: Boolean; LastView: PView);
  1200. var
  1201.   R: TRect;
  1202. begin
  1203.   GetBounds(R);
  1204.   if DoShadow then
  1205.   begin
  1206.     Inc(R.B.X, ShadowSize.X);
  1207.     Inc(R.B.Y, ShadowSize.Y);
  1208.   end;
  1209.   DrawUnderRect(R, LastView);
  1210. end;
  1211.  
  1212. procedure TView.DrawView;
  1213. begin
  1214.   if Exposed then
  1215.   begin
  1216.     Draw;
  1217.     DrawCursor;
  1218.   end;
  1219. end;
  1220.  
  1221. procedure TView.EnableCommands(Commands: TCommandSet);
  1222. begin
  1223.   CommandSetChanged := CommandSetChanged or
  1224.     (CurCommandSet * Commands <> Commands);
  1225.   CurCommandSet := CurCommandSet + Commands;
  1226. end;
  1227.  
  1228. procedure TView.EndModal(Command: Word);
  1229. var
  1230.   P: PView;
  1231. begin
  1232.   P := TopView;
  1233.   if TopView <> nil then TopView^.EndModal(Command);
  1234. end;
  1235.  
  1236. function TView.EventAvail: Boolean;
  1237. var
  1238.   Event: TEvent;
  1239. begin
  1240.   GetEvent(Event);
  1241.   if Event.What <> evNothing then PutEvent(Event);
  1242.   EventAvail := Event.What <> evNothing;
  1243. end;
  1244.  
  1245. procedure TView.GetBounds(var Bounds: TRect); assembler;
  1246. asm
  1247.         PUSH    DS
  1248.         LDS     SI,Self
  1249.         ADD     SI,OFFSET TView.Origin
  1250.         LES     DI,Bounds
  1251.         CLD
  1252.         LODSW                           {Origin.X}
  1253.         MOV     CX,AX
  1254.         STOSW
  1255.         LODSW                           {Origin.Y}
  1256.         MOV     DX,AX
  1257.         STOSW
  1258.         LODSW                           {Size.X}
  1259.         ADD     AX,CX
  1260.         STOSW
  1261.         LODSW                           {Size.Y}
  1262.         ADD     AX,DX
  1263.         STOSW
  1264.         POP     DS
  1265. end;
  1266.  
  1267. function TView.Execute: Word;
  1268. begin
  1269.   Execute := cmCancel;
  1270. end;
  1271.  
  1272. function TView.Exposed: Boolean; assembler;
  1273. var
  1274.   Target: Pointer;
  1275. asm
  1276.         LES     DI,Self
  1277.         TEST    ES:[DI].TView.State,sfExposed
  1278.         JE      @@2
  1279.         XOR     AX,AX
  1280.         CMP     AX,ES:[DI].TView.Size.X
  1281.         JGE     @@2
  1282.         CMP     AX,ES:[DI].TView.Size.Y
  1283.         JGE     @@2
  1284. @@1:    XOR     BX,BX
  1285.         MOV     CX,ES:[DI].TView.Size.X
  1286.         PUSH    AX
  1287.         CALL    @@11
  1288.         POP     AX
  1289.         JNC     @@3
  1290.         LES     DI,Self
  1291.         INC     AX
  1292.         CMP     AX,ES:[DI].TView.Size.Y
  1293.         JL      @@1
  1294. @@2:    MOV     AL,0
  1295.         JMP     @@30
  1296. @@3:    MOV     AL,1
  1297.         JMP     @@30
  1298. @@8:    STC
  1299. @@9:    RETN
  1300. @@10:   LES     DI,ES:[DI].TView.Owner
  1301.         CMP     ES:[DI].TGroup.Buffer.Word[2],0
  1302.         JNE     @@9
  1303. @@11:   MOV     Target.Word[0],DI
  1304.         MOV     Target.Word[2],ES
  1305.         ADD     AX,ES:[DI].TView.Origin.Y
  1306.         MOV     SI,ES:[DI].TView.Origin.X
  1307.         ADD     BX,SI
  1308.         ADD     CX,SI
  1309.         LES     DI,ES:[DI].TView.Owner
  1310.         MOV     SI,ES
  1311.         OR      SI,DI
  1312.         JE      @@9
  1313.         CMP     AX,ES:[DI].TGroup.Clip.A.Y
  1314.         JL      @@8
  1315.         CMP     AX,ES:[DI].TGroup.Clip.B.Y
  1316.         JGE     @@8
  1317.         CMP     BX,ES:[DI].TGroup.Clip.A.X
  1318.         JGE     @@12
  1319.         MOV     BX,ES:[DI].TGroup.Clip.A.X
  1320. @@12:   CMP     CX,ES:[DI].TGroup.Clip.B.X
  1321.         JLE     @@13
  1322.         MOV     CX,ES:[DI].TGroup.Clip.B.X
  1323. @@13:   CMP     BX,CX
  1324.         JGE     @@8
  1325.         LES     DI,ES:[DI].TGroup.Last
  1326. @@20:   LES     DI,ES:[DI].TView.Next
  1327.         CMP     DI,Target.Word[0]
  1328.         JNE     @@21
  1329.         MOV     SI,ES
  1330.         CMP     SI,Target.Word[2]
  1331.         JE      @@10
  1332. @@21:   TEST    ES:[DI].TView.State,sfVisible
  1333.         JE      @@20
  1334.         MOV     SI,ES:[DI].TView.Origin.Y
  1335.         CMP     AX,SI
  1336.         JL      @@20
  1337.         ADD     SI,ES:[DI].TView.Size.Y
  1338.         CMP     AX,SI
  1339.         JGE     @@20
  1340.         MOV     SI,ES:[DI].TView.Origin.X
  1341.         CMP     BX,SI
  1342.         JL      @@22
  1343.         ADD     SI,ES:[DI].TView.Size.X
  1344.         CMP     BX,SI
  1345.         JGE     @@20
  1346.         MOV     BX,SI
  1347.         CMP     BX,CX
  1348.         JL      @@20
  1349.         STC
  1350.         RETN
  1351. @@22:   CMP     CX,SI
  1352.         JLE     @@20
  1353.         ADD     SI,ES:[DI].TView.Size.X
  1354.         CMP     CX,SI
  1355.         JG      @@23
  1356.         MOV     CX,ES:[DI].TView.Origin.X
  1357.         JMP     @@20
  1358. @@23:   PUSH    Target.Word[2]
  1359.         PUSH    Target.Word[0]
  1360.         PUSH    ES
  1361.         PUSH    DI
  1362.         PUSH    SI
  1363.         PUSH    CX
  1364.         PUSH    AX
  1365.         MOV     CX,ES:[DI].TView.Origin.X
  1366.         CALL    @@20
  1367.         POP     AX
  1368.         POP     CX
  1369.         POP     BX
  1370.         POP     DI
  1371.         POP     ES
  1372.         POP     Target.Word[0]
  1373.         POP     Target.Word[2]
  1374.         JC      @@20
  1375.         RETN
  1376. @@30:
  1377. end;
  1378.  
  1379. function TView.Focus: Boolean;
  1380. var
  1381.   Result: Boolean;
  1382. begin
  1383.   Result := True;
  1384.   if State and (sfSelected + sfModal) = 0 then
  1385.   begin
  1386.     if Owner <> nil then
  1387.     begin
  1388.       Result := Owner^.Focus;
  1389.       if Result then
  1390.         if ((Owner^.Current = nil) or
  1391.           (Owner^.Current^.Options and ofValidate = 0) or
  1392.           (Owner^.Current^.Valid(cmReleasedFocus))) then
  1393.           Select
  1394.         else
  1395.           Result := False;
  1396.     end;
  1397.   end;
  1398.   Focus := Result;
  1399. end;
  1400.  
  1401. procedure TView.GetClipRect(var Clip: TRect);
  1402. begin
  1403.   GetBounds(Clip);
  1404.   if Owner <> nil then Clip.Intersect(Owner^.Clip);
  1405.   Clip.Move(-Origin.X, -Origin.Y);
  1406. end;
  1407.  
  1408. function TView.GetColor(Color: Word): Word; assembler;
  1409. asm
  1410.         MOV     AX,Color
  1411.         CALL    MapCPair
  1412. end;
  1413.  
  1414. procedure TView.GetCommands(var Commands: TCommandSet);
  1415. begin
  1416.   Commands := CurCommandSet;
  1417. end;
  1418.  
  1419. procedure TView.GetData(var Rec);
  1420. begin
  1421. end;
  1422.  
  1423. procedure TView.GetEvent(var Event: TEvent);
  1424. begin
  1425.   if Owner <> nil then Owner^.GetEvent(Event);
  1426. end;
  1427.  
  1428. procedure TView.GetExtent(var Extent: TRect); assembler;
  1429. asm
  1430.         PUSH    DS
  1431.         LDS     SI,Self
  1432.         ADD     SI,OFFSET TView.Size
  1433.         LES     DI,Extent
  1434.         CLD
  1435.         XOR     AX,AX
  1436.         STOSW
  1437.         STOSW
  1438.         MOVSW
  1439.         MOVSW
  1440.         POP     DS
  1441. end;
  1442.  
  1443. function TView.GetHelpCtx: Word;
  1444. begin
  1445.   if State and sfDragging <> 0 then
  1446.     GetHelpCtx := hcDragging else
  1447.     GetHelpCtx := HelpCtx;
  1448. end;
  1449.  
  1450. function TView.GetPalette: PPalette;
  1451. begin
  1452.   GetPalette := nil;
  1453. end;
  1454.  
  1455. procedure TView.GetPeerViewPtr(var S: TStream; var P);
  1456. var
  1457.   Index: Integer;
  1458. begin
  1459.   S.Read(Index, SizeOf(Word));
  1460.   if (Index = 0) or (OwnerGroup = nil) then Pointer(P) := nil
  1461.   else
  1462.   begin
  1463.     Pointer(P) := FixupList^[Index];
  1464.     FixupList^[Index] := @P;
  1465.   end;
  1466. end;
  1467.  
  1468. function TView.GetState(AState: Word): Boolean;
  1469. begin
  1470.   GetState := State and AState = AState;
  1471. end;
  1472.  
  1473. procedure TView.GrowTo(X, Y: Integer);
  1474. var
  1475.   R: TRect;
  1476. begin
  1477.   R.Assign(Origin.X, Origin.Y, Origin.X + X, Origin.Y + Y);
  1478.   Locate(R);
  1479. end;
  1480.  
  1481. procedure TView.HandleEvent(var Event: TEvent);
  1482. begin
  1483.   if Event.What = evMouseDown then
  1484.     if (State and (sfSelected + sfDisabled) = 0) and
  1485.        (Options and ofSelectable <> 0) then
  1486.       if not Focus or (Options and ofFirstClick = 0) then
  1487.         ClearEvent(Event);
  1488. end;
  1489.  
  1490. procedure TView.Hide;
  1491. begin
  1492.   if State and sfVisible <> 0 then SetState(sfVisible, False);
  1493. end;
  1494.  
  1495. procedure TView.HideCursor;
  1496. begin
  1497.   SetState(sfCursorVis, False);
  1498. end;
  1499.  
  1500. procedure TView.KeyEvent(var Event: TEvent);
  1501. begin
  1502.   repeat GetEvent(Event) until Event.What = evKeyDown;
  1503. end;
  1504.  
  1505. procedure TView.Locate(var Bounds: TRect);
  1506. var
  1507.   R: TRect;
  1508.   Min, Max: TPoint;
  1509.  
  1510. function Range(Val, Min, Max: Integer): Integer;
  1511. begin
  1512.   if Val < Min then Range := Min else
  1513.     if Val > Max then Range := Max else
  1514.       Range := Val;
  1515. end;
  1516.  
  1517. begin
  1518.   SizeLimits(Min, Max);
  1519.   Bounds.B.X := Bounds.A.X + Range(Bounds.B.X - Bounds.A.X, Min.X, Max.X);
  1520.   Bounds.B.Y := Bounds.A.Y + Range(Bounds.B.Y - Bounds.A.Y, Min.Y, Max.Y);
  1521.   GetBounds(R);
  1522.   if not Bounds.Equals(R) then
  1523.   begin
  1524.     ChangeBounds(Bounds);
  1525.     if (Owner <> nil) and (State and sfVisible <> 0) then
  1526.     begin
  1527.       if State and sfShadow <> 0 then
  1528.       begin
  1529.         R.Union(Bounds);
  1530.         Inc(R.B.X, ShadowSize.X);
  1531.         Inc(R.B.Y, ShadowSize.Y);
  1532.       end;
  1533.       DrawUnderRect(R, nil);
  1534.     end;
  1535.   end;
  1536. end;
  1537.  
  1538. procedure TView.MakeFirst;
  1539. begin
  1540.   PutInFrontOf(Owner^.First);
  1541. end;
  1542.  
  1543. procedure TView.MakeGlobal(Source: TPoint; var Dest: TPoint); assembler;
  1544. asm
  1545.         LES     DI,Self
  1546.         XOR     AX,AX
  1547.         MOV     DX,AX
  1548. @@1:    ADD     AX,ES:[DI].TView.Origin.X
  1549.         ADD     DX,ES:[DI].TView.Origin.Y
  1550.         LES     DI,ES:[DI].TView.Owner
  1551.         MOV     SI,ES
  1552.         OR      SI,DI
  1553.         JNE     @@1
  1554.         ADD     AX,Source.X
  1555.         ADD     DX,Source.Y
  1556.         LES     DI,Dest
  1557.         CLD
  1558.         STOSW
  1559.         XCHG    AX,DX
  1560.         STOSW
  1561. end;
  1562.  
  1563. procedure TView.MakeLocal(Source: TPoint; var Dest: TPoint); assembler;
  1564. asm
  1565.         LES     DI,Self
  1566.         XOR     AX,AX
  1567.         MOV     DX,AX
  1568. @@1:    ADD     AX,ES:[DI].TView.Origin.X
  1569.         ADD     DX,ES:[DI].TView.Origin.Y
  1570.         LES     DI,ES:[DI].TView.Owner
  1571.         MOV     SI,ES
  1572.         OR      SI,DI
  1573.         JNE     @@1
  1574.         NEG     AX
  1575.         NEG     DX
  1576.         ADD     AX,Source.X
  1577.         ADD     DX,Source.Y
  1578.         LES     DI,Dest
  1579.         CLD
  1580.         STOSW
  1581.         XCHG    AX,DX
  1582.         STOSW
  1583. end;
  1584.  
  1585. function TView.MouseEvent(var Event: TEvent; Mask: Word): Boolean;
  1586. begin
  1587.   repeat GetEvent(Event) until Event.What and (Mask or evMouseUp) <> 0;
  1588.   MouseEvent := Event.What <> evMouseUp;
  1589. end;
  1590.  
  1591. function TView.MouseInView(Mouse: TPoint): Boolean;
  1592. var
  1593.   Extent: TRect;
  1594. begin
  1595.   MakeLocal(Mouse, Mouse);
  1596.   GetExtent(Extent);
  1597.   MouseInView := Extent.Contains(Mouse);
  1598. end;
  1599.  
  1600. procedure TView.MoveTo(X, Y: Integer);
  1601. var
  1602.   R: TRect;
  1603. begin
  1604.   R.Assign(X, Y, X + Size.X, Y + Size.Y);
  1605.   Locate(R);
  1606. end;
  1607.  
  1608. function TView.NextView: PView;
  1609. begin
  1610.   if @Self = Owner^.Last then NextView := nil else NextView := Next;
  1611. end;
  1612.  
  1613. procedure TView.NormalCursor;
  1614. begin
  1615.   SetState(sfCursorIns, False);
  1616. end;
  1617.  
  1618. function TView.Prev: PView; assembler;
  1619. asm
  1620.         LES     DI,Self
  1621.         MOV     CX,DI
  1622.         MOV     BX,ES
  1623. @@1:    MOV     AX,DI
  1624.         MOV     DX,ES
  1625.         LES     DI,ES:[DI].TView.Next
  1626.         CMP     DI,CX
  1627.         JNE     @@1
  1628.         MOV     SI,ES
  1629.         CMP     SI,BX
  1630.         JNE     @@1
  1631. end;
  1632.  
  1633. function TView.PrevView: PView;
  1634. begin
  1635.   if @Self = Owner^.First then PrevView := nil else PrevView := Prev;
  1636. end;
  1637.  
  1638. procedure TView.PutEvent(var Event: TEvent);
  1639. begin
  1640.   if Owner <> nil then Owner^.PutEvent(Event);
  1641. end;
  1642.  
  1643. procedure TView.PutInFrontOf(Target: PView);
  1644. var
  1645.   P, LastView: PView;
  1646.  
  1647. procedure MoveView;
  1648. begin
  1649.   Owner^.RemoveView(@Self);
  1650.   Owner^.InsertView(@Self, Target);
  1651. end;
  1652.  
  1653. begin
  1654.   if (Owner <> nil) and (Target <> @Self) and (Target <> NextView) and
  1655.     ((Target = nil) or (Target^.Owner = Owner)) then
  1656.     if State and sfVisible = 0 then MoveView else
  1657.     begin
  1658.       
  1659.       LastView := NextView;
  1660.       if LastView <> nil then
  1661.       begin
  1662.         P := Target;
  1663.         while (P <> nil) and (P <> LastView) do P := P^.NextView;
  1664.         if P = nil then LastView := Target;
  1665.       end;
  1666.       State := State and not sfVisible;
  1667.       if LastView = Target then DrawHide(LastView);
  1668.       MoveView;
  1669.       State := State or sfVisible;
  1670.       if LastView <> Target then DrawShow(LastView);
  1671.       if Options and ofSelectable <> 0 then
  1672.       begin
  1673.         Owner^.ResetCurrent;
  1674.         Owner^.ResetCursor;
  1675.       end;
  1676.     end;
  1677. end;
  1678.  
  1679. procedure TView.PutPeerViewPtr(var S: TStream; P: PView);
  1680. var
  1681.   Index: Integer;
  1682. begin
  1683.   if (P = nil) or (OwnerGroup = nil) then Index := 0
  1684.   else Index := OwnerGroup^.IndexOf(P);
  1685.   S.Write(Index, SizeOf(Word));
  1686. end;
  1687.  
  1688. procedure TView.ResetCursor; assembler;
  1689. asm
  1690.         LES     DI,Self
  1691.         MOV     AX,ES:[DI].TView.State
  1692.         NOT     AX
  1693.         TEST    AX,sfVisible+sfCursorVis+sfFocused
  1694.         JNE     @@4
  1695.         MOV     AX,ES:[DI].TView.Cursor.Y
  1696.         MOV     DX,ES:[DI].TView.Cursor.X
  1697. @@1:    OR      AX,AX
  1698.         JL      @@4
  1699.         CMP     AX,ES:[DI].TView.Size.Y
  1700.         JGE     @@4
  1701.         OR      DX,DX
  1702.         JL      @@4
  1703.         CMP     DX,ES:[DI].TView.Size.X
  1704.         JGE     @@4
  1705.         ADD     AX,ES:[DI].TView.Origin.Y
  1706.         ADD     DX,ES:[DI].TView.Origin.X
  1707.         MOV     CX,DI
  1708.         MOV     BX,ES
  1709.         LES     DI,ES:[DI].TView.Owner
  1710.         MOV     SI,ES
  1711.         OR      SI,DI
  1712.         JE      @@5
  1713.         TEST    ES:[DI].TView.State,sfVisible
  1714.         JE      @@4
  1715.         LES     DI,ES:[DI].TGroup.Last
  1716. @@2:    LES     DI,ES:[DI].TView.Next
  1717.         CMP     CX,DI
  1718.         JNE     @@3
  1719.         MOV     SI,ES
  1720.         CMP     BX,SI
  1721.         JNE     @@3
  1722.         LES     DI,ES:[DI].TView.Owner
  1723.         JMP     @@1
  1724. @@3:    TEST    ES:[DI].TView.State,sfVisible
  1725.         JE      @@2
  1726.         MOV     SI,ES:[DI].TView.Origin.Y
  1727.         CMP     AX,SI
  1728.         JL      @@2
  1729.         ADD     SI,ES:[DI].TView.Size.Y
  1730.         CMP     AX,SI
  1731.         JGE     @@2
  1732.         MOV     SI,ES:[DI].TView.Origin.X
  1733.         CMP     DX,SI
  1734.         JL      @@2
  1735.         ADD     SI,ES:[DI].TView.Size.X
  1736.         CMP     DX,SI
  1737.         JGE     @@2
  1738. @@4:    MOV     CX,2000H
  1739.         JMP     @@6
  1740. @@5:    MOV     DH,AL
  1741.         XOR     BH,BH
  1742.         MOV     AH,2
  1743.         INT     10H
  1744.         MOV     CX,CursorLines
  1745.         LES     DI,Self
  1746.         TEST    ES:[DI].TView.State,sfCursorIns
  1747.         JE      @@6
  1748.         MOV     CH,0
  1749.         OR      CL,CL
  1750.         JNE     @@6
  1751.         MOV     CL,7
  1752. @@6:    MOV     AH,1
  1753.         INT     10H
  1754. end;
  1755.  
  1756. procedure TView.Select;
  1757. begin
  1758.   if Options and ofSelectable <> 0 then
  1759.     if Options and ofTopSelect <> 0 then MakeFirst else
  1760.       if Owner <> nil then Owner^.SetCurrent(@Self, NormalSelect);
  1761. end;
  1762.  
  1763. procedure TView.SetBounds(var Bounds: TRect); assembler;
  1764. asm
  1765.         PUSH    DS
  1766.         LES     DI,Self
  1767.         LDS     SI,Bounds
  1768.         MOV     AX,[SI].TRect.A.X
  1769.         MOV     ES:[DI].Origin.X,AX
  1770.         MOV     AX,[SI].TRect.A.Y
  1771.         MOV     ES:[DI].Origin.Y,AX
  1772.         MOV     AX,[SI].TRect.B.X
  1773.         SUB     AX,[SI].TRect.A.X
  1774.         MOV     ES:[DI].Size.X,AX
  1775.         MOV     AX,[SI].TRect.B.Y
  1776.         SUB     AX,[SI].TRect.A.Y
  1777.         MOV     ES:[DI].Size.Y,AX
  1778.         POP     DS
  1779. end;
  1780.  
  1781. procedure TView.SetCmdState(Commands: TCommandSet; Enable: Boolean);
  1782. begin
  1783.   if Enable then EnableCommands(Commands)
  1784.   else DisableCommands(Commands);
  1785. end;
  1786.  
  1787. procedure TView.SetCommands(Commands: TCommandSet);
  1788. begin
  1789.   CommandSetChanged := CommandSetChanged or (CurCommandSet <> Commands);
  1790.   CurCommandSet := Commands;
  1791. end;
  1792.  
  1793. procedure TView.SetCursor(X, Y: Integer);
  1794. begin
  1795.   Cursor.X := X;
  1796.   Cursor.Y := Y;
  1797.   DrawCursor;
  1798. end;
  1799.  
  1800. procedure TView.SetData(var Rec);
  1801. begin
  1802. end;
  1803.  
  1804. procedure TView.SetState(AState: Word; Enable: Boolean);
  1805. var
  1806.   Command: Word;
  1807. begin
  1808.   if Enable then
  1809.     State := State or AState else
  1810.     State := State and not AState;
  1811.   if Owner <> nil then
  1812.     case AState of
  1813.       sfVisible:
  1814.         begin
  1815.           if Owner^.State and sfExposed <> 0 then
  1816.             SetState(sfExposed, Enable);
  1817.           if Enable then DrawShow(nil) else DrawHide(nil);
  1818.           if Options and ofSelectable <> 0 then Owner^.ResetCurrent;
  1819.         end;
  1820.       sfCursorVis, sfCursorIns:
  1821.         DrawCursor;
  1822.       sfShadow:
  1823.         DrawUnderView(True, nil);
  1824.       sfFocused:
  1825.         begin
  1826.           ResetCursor;
  1827.           if Enable then
  1828.             Command := cmReceivedFocus else
  1829.             Command := cmReleasedFocus;
  1830.           Message(Owner, evBroadcast, Command, @Self);
  1831.         end;
  1832.     end;
  1833. end;
  1834.  
  1835. procedure TView.Show;
  1836. begin
  1837.   if State and sfVisible = 0 then SetState(sfVisible, True);
  1838. end;
  1839.  
  1840. procedure TView.ShowCursor;
  1841. begin
  1842.   SetState(sfCursorVis, True);
  1843. end;
  1844.  
  1845. procedure TView.SizeLimits(var Min, Max: TPoint);
  1846. begin
  1847.   Longint(Min) := 0;
  1848.   if Owner <> nil then
  1849.     Max := Owner^.Size else
  1850.     Longint(Max) := $7FFF7FFF;
  1851. end;
  1852.  
  1853. procedure TView.Store(var S: TStream);
  1854. var
  1855.   SaveState: Word;
  1856. begin
  1857.   SaveState := State;
  1858.   State := State and not (sfActive + sfSelected + sfFocused + sfExposed);
  1859.   S.Write(Origin,
  1860.     SizeOf(TPoint) * 3 +
  1861.     SizeOf(Byte) * 2 +
  1862.     SizeOf(Word) * 4);
  1863.   State := SaveState;
  1864. end;
  1865.  
  1866. function TView.TopView: PView;
  1867. var
  1868.   P: PView;
  1869. begin
  1870.   if TheTopView = nil then
  1871.   begin
  1872.     P := @Self;
  1873.     while (P <> nil) and (P^.State and sfModal = 0) do P := P^.Owner;
  1874.     TopView := P;
  1875.   end
  1876.   else TopView := TheTopView;
  1877. end;
  1878.  
  1879. function TView.Valid(Command: Word): Boolean;
  1880. begin
  1881.   Valid := True;
  1882. end;
  1883.  
  1884. procedure TView.WriteBuf(X, Y, W, H: Integer; var Buf); assembler;
  1885. var
  1886.   Target: Pointer; {Variables used by WriteView}
  1887.   Buffer: Pointer;
  1888.   Offset: Word;
  1889. asm
  1890.         CMP     H,0
  1891.         JLE     @@2
  1892. @@1:    MOV     AX,Y
  1893.         MOV     BX,X
  1894.         MOV     CX,W
  1895.         LES     DI,Buf
  1896.         CALL    WriteView
  1897.         MOV     AX,W
  1898.         SHL     AX,1
  1899.         ADD     WORD PTR Buf[0],AX
  1900.         INC     Y
  1901.         DEC     H
  1902.         JNE     @@1
  1903. @@2:
  1904. end;
  1905.  
  1906. procedure TView.WriteChar(X, Y: Integer; C: Char; Color: Byte;
  1907.   Count: Integer); assembler;
  1908. var
  1909.   Target: Pointer; {Variables used by WriteView}
  1910.   Buffer: Pointer;
  1911.   Offset: Word;
  1912. asm
  1913.         MOV     AL,Color
  1914.         CALL    MapColor
  1915.         MOV     AH,AL
  1916.         MOV     AL,C
  1917.         MOV     CX,Count
  1918.         OR      CX,CX
  1919.         JLE     @@2
  1920.         CMP     CX,256
  1921.         JLE     @@1
  1922.         MOV     CX,256
  1923. @@1:    MOV     DI,CX
  1924.         SHL     DI,1
  1925.         SUB     SP,DI
  1926.         MOV     DI,SP
  1927.         PUSH    SS
  1928.         POP     ES
  1929.         MOV     DX,CX
  1930.         CLD
  1931.         REP     STOSW
  1932.         MOV     CX,DX
  1933.         MOV     DI,SP
  1934.         MOV     AX,Y
  1935.         MOV     BX,X
  1936.         CALL    WriteView
  1937. @@2:
  1938. end;
  1939.  
  1940. procedure TView.WriteLine(X, Y, W, H: Integer; var Buf); assembler;
  1941. var
  1942.   Target: Pointer; {Variables used by WriteView}
  1943.   Buffer: Pointer;
  1944.   Offset: Word;
  1945. asm
  1946.         CMP     H,0
  1947.         JLE     @@2
  1948. @@1:    MOV     AX,Y
  1949.         MOV     BX,X
  1950.         MOV     CX,W
  1951.         LES     DI,Buf
  1952.         CALL    WriteView
  1953.         INC     Y
  1954.         DEC     H
  1955.         JNE     @@1
  1956. @@2:
  1957. end;
  1958.  
  1959. procedure TView.WriteStr(X, Y: Integer; Str: String; Color: Byte); assembler;
  1960. var
  1961.   Target: Pointer; {Variables used by WriteView}
  1962.   Buffer: Pointer;
  1963.   Offset: Word;
  1964. asm
  1965.         MOV     AL,Color
  1966.         CALL    MapColor
  1967.         MOV     AH,AL
  1968.         MOV     BX,DS
  1969.         LDS     SI,Str
  1970.         CLD
  1971.         LODSB
  1972.         MOV     CL,AL
  1973.         XOR     CH,CH
  1974.         JCXZ    @@3
  1975.         MOV     DI,CX
  1976.         SHL     DI,1
  1977.         SUB     SP,DI
  1978.         MOV     DI,SP
  1979.         PUSH    SS
  1980.         POP     ES
  1981.         MOV     DX,CX
  1982. @@1:    LODSB
  1983.         STOSW
  1984.         LOOP    @@1
  1985.         MOV     DS,BX
  1986.         MOV     CX,DX
  1987.         MOV     DI,SP
  1988.         MOV     AX,Y
  1989.         MOV     BX,X
  1990.         CALL    WriteView
  1991.         JMP     @@2
  1992. @@3:    MOV     DS,BX
  1993. @@2:
  1994. end;
  1995.  
  1996. { TFrame }
  1997.  
  1998. constructor TFrame.Init(var Bounds: TRect);
  1999. begin
  2000.   TView.Init(Bounds);
  2001.   GrowMode := gfGrowHiX + gfGrowHiY;
  2002.   EventMask := EventMask or evBroadcast;
  2003. end;
  2004.  
  2005. procedure TFrame.FrameLine(var FrameBuf; Y, N: Integer; Color: Byte);
  2006. const
  2007.   InitFrame: array[0..17] of Byte =
  2008.     (4, 4, 4, 3, 4, 9, 4, 4, 4,
  2009.      0, 1, 2, 3, 4, 5, 6, 7, 8);
  2010.   FrameChars: array[0..9] of Char =
  2011.     '┼┴╟┤ ═╔╦╚'#3;
  2012. var
  2013.   B: array[0..1] of Word absolute FrameBuf;
  2014.  
  2015. procedure DL(P: PView); far;
  2016. var
  2017.   R: TRect;
  2018. begin
  2019.   if (P^.State and sfVisible <> 0) and (P^.Options and ofFramed <> 0) then
  2020.   begin
  2021.     P^.GetBounds(R);
  2022.     R.Grow(1, 1);
  2023.     if R.A.Y = Y then
  2024.     begin
  2025.       if R.A.X <> 0 then MoveChar(B[R.A.X], #218, Color, 1);
  2026.       MoveChar(B[R.A.X+1], #196, Color, P^.Size.X);
  2027.       if R.B.X <> Size.X then MoveChar(B[R.B.X-1], #191, Color, 1);
  2028.       Exit;
  2029.     end;
  2030.     if R.B.Y = Y+1 then
  2031.     begin
  2032.       if R.A.X <> 0 then MoveChar(B[R.A.X], #192, Color, 1);
  2033.       MoveChar(B[R.A.X+1], #196, Color, P^.Size.X);
  2034.       if R.B.X <> Size.X then MoveChar(B[R.B.X-1], #11, Color, 1);
  2035.       Exit;
  2036.     end;
  2037.     if (R.A.Y < Y) and (R.B.Y > Y+1) then
  2038.     begin
  2039.       if R.A.X <> 0 then MoveChar(B[R.A.X], #179, Color, 1);
  2040.       MoveChar(B[R.A.X+1], #32, Color, P^.Size.X);
  2041.       if R.B.X <> Size.X then MoveChar(B[R.B.X-1], #179, Color, 1);
  2042.     end;
  2043.   end;
  2044. end;
  2045.  
  2046. begin
  2047.   MoveChar(B, FrameChars[InitFrame[N]], Color, 1);
  2048.   MoveChar(B[1], FrameChars[InitFrame[N+1]], Color, Size.X-2);
  2049.   MoveChar(B[Size.X-1], FrameChars[InitFrame[N+2]], Color, 1);
  2050.   Owner^.ForEach(@DL);
  2051. end;
  2052.  
  2053. procedure TFrame.Draw;
  2054. var
  2055.   CIcons, CFrame, CTitle: Word;
  2056.   F, I, L, Width: Integer;
  2057.   B: TDrawBuffer;
  2058.   Title: TTitleStr;
  2059.   Min, Max: TPoint;
  2060. begin
  2061.   if State and sfActive = 0 then
  2062.   begin
  2063.     CFrame := $0101;
  2064.     CTitle := $0202;
  2065.     F := 9;
  2066.   end else
  2067.   begin
  2068.     CFrame := $0503;
  2069.     CTitle := $0404;
  2070.     CIcons := GetColor($0505);
  2071.     InvertColor(WordRec(CIcons).Hi);
  2072.     if PWindow(Owner)^.Flags and wfBottomLine <> 0
  2073.       then F := 0
  2074.       else F := 9;
  2075.   end;
  2076.   CFrame := GetColor(CFrame);
  2077.   CTitle := GetColor(CTitle);
  2078.   Width := Size.X;
  2079.   L := Width - 10;
  2080.   if PWindow(Owner)^.Flags and (wfClose+wfZoom) <> 0 then Dec(L, 6);
  2081.   MoveChar(B, ' ', Byte(CTitle), Size.X);
  2082.   if (PWindow(Owner)^.Number <> wnNoNumber) and
  2083.      (PWindow(Owner)^.Number < 10) then
  2084.   begin
  2085.     Dec(L, 4);
  2086.     if PWindow(Owner)^.Flags and wfZoom <> 0 then I := 7
  2087.     else I := 3;
  2088.     WordRec(B[Width - I]).Lo := PWindow(Owner)^.Number + $30;
  2089.   end;
  2090.   if Owner <> nil then Title := PWindow(Owner)^.GetTitle(L)
  2091.   else Title := '';
  2092.   if Title <> '' then
  2093.   begin
  2094.     L := Length(Title);
  2095.     if L > Width - 10 then L := Width - 10;
  2096.     if L < 0 then L := 0;
  2097.     I := (Width - L) shr 1;
  2098.     MoveChar(B[I - 1], ' ', CTitle, 1);
  2099.     MoveBuf(B[I], Title[1], CTitle, L);
  2100.     MoveChar(B[I + L], ' ', CTitle, 1);
  2101.   end;
  2102.   if State and sfActive <> 0 then
  2103.   begin
  2104.     MoveCStr(B[0], #207#4, CIcons);
  2105.     if PWindow(Owner)^.Flags and wfZoom <> 0 then
  2106.     begin
  2107.       MoveCStr(B[Width - 2], '~'#195'~'#7, CIcons);
  2108.       Owner^.SizeLimits(Min, Max);
  2109.       if Longint(Owner^.Size) = Longint(Max) then
  2110.         MoveCStr(B[Width - 2], '~'#194'~'#6, CIcons);
  2111.     end;
  2112.   end;
  2113.   WriteLine(0, 0, Size.X, 1, B);
  2114.   for I := 1 to Size.Y - 2 do
  2115.   begin
  2116.     FrameLine(B, I, F + 3, Byte(CFrame));
  2117.     WriteLine(0, I, Size.X, 1, B);
  2118.   end;
  2119.   if F = 0 then
  2120.   begin
  2121.     MoveChar(B, ' ', Byte(CTitle), Size.X );
  2122.     MoveChar(B, '┤', (Byte(CTitle) and $F0) or (Byte(CFrame) and $0F), 1);
  2123.   end else
  2124.     FrameLine(B, Size.Y - 1, F + 6, Byte(CFrame));
  2125.   if State and sfActive <> 0 then
  2126.     if PWindow(Owner)^.Flags and wfGrow <> 0 then
  2127.       MoveCStr(B[Width - 2], '~'#217'~'#15, CIcons);
  2128.   WriteLine(0, Size.Y - 1, Size.X, 1, B);
  2129. end;
  2130.  
  2131. function TFrame.GetPalette: PPalette;
  2132. const
  2133.   P: String[Length(CFrame)] = CFrame;
  2134. begin
  2135.   GetPalette := @P;
  2136. end;
  2137.  
  2138. procedure TFrame.HandleEvent(var Event: TEvent);
  2139. var
  2140.   Mouse: TPoint;
  2141.  
  2142. procedure DragWindow(Mode: Byte);
  2143. var
  2144.   Limits: TRect;
  2145.   Min, Max: TPoint;
  2146. begin
  2147.   Owner^.Owner^.GetExtent(Limits);
  2148.   Owner^.SizeLimits(Min, Max);
  2149.   Owner^.DragView(Event, Owner^.DragMode or Mode, Limits, Min, Max);
  2150.   ClearEvent(Event);
  2151. end;
  2152.  
  2153. procedure CallWindowMenu;
  2154. var
  2155.   P: PMenuView;
  2156.   R: TRect;
  2157. begin
  2158.   R.Assign(0, 1, 25, 5);
  2159.   P := New(PMenuPopup, Init(R, NewMenu(
  2160.     NewItem('~ç~á¬αδΓ∞', 'Alt+F3', kbAltF3, cmClose, hcNoContext,
  2161.     NewItem('~É~ẼÑα/îÑßΓ«', 'Ctrl+F5', kbCtrlF5, cmResize, hcNoContext,
  2162.     NewItem('~ô~óѽ¿τ¿Γ∞', 'F5', kbF5, cmZoom, hcNoContext, nil))))));
  2163.   Event.Command := PGroup(Owner)^.ExecView(P);
  2164.   Dispose(P, Done);
  2165.   Event.What := evCommand;
  2166.   Event.InfoPtr := Owner;
  2167.   PutEvent(Event);
  2168. end;
  2169.  
  2170. begin
  2171.   TView.HandleEvent(Event);
  2172.   case Event.What of
  2173.   evBroadcast:
  2174.     if Event.Command = cmWindowMenu then
  2175.     begin
  2176.       CallWindowMenu;
  2177.       ClearEvent(Event);
  2178.     end;
  2179.   evMouseDown:
  2180.   begin
  2181.     MakeLocal(Event.Where, Mouse);
  2182.     if Mouse.Y = 0 then
  2183.     begin
  2184.       if (State and sfActive <> 0) and (Mouse.X >= 0) and (Mouse.X <= 1) then
  2185.       begin
  2186.         repeat
  2187.           MakeLocal(Event.Where, Mouse);
  2188.           if (Mouse.X >= 0) and (Mouse.X <= 1) and (Mouse.Y = 0) then
  2189.             FrameMode := fmCloseClicked
  2190.           else FrameMode := 0;
  2191.           DrawView;
  2192.         until not MouseEvent(Event, evMouseMove + evMouseAuto);
  2193.         FrameMode := 0;
  2194.         if (Mouse.X >= 0) and (Mouse.X <= 1) and (Mouse.Y = 0) then
  2195.           CallWindowMenu;
  2196.         ClearEvent(Event);
  2197.         DrawView;
  2198.       end else
  2199.         if (PWindow(Owner)^.Flags and wfZoom <> 0) and
  2200.           (State and sfActive <> 0) and (Event.Double or
  2201.           (Mouse.X >= Size.X - 2) and
  2202.           (Mouse.X <= Size.X - 1)) then
  2203.         begin
  2204.           if not Event.Double then
  2205.             repeat
  2206.               MakeLocal(Event.Where, Mouse);
  2207.               if (Mouse.X >= Size.X - 2) and (Mouse.X <= Size.X - 1) and
  2208.                 (Mouse.Y = 0) then
  2209.                 FrameMode := fmZoomClicked
  2210.               else FrameMode := 0;
  2211.               DrawView;
  2212.             until not MouseEvent(Event, evMouseMove + evMouseAuto);
  2213.           FrameMode := 0;
  2214.           if ((Mouse.X >= Size.X - 2) and (Mouse.X <= Size.X - 1) and
  2215.               (Mouse.Y = 0)) or Event.Double then
  2216.           begin
  2217.             Event.What := evCommand;
  2218.             Event.Command := cmZoom;
  2219.             Event.InfoPtr := Owner;
  2220.             PutEvent(Event);
  2221.           end;
  2222.           ClearEvent(Event);
  2223.           DrawView;
  2224.         end else
  2225.           if PWindow(Owner)^.Flags and wfMove <> 0 then
  2226.             DragWindow(dmDragMove);
  2227.     end else
  2228.       if (State and sfActive <> 0) and (Mouse.X >= Size.X - 2) and
  2229.           (Mouse.Y >= Size.Y - 1) then
  2230.         if PWindow(Owner)^.Flags and wfGrow <> 0 then
  2231.           DragWindow(dmDragGrow);
  2232.   end;
  2233.   end;
  2234. end;
  2235.  
  2236. procedure TFrame.SetState(AState: Word; Enable: Boolean);
  2237. begin
  2238.   TView.SetState(AState, Enable);
  2239.   if AState and (sfActive + sfDragging) <> 0 then DrawView;
  2240. end;
  2241.  
  2242. { TScrollBar }
  2243.  
  2244. constructor TScrollBar.Init(var Bounds: TRect);
  2245. const
  2246.   VChars: TScrollChars = (#202,#12, #204,#14, #180,#003, #254,#254, #211,#28);
  2247.   HChars: TScrollChars = (#208,#21, #198,#19, #209,#209, #254,#254, #215,#212);
  2248. begin
  2249.   TView.Init(Bounds);
  2250.   Value := 0;
  2251.   Min := 0;
  2252.   Max := 0;
  2253.   PgStep := 1;
  2254.   ArStep := 1;
  2255.   if Size.X = 2 then
  2256.   begin
  2257.     GrowMode := gfGrowLoX + gfGrowHiX + gfGrowHiY;
  2258.     Chars := VChars;
  2259.   end else
  2260.   begin
  2261.     GrowMode := gfGrowLoY + gfGrowHiX + gfGrowHiY;
  2262.     Chars := HChars;
  2263.   end;
  2264. end;
  2265.  
  2266. constructor TScrollBar.Load(var S: TStream);
  2267. begin
  2268.   TView.Load(S);
  2269.   S.Read(Value, SizeOf(Integer) * 5 + SizeOf(TScrollChars));
  2270. end;
  2271.  
  2272. procedure TScrollBar.Draw;
  2273. begin
  2274.   DrawPos(GetPos);
  2275. end;
  2276.  
  2277. procedure TScrollBar.DrawPos(Pos: Integer);
  2278. var
  2279.   I, S, M: Integer;
  2280.   B: TDrawBuffer;
  2281.   CPage, CIcons: Word;
  2282. begin
  2283.   CPage := GetColor(1);
  2284.   CIcons := GetColor($0202);
  2285.   InvertColor(Byte(CIcons));
  2286.   if Size.X = 2
  2287.     then M := 2
  2288.     else M := 1;
  2289.   S := GetSize * M;
  2290.   if Size.X = 2
  2291.     then MoveCStr(B, Chars[0]+'~'+Chars[1]+'~', CIcons)
  2292.     else MoveCStr(B, Chars[0]+Chars[1], CIcons);
  2293.   if Max = Min then
  2294.     MoveChar(B[2], Chars[8], CPage, S * M)
  2295.   else
  2296.   begin
  2297.     I := 2;
  2298.     while I <= (S - 4) * M + 2 do
  2299.     begin
  2300.       MoveStr(B[I], Chars[4]+Chars[5], CPage);
  2301.       Inc(I, 2);
  2302.     end;
  2303.     MoveCStr(B[Pos * M], Chars[8]+Chars[9], CPage);
  2304.   end;
  2305.   MoveCStr(B[S - 2], Chars[2]+'~'+Chars[3]+'~', CIcons);
  2306.   WriteBuf(0, 0, Size.X, Size.Y, B);
  2307. end;
  2308.  
  2309. function TScrollBar.GetPalette: PPalette;
  2310. const
  2311.   P: String[Length(CScrollBar)] = CScrollBar;
  2312. begin
  2313.   GetPalette := @P;
  2314. end;
  2315.  
  2316. function TScrollBar.GetPos: Integer;
  2317. var
  2318.   M, R: Integer;
  2319. begin
  2320.   R := Max - Min;
  2321.   if Size.X = 2 then M := 0 else M := 1;
  2322.   if R = 0 then GetPos := 1 else
  2323.     R := LongDiv(LongMul(Value - Min, GetSize - 3 - 2*M) + R shr 1, R) + 1 + M;
  2324.   if (M = 1) and (R = GetSize - 3) then Dec(R);
  2325.   GetPos := R;
  2326. end;
  2327.  
  2328. function TScrollBar.GetSize: Integer;
  2329. var
  2330.   S: Integer;
  2331. begin
  2332.   if Size.X = 2 then S := Size.Y else S := Size.X;
  2333.   if S < 3 then GetSize := 3 else GetSize := S;
  2334. end;
  2335.  
  2336. procedure TScrollBar.HandleEvent(var Event: TEvent);
  2337. var
  2338.   Tracking: Boolean;
  2339.   I, P, S, M, ClickPart: Integer;
  2340.   Mouse: TPoint;
  2341.   Extent: TRect;
  2342.  
  2343. function GetPartCode: Integer;
  2344. var
  2345.   Mark, Part: Integer;
  2346. begin
  2347.   Part := -1;
  2348.   if Extent.Contains(Mouse) then
  2349.   begin
  2350.     if Size.X = 2 then Mark := Mouse.Y else Mark := Mouse.X;
  2351.     if (Mark = P) or (Mark = P+M-1) then Part := sbIndicator else
  2352.     begin
  2353.       if Mark < M then Part := sbLeftArrow else
  2354.         if Mark < P then Part := sbPageLeft else
  2355.           if Mark < S-M then Part := sbPageRight else
  2356.             Part := sbRightArrow;
  2357.       if Size.X = 2 then Inc(Part, 4);
  2358.     end;
  2359.   end;
  2360.   GetPartCode := Part;
  2361. end;
  2362.  
  2363. procedure Clicked;
  2364. begin
  2365.   Message(Owner, evBroadcast, cmScrollBarClicked, @Self);
  2366. end;
  2367.  
  2368. begin
  2369.   TView.HandleEvent(Event);
  2370.   case Event.What of
  2371.     evMouseDown:
  2372.       begin
  2373.         Clicked;
  2374.         MakeLocal(Event.Where, Mouse);
  2375.         GetExtent(Extent);
  2376.         Extent.Grow(1, 1);
  2377.         P := GetPos;
  2378.         if Size.X = 2 then M := 1 else M := 2;
  2379.         S := GetSize;
  2380.         ClickPart := GetPartCode;
  2381.         if ClickPart <> sbIndicator then
  2382.         begin
  2383.           repeat
  2384.             MakeLocal(Event.Where, Mouse);
  2385.             if GetPartCode = ClickPart then
  2386.               SetValue(Value + ScrollStep(ClickPart));
  2387.           until not MouseEvent(Event, evMouseAuto);
  2388.         end else
  2389.         begin
  2390.           repeat
  2391.             MakeLocal(Event.Where, Mouse);
  2392.             Tracking := Extent.Contains(Mouse);
  2393.             if Tracking then
  2394.             begin
  2395.               if Size.X = 2 then I := Mouse.Y else I := Mouse.X;
  2396.               if I < M then I := M;
  2397.               if I > S-M*2 then I := S-M*2;
  2398.             end else I := GetPos;
  2399.             if I <> P then
  2400.             begin
  2401.               DrawPos(I);
  2402.               P := I;
  2403.             end;
  2404.           until not MouseEvent(Event, evMouseMove);
  2405.           if Tracking and (S > M*2+1) then
  2406.           begin
  2407.             Dec(S, M*2+1);
  2408.             SetValue(LongDiv(LongMul(P - M, Max - Min) + S shr 1, S) + Min);
  2409.           end;
  2410.         end;
  2411.         ClearEvent(Event);
  2412.       end;
  2413.     evKeyDown:
  2414.       if State and sfVisible <> 0 then
  2415.       begin
  2416.         ClickPart := sbIndicator;
  2417.         if Size.Y = 1 then
  2418.           case CtrlToArrow(Event.KeyCode) of
  2419.             kbLeft: ClickPart := sbLeftArrow;
  2420.             kbRight: ClickPart := sbRightArrow;
  2421.             kbCtrlLeft: ClickPart := sbPageLeft;
  2422.             kbCtrlRight: ClickPart := sbPageRight;
  2423.             kbHome: I := Min;
  2424.             kbEnd: I := Max;
  2425.           else
  2426.             Exit;
  2427.           end
  2428.         else
  2429.           case CtrlToArrow(Event.KeyCode) of
  2430.             kbUp: ClickPart := sbUpArrow;
  2431.             kbDown: ClickPart := sbDownArrow;
  2432.             kbPgUp: ClickPart := sbPageUp;
  2433.             kbPgDn: ClickPart := sbPageDown;
  2434.             kbCtrlPgUp: I := Min;
  2435.             kbCtrlPgDn: I := Max;
  2436.           else
  2437.             Exit;
  2438.           end;
  2439.         Clicked;
  2440.         if ClickPart <> sbIndicator then I := Value + ScrollStep(ClickPart);
  2441.         SetValue(I);
  2442.         ClearEvent(Event);
  2443.       end;
  2444.   end;
  2445. end;
  2446.  
  2447. procedure TScrollBar.ScrollDraw;
  2448. begin
  2449.   Message(Owner, evBroadcast, cmScrollBarChanged, @Self);
  2450. end;
  2451.  
  2452. function TScrollBar.ScrollStep(Part: Integer): Integer;
  2453. var
  2454.   Step: Integer;
  2455. begin
  2456.   if Part and 2 = 0 then Step := ArStep else Step := PgStep;
  2457.   if Part and 1 = 0 then ScrollStep := -Step else ScrollStep := Step;
  2458. end;
  2459.  
  2460. procedure TScrollBar.SetParams(AValue, AMin, AMax, APgStep,
  2461.   AArStep: Integer);
  2462. var
  2463.   SValue: Integer;
  2464.   IsVisible: Boolean;
  2465. begin
  2466.   if AMax < AMin then AMax := AMin;
  2467.   if AValue < AMin then AValue := AMin;
  2468.   if AValue > AMax then AValue := AMax;
  2469.   SValue := Value;
  2470.   if (SValue <> AValue) or (Min <> AMin) or (Max <> AMax) then
  2471.   begin
  2472.     Value := AValue;
  2473.     Min := AMin;
  2474.     Max := AMax;
  2475.     IsVisible := GetState(sfVisible);
  2476.     if AMin = AMax
  2477.       then if IsVisible then Hide else {}
  2478.       else if not IsVisible and GetState(sfActive) then Show;
  2479.     DrawView;
  2480.     if SValue <> AValue then ScrollDraw;
  2481.   end;
  2482.   PgStep := APgStep;
  2483.   ArStep := AArStep;
  2484. end;
  2485.  
  2486. procedure TScrollBar.SetRange(AMin, AMax: Integer);
  2487. begin
  2488.   SetParams(Value, AMin, AMax, PgStep, ArStep);
  2489. end;
  2490.  
  2491. procedure TScrollBar.SetState(AState: Word; Enable: Boolean);
  2492. begin
  2493.   if (AState and sfVisible <> 0) and Enable and (Min = Max) then Exit;
  2494.   inherited SetState(AState, Enable);
  2495. end;
  2496.  
  2497. procedure TScrollBar.SetStep(APgStep, AArStep: Integer);
  2498. begin
  2499.   SetParams(Value, Min, Max, APgStep, AArStep);
  2500. end;
  2501.  
  2502. procedure TScrollBar.SetValue(AValue: Integer);
  2503. begin
  2504.   SetParams(AValue, Min, Max, PgStep, ArStep);
  2505. end;
  2506.  
  2507. procedure TScrollBar.Store(var S: TStream);
  2508. begin
  2509.   TView.Store(S);
  2510.   S.Write(Value, SizeOf(Integer) * 5 + SizeOf(TScrollChars));
  2511. end;
  2512.  
  2513. { TScroller }
  2514.  
  2515. constructor TScroller.Init(var Bounds: TRect; AHScrollBar,
  2516.   AVScrollBar: PScrollBar);
  2517. begin
  2518.   TView.Init(Bounds);
  2519.   Options := Options or ofSelectable;
  2520.   EventMask := EventMask or evBroadcast;
  2521.   HScrollBar := AHScrollBar;
  2522.   VScrollBar := AVScrollBar;
  2523. end;
  2524.  
  2525. constructor TScroller.Load(var S: TStream);
  2526. begin
  2527.   TView.Load(S);
  2528.   GetPeerViewPtr(S, HScrollBar);
  2529.   GetPeerViewPtr(S, VScrollBar);
  2530.   S.Read(Delta, SizeOf(TPoint)*2);
  2531. end;
  2532.  
  2533. procedure TScroller.ChangeBounds(var Bounds: TRect);
  2534. begin
  2535.   SetBounds(Bounds);
  2536.   Inc(DrawLock);
  2537.   SetLimit(Limit.X, Limit.Y);
  2538.   Dec(DrawLock);
  2539.   DrawFlag := False;
  2540.   DrawView;
  2541. end;
  2542.  
  2543. procedure TScroller.CheckDraw;
  2544. begin
  2545.   if (DrawLock = 0) and DrawFlag then
  2546.   begin
  2547.     DrawFlag := False;
  2548.     DrawView;
  2549.   end;
  2550. end;
  2551.  
  2552. function TScroller.GetPalette: PPalette;
  2553. const
  2554.   P: String[Length(CScroller)] = CScroller;
  2555. begin
  2556.   GetPalette := @P;
  2557. end;
  2558.  
  2559. procedure TScroller.HandleEvent(var Event: TEvent);
  2560. begin
  2561.   TView.HandleEvent(Event);
  2562.   if (Event.What = evBroadcast) and (Event.Command = cmScrollBarChanged) and
  2563.      ((Event.InfoPtr = HScrollBar) or (Event.InfoPtr = VScrollBar)) then
  2564.       ScrollDraw;
  2565. end;
  2566.  
  2567. procedure TScroller.ScrollDraw;
  2568. var
  2569.   D: TPoint;
  2570. begin
  2571.   if HScrollBar <> nil then D.X := HScrollBar^.Value
  2572.   else D.X := 0;
  2573.   if VScrollBar <> nil then D.Y := VScrollBar^.Value
  2574.   else D.Y := 0;
  2575.   if (D.X <> Delta.X) or (D.Y <> Delta.Y) then
  2576.   begin
  2577.     SetCursor(Cursor.X + Delta.X - D.X, Cursor.Y + Delta.Y - D.Y);
  2578.     Delta := D;
  2579.     if DrawLock <> 0 then DrawFlag := True else DrawView;
  2580.   end;
  2581. end;
  2582.  
  2583. procedure TScroller.ScrollTo(X, Y: Integer);
  2584. begin
  2585.   Inc(DrawLock);
  2586.   if HScrollBar <> nil then HScrollBar^.SetValue(X);
  2587.   if VScrollBar <> nil then VScrollBar^.SetValue(Y);
  2588.   Dec(DrawLock);
  2589.   CheckDraw;
  2590. end;
  2591.  
  2592. procedure TScroller.SetLimit(X, Y: Integer);
  2593. begin
  2594.   Limit.X := X;
  2595.   Limit.Y := Y;
  2596.   Inc(DrawLock);
  2597.   if HScrollBar <> nil then
  2598.     HScrollBar^.SetParams(HScrollBar^.Value, 0, X - Size.X, Size.X - 1,
  2599.       HScrollBar^.ArStep);
  2600.   if VScrollBar <> nil then
  2601.     VScrollBar^.SetParams(VScrollBar^.Value, 0, Y - Size.Y, Size.Y - 1,
  2602.       VScrollBar^.ArStep);
  2603.   Dec(DrawLock);
  2604.   CheckDraw;
  2605. end;
  2606.  
  2607. procedure TScroller.SetState(AState: Word; Enable: Boolean);
  2608.  
  2609. procedure ShowSBar(SBar: PScrollBar);
  2610. begin
  2611.   if (SBar <> nil) then
  2612.     if GetState(sfActive + sfSelected) then SBar^.Show
  2613.     else SBar^.Hide;
  2614. end;
  2615.  
  2616. begin
  2617.   TView.SetState(AState, Enable);
  2618.   if AState and (sfActive + sfSelected) <> 0 then
  2619.   begin
  2620.     ShowSBar(HScrollBar);
  2621.     ShowSBar(VScrollBar);
  2622.   end;
  2623. end;
  2624.  
  2625. procedure TScroller.Store(var S: TStream);
  2626. begin
  2627.   TView.Store(S);
  2628.   PutPeerViewPtr(S, HScrollBar);
  2629.   PutPeerViewPtr(S, VScrollBar);
  2630.   S.Write(Delta, SizeOf(TPoint)*2);
  2631. end;
  2632.  
  2633. { TListViewer }
  2634.  
  2635. constructor TListViewer.Init(var Bounds: TRect; ANumCols: Word;
  2636.   AHScrollBar, AVScrollBar: PScrollBar);
  2637. var
  2638.   ArStep, PgStep: Integer;
  2639. begin
  2640.   TView.Init(Bounds);
  2641.   Options := Options or (ofFirstClick + ofSelectable);
  2642.   EventMask := EventMask or evBroadcast;
  2643.   Range := 0;
  2644.   NumCols := ANumCols;
  2645.   Focused := 0;
  2646.   if AVScrollBar <> nil then
  2647.   begin
  2648.     if NumCols = 1 then
  2649.     begin
  2650.       PgStep := Size.Y -1;
  2651.       ArStep := 1;
  2652.     end else
  2653.     begin
  2654.       PgStep := Size.Y * NumCols;
  2655.       ArStep := Size.Y;
  2656.     end;
  2657.     AVScrollBar^.SetStep(PgStep, ArStep);
  2658.   end;
  2659.   if AHScrollBar <> nil then AHScrollBar^.SetStep(Size.X div NumCols, 1);
  2660.   HScrollBar := AHScrollBar;
  2661.   VScrollBar := AVScrollBar;
  2662. end;
  2663.  
  2664. constructor TListViewer.Load(var S: TStream);
  2665. begin
  2666.   TView.Load(S);
  2667.   GetPeerViewPtr(S, HScrollBar);
  2668.   GetPeerViewPtr(S, VScrollBar);
  2669.   S.Read(NumCols, SizeOf(Word) * 4);
  2670. end;
  2671.  
  2672. procedure TListViewer.ChangeBounds(var Bounds: TRect);
  2673. begin
  2674.   TView.ChangeBounds(Bounds);
  2675.   if HScrollBar <> nil then
  2676.     HScrollBar^.SetStep(Size.X div NumCols, HScrollBar^.ArStep);
  2677.   if VScrollBar <> nil then
  2678.     VScrollBar^.SetStep(Size.Y, VScrollBar^.ArStep);
  2679. end;
  2680.  
  2681. procedure TListViewer.Draw;
  2682. var
  2683.   I, J, Item: Integer;
  2684.   NormalColor, SelectedColor, FocusedColor, Color: Word;
  2685.   ColWidth, CurCol, Indent: Integer;
  2686.   B: TDrawBuffer;
  2687.   Text: String;
  2688.   SCOff: Byte;
  2689. begin
  2690.   if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  2691.   begin
  2692.     NormalColor := GetColor(1);
  2693.     FocusedColor := GetColor(3);
  2694.     SelectedColor := GetColor(4);
  2695.   end else
  2696.   begin
  2697.     NormalColor := GetColor(2);
  2698.     SelectedColor := GetColor(4);
  2699.   end;
  2700.   if HScrollBar <> nil then Indent := HScrollBar^.Value
  2701.   else Indent := 0;
  2702.   ColWidth := Size.X div NumCols + 1;
  2703.   for I := 0 to Size.Y - 1 do
  2704.   begin
  2705.     for J := 0 to NumCols-1 do
  2706.     begin
  2707.       Item := J*Size.Y + I + TopItem;
  2708.       CurCol := J*ColWidth;
  2709.       if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  2710.         (Focused = Item) and (Range > 0) then
  2711.       begin
  2712.         Color := FocusedColor;
  2713.         SetCursor(CurCol+1,I);
  2714.         SCOff := 0;
  2715.       end
  2716.       else if (Item < Range) and IsSelected(Item) then
  2717.       begin
  2718.         Color := SelectedColor;
  2719.         SCOff := 2;
  2720.       end
  2721.       else
  2722.       begin
  2723.         Color := NormalColor;
  2724.         SCOff := 4;
  2725.       end;
  2726.       MoveChar(B[CurCol], ' ', Color, ColWidth);
  2727.       if Item < Range then
  2728.       begin
  2729.         Text := GetText(Item, ColWidth + Indent);
  2730.         Text := Copy(Text,Indent,ColWidth);
  2731.         MoveStr(B[CurCol+1], Text, Color);
  2732.         if ShowMarkers then
  2733.         begin
  2734.           WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  2735.           WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  2736.         end;
  2737.       end;
  2738.       MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  2739.     end;
  2740.     WriteLine(0, I, Size.X, 1, B);
  2741.   end;
  2742. end;
  2743.  
  2744. procedure TListViewer.FocusItem(Item: Integer);
  2745. begin
  2746.   Focused := Item;
  2747.   if VScrollBar <> nil then VScrollBar^.SetValue(Item);
  2748.   if Item < TopItem then
  2749.     if NumCols = 1 then TopItem := Item
  2750.     else TopItem := Item - Item mod Size.Y
  2751.   else if Item >= TopItem + (Size.Y*NumCols) then
  2752.     if NumCols = 1 then TopItem := Item - Size.Y + 1
  2753.     else TopItem := Item - Item mod Size.Y - (Size.Y*(NumCols - 1));
  2754. end;
  2755.  
  2756. procedure TListViewer.FocusItemNum(Item: Integer);
  2757. begin
  2758.   if Item < 0 then Item := 0
  2759.   else if (Item >= Range) and (Range > 0) then Item := Range-1;
  2760.   if Range <> 0 then FocusItem(Item);
  2761. end;
  2762.  
  2763. function TListViewer.GetPalette: PPalette;
  2764. const
  2765.   P: String[Length(CListViewer)] = CListViewer;
  2766. begin
  2767.   GetPalette := @P;
  2768. end;
  2769.  
  2770. function TListViewer.GetText(Item: Integer; MaxLen: Integer): String;
  2771. begin
  2772.   Abstract;
  2773. end;
  2774.  
  2775. function TListViewer.IsSelected(Item: Integer): Boolean;
  2776. begin
  2777.   IsSelected := Item = Focused;
  2778. end;
  2779.  
  2780. procedure TListViewer.HandleEvent(var Event: TEvent);
  2781. const
  2782.   MouseAutosToSkip = 4;
  2783. var
  2784.   Mouse: TPoint;
  2785.   ColWidth: Word;
  2786.   OldItem, NewItem: Integer;
  2787.   Count: Word;
  2788. begin
  2789.   TView.HandleEvent(Event);
  2790.   if Event.What = evMouseDown then
  2791.   begin
  2792.     ColWidth := Size.X div NumCols + 1;
  2793.     OldItem := Focused;
  2794.     MakeLocal(Event.Where, Mouse);
  2795.     if MouseInView(Event.Where) then
  2796.       NewItem := Mouse.Y + (Size.Y * (Mouse.X div ColWidth)) + TopItem
  2797.     else NewItem := OldItem;
  2798.     Count := 0;
  2799.     repeat
  2800.       if NewItem <> OldItem then
  2801.       begin
  2802.         FocusItemNum(NewItem);
  2803.         DrawView;
  2804.       end;
  2805.       OldItem := NewItem;
  2806.       MakeLocal(Event.Where, Mouse);
  2807.       if MouseInView(Event.Where) then
  2808.         NewItem := Mouse.Y + (Size.Y * (Mouse.X div ColWidth)) + TopItem
  2809.       else
  2810.       begin
  2811.         if NumCols = 1 then
  2812.         begin
  2813.           if Event.What = evMouseAuto then Inc(Count);
  2814.           if Count = MouseAutosToSkip then
  2815.           begin
  2816.             Count := 0;
  2817.             if Mouse.Y < 0 then NewItem := Focused-1
  2818.             else if Mouse.Y >= Size.Y then NewItem := Focused+1;
  2819.           end;
  2820.         end
  2821.         else
  2822.         begin
  2823.           if Event.What = evMouseAuto then Inc(Count);
  2824.           if Count = MouseAutosToSkip then
  2825.           begin
  2826.             Count := 0;
  2827.             if Mouse.X < 0 then NewItem := Focused-Size.Y
  2828.             else if Mouse.X >= Size.X then NewItem := Focused+Size.Y
  2829.             else if Mouse.Y < 0 then
  2830.               NewItem := Focused - Focused mod Size.Y
  2831.             else if Mouse.Y > Size.Y then
  2832.               NewItem := Focused - Focused mod Size.Y + Size.Y - 1;
  2833.           end
  2834.         end;
  2835.       end;
  2836.     until not MouseEvent(Event, evMouseMove + evMouseAuto);
  2837.     FocusItemNum(NewItem);
  2838.     DrawView;
  2839.     if Event.Double and (Range > Focused) then SelectItem(Focused);
  2840.     ClearEvent(Event);
  2841.   end
  2842.   else if Event.What = evKeyDown then
  2843.   begin
  2844.     if (Event.CharCode = ' ') and (Focused < Range) then
  2845.     begin
  2846.       SelectItem(Focused);
  2847.       NewItem := Focused;
  2848.     end
  2849.     else case CtrlToArrow(Event.KeyCode) of
  2850.       kbUp: NewItem := Focused - 1;
  2851.       kbDown: NewItem := Focused + 1;
  2852.       kbRight: if NumCols > 1 then NewItem := Focused + Size.Y else Exit;
  2853.       kbLeft: if NumCols > 1 then NewItem := Focused - Size.Y else Exit;
  2854.       kbPgDn: NewItem := Focused + Size.Y * NumCols;
  2855.       kbPgUp: NewItem := Focused - Size.Y * NumCols;
  2856.       kbHome: NewItem := TopItem;
  2857.       kbEnd: NewItem := TopItem + (Size.Y * NumCols) - 1;
  2858.       kbCtrlPgDn: NewItem := Range - 1;
  2859.       kbCtrlPgUp: NewItem := 0;
  2860.     else
  2861.       Exit;
  2862.     end;
  2863.     FocusItemNum(NewItem);
  2864.     DrawView;
  2865.     ClearEvent(Event);
  2866.   end else if Event.What = evBroadcast then
  2867.     if Options and ofSelectable <> 0 then
  2868.       if (Event.Command = cmScrollBarClicked) and
  2869.          ((Event.InfoPtr = HScrollBar) or (Event.InfoPtr = VScrollBar)) then
  2870.         Select
  2871.       else if (Event.Command = cmScrollBarChanged) then
  2872.       begin
  2873.         if (VScrollBar = Event.InfoPtr) then
  2874.         begin
  2875.           FocusItemNum(VScrollBar^.Value);
  2876.           DrawView;
  2877.         end else if (HScrollBar = Event.InfoPtr) then DrawView;
  2878.       end;
  2879. end;
  2880.  
  2881. procedure TListViewer.SelectItem(Item: Integer);
  2882. begin
  2883.   Message(Owner, evBroadcast, cmListItemSelected, @Self);
  2884. end;
  2885.  
  2886. procedure TListViewer.SetRange(ARange: Integer);
  2887. begin
  2888.   Range := ARange;
  2889.   if VScrollBar <> nil then
  2890.   begin
  2891.     if Focused > ARange then Focused := 0;
  2892.     VScrollbar^.SetParams(Focused, 0, ARange-1, VScrollBar^.PgStep,
  2893.       VScrollBar^.ArStep);
  2894.   end;
  2895. end;
  2896.  
  2897. procedure TListViewer.SetState(AState: Word; Enable: Boolean);
  2898.  
  2899. procedure ShowSBar(SBar: PScrollBar);
  2900. begin
  2901.   if (SBar <> nil) then
  2902.     if GetState(sfActive) and GetState(sfVisible) then SBar^.Show
  2903.     else SBar^.Hide;
  2904. end;
  2905.  
  2906. begin
  2907.   TView.SetState(AState, Enable);
  2908.   if AState and (sfSelected + sfActive + sfVisible) <> 0 then
  2909.   begin
  2910.     ShowSBar(HScrollBar);
  2911.     ShowSBar(VScrollBar);
  2912.     DrawView;
  2913.   end;
  2914. end;
  2915.  
  2916. procedure TListViewer.Store(var S: TStream);
  2917. begin
  2918.   TView.Store(S);
  2919.   PutPeerViewPtr(S, HScrollBar);
  2920.   PutPeerViewPtr(S, VScrollBar);
  2921.   S.Write(NumCols, SizeOf(Word) * 4);
  2922. end;
  2923.  
  2924. { TGroup }
  2925.  
  2926. constructor TGroup.Init(var Bounds: TRect);
  2927. begin
  2928.   TView.Init(Bounds);
  2929.   Options := Options or (ofSelectable + ofBuffered);
  2930.   GetExtent(Clip);
  2931.   EventMask := $FFFF;
  2932. end;
  2933.  
  2934. constructor TGroup.Load(var S: TStream);
  2935. var
  2936.   FixupSave: PFixupList;
  2937.   Count, I: Integer;
  2938.   P, Q: ^Pointer;
  2939.   V: PView;
  2940.   OwnerSave: PGroup;
  2941. begin
  2942.   TView.Load(S);
  2943.   GetExtent(Clip);
  2944.   OwnerSave := OwnerGroup;
  2945.   OwnerGroup := @Self;
  2946.   FixupSave := FixupList;
  2947.   S.Read(Count, SizeOf(Word));
  2948.   asm
  2949.         MOV     CX,Count
  2950.         SHL     CX,1
  2951.         SHL     CX,1
  2952.         SUB     SP,CX
  2953.         MOV     FixupList.Word[0],SP
  2954.         MOV     FixupList.Word[2],SS
  2955.         MOV     DI,SP
  2956.         PUSH    SS
  2957.         POP     ES
  2958.         XOR     AL,AL
  2959.         CLD
  2960.         REP     STOSB
  2961.   end;
  2962.   for I := 1 to Count do
  2963.   begin
  2964.     V := PView(S.Get);
  2965.     if V <> nil then InsertView(V, nil);
  2966.   end;
  2967.   V := Last;
  2968.   for I := 1 to Count do
  2969.   begin
  2970.     V := V^.Next;
  2971.     P := FixupList^[I];
  2972.     while P <> nil do
  2973.     begin
  2974.       Q := P;
  2975.       P := P^;
  2976.       Q^ := V;
  2977.     end;
  2978.   end;
  2979.   OwnerGroup := OwnerSave;
  2980.   FixupList := FixupSave;
  2981.   GetSubViewPtr(S, V);
  2982.   SetCurrent(V, NormalSelect);
  2983.   if OwnerGroup = nil then Awaken;
  2984. end;
  2985.  
  2986. destructor TGroup.Done;
  2987. var
  2988.   P, T: PView;
  2989. begin
  2990.   Hide;
  2991.   P := Last;
  2992.   if P <> nil then
  2993.   begin
  2994.     repeat
  2995.       P^.Hide;
  2996.       P := P^.Prev;
  2997.     until P = Last;
  2998.     repeat
  2999.       T := P^.Prev;
  3000.       Dispose(P, Done);
  3001.       P := T;
  3002.     until Last = nil;
  3003.   end;
  3004.   FreeBuffer;
  3005.   TView.Done;
  3006. end;
  3007.  
  3008. function TGroup.At(Index: Integer): PView; assembler;
  3009. asm
  3010.         LES     DI,Self
  3011.         LES     DI,ES:[DI].TGroup.Last
  3012.         MOV     CX,Index
  3013. @@1:    LES     DI,ES:[DI].TView.Next
  3014.         LOOP    @@1
  3015.         MOV     AX,DI
  3016.         MOV     DX,ES
  3017. end;
  3018.  
  3019. procedure TGroup.Awaken;
  3020.  
  3021.   procedure DoAwaken(P: PView); far;
  3022.   begin
  3023.     P^.Awaken;
  3024.   end;
  3025.  
  3026. begin
  3027.   ForEach(@DoAwaken);
  3028. end;
  3029.  
  3030. procedure TGroup.ChangeBounds(var Bounds: TRect);
  3031. var
  3032.   D: TPoint;
  3033.  
  3034. procedure DoCalcChange(P: PView); far;
  3035. var
  3036.   R: TRect;
  3037. begin
  3038.   P^.CalcBounds(R, D);
  3039.   P^.ChangeBounds(R);
  3040. end;
  3041.  
  3042. begin
  3043.   D.X := Bounds.B.X - Bounds.A.X - Size.X;
  3044.   D.Y := Bounds.B.Y - Bounds.A.Y - Size.Y;
  3045.   if Longint(D) = 0 then
  3046.   begin
  3047.     SetBounds(Bounds);
  3048.     DrawView;
  3049.   end else
  3050.   begin
  3051.     FreeBuffer;
  3052.     SetBounds(Bounds);
  3053.     GetExtent(Clip);
  3054.     GetBuffer;
  3055.     Lock;
  3056.     ForEach(@DoCalcChange);
  3057.     Unlock;
  3058.   end;
  3059. end;
  3060.  
  3061. function TGroup.DataSize: Word;
  3062. var
  3063.   T: Word;
  3064.  
  3065. procedure AddSubviewDataSize(P: PView); far;
  3066. begin
  3067.   Inc(T, P^.DataSize);
  3068. end;
  3069.  
  3070. begin
  3071.   T := 0;
  3072.   ForEach(@AddSubviewDataSize);
  3073.   DataSize := T;
  3074. end;
  3075.  
  3076. procedure TGroup.Delete(P: PView);
  3077. var
  3078.   SaveState: Word;
  3079. begin
  3080.   SaveState := P^.State;
  3081.   P^.Hide;
  3082.   RemoveView(P);
  3083.   P^.Owner := nil;
  3084.   P^.Next := nil;
  3085.   if SaveState and sfVisible <> 0 then P^.Show;
  3086. end;
  3087.  
  3088. procedure TGroup.Draw;
  3089. var
  3090.   R: TRect;
  3091. begin
  3092.   if Buffer = nil then
  3093.   begin
  3094.     GetBuffer;
  3095.     if Buffer <> nil then
  3096.     begin
  3097.       Inc(LockFlag);
  3098.       Redraw;
  3099.       Dec(LockFlag);
  3100.     end;
  3101.   end;
  3102.   if Buffer <> nil then WriteBuf(0, 0, Size.X, Size.Y, Buffer^) else
  3103.   begin
  3104.     GetClipRect(Clip);
  3105.     Redraw;
  3106.     GetExtent(Clip);
  3107.   end;
  3108. end;
  3109.  
  3110. procedure TGroup.DrawSubViews(P, Bottom: PView);
  3111. begin
  3112.   if P <> nil then
  3113.     while P <> Bottom do
  3114.     begin
  3115.       P^.DrawView;
  3116.       P := P^.NextView;
  3117.     end;
  3118. end;
  3119.  
  3120. procedure TGroup.EndModal(Command: Word);
  3121. begin
  3122.   if State and sfModal <> 0 then EndState := Command
  3123.   else TView.EndModal(Command);
  3124. end;
  3125.  
  3126. procedure TGroup.EventError(var Event: TEvent);
  3127. begin
  3128.   if Owner <> nil then Owner^.EventError(Event);
  3129. end;
  3130.  
  3131. function TGroup.Execute: Word;
  3132. var
  3133.   E: TEvent;
  3134. begin
  3135.   repeat
  3136.     EndState := 0;
  3137.     repeat
  3138.       GetEvent(E);
  3139.       HandleEvent(E);
  3140.       if E.What <> evNothing then EventError(E);
  3141.     until EndState <> 0;
  3142.   until Valid(EndState);
  3143.   Execute := EndState;
  3144. end;
  3145.  
  3146. function TGroup.ExecView(P: PView): Word;
  3147. var
  3148.   SaveOptions: Word;
  3149.   SaveOwner: PGroup;
  3150.   SaveTopView: PView;
  3151.   SaveCurrent: PView;
  3152.   SaveCommands: TCommandSet;
  3153. begin
  3154.   if P <> nil then
  3155.   begin
  3156.     SaveOptions := P^.Options;
  3157.     SaveOwner := P^.Owner;
  3158.     SaveTopView := TheTopView;
  3159.     SaveCurrent := Current;
  3160.     GetCommands(SaveCommands);
  3161.     TheTopView := P;
  3162.     P^.Options := P^.Options and not ofSelectable;
  3163.     P^.SetState(sfModal, True);
  3164.     SetCurrent(P, EnterSelect);
  3165.     if SaveOwner = nil then Insert(P);
  3166.     ExecView := P^.Execute;
  3167.     if SaveOwner = nil then Delete(P);
  3168.     SetCurrent(SaveCurrent, LeaveSelect);
  3169.     P^.SetState(sfModal, False);
  3170.     P^.Options := SaveOptions;
  3171.     TheTopView := SaveTopView;
  3172.     SetCommands(SaveCommands);
  3173.   end else ExecView := cmCancel;
  3174. end;
  3175.  
  3176. function TGroup.First: PView;
  3177. begin
  3178.   if Last = nil then First := nil else First := Last^.Next;
  3179. end;
  3180.  
  3181. function TGroup.FirstMatch(AState: Word; AOptions: Word): PView;
  3182.  
  3183. function Matches(P: PView): Boolean; far;
  3184. begin
  3185.   Matches := (P^.State and AState = AState) and
  3186.     (P^.Options and AOptions = AOptions);
  3187. end;
  3188.  
  3189. begin
  3190.   FirstMatch := FirstThat(@Matches);
  3191. end;
  3192.  
  3193. function TGroup.FirstThat(P: Pointer): PView; assembler;
  3194. var
  3195.   ALast: Pointer;
  3196. asm
  3197.         LES     DI,Self
  3198.         LES     DI,ES:[DI].TGroup.Last
  3199.         MOV     AX,ES
  3200.         OR      AX,DI
  3201.         JE      @@3
  3202.         MOV     WORD PTR ALast[2],ES
  3203.         MOV     WORD PTR ALast[0],DI
  3204. @@1:    LES     DI,ES:[DI].TView.Next
  3205.         PUSH    ES
  3206.         PUSH    DI
  3207.         PUSH    ES
  3208.         PUSH    DI
  3209.         PUSH    WORD PTR [BP]
  3210.         CALL    P
  3211.         POP     DI
  3212.         POP     ES
  3213.         OR      AL,AL
  3214.         JNE     @@2
  3215.         CMP     DI,WORD PTR ALast[0]
  3216.         JNE     @@1
  3217.         MOV     AX,ES
  3218.         CMP     AX,WORD PTR ALast[2]
  3219.         JNE     @@1
  3220.         XOR     DI,DI
  3221.         MOV     ES,DI
  3222. @@2:    MOV     SP,BP
  3223. @@3:    MOV     AX,DI
  3224.         MOV     DX,ES
  3225. end;
  3226.  
  3227. function TGroup.FindNext(Forwards: Boolean): PView;
  3228. var
  3229.   P: PView;
  3230. begin
  3231.   FindNext := nil;
  3232.   if Current <> nil then
  3233.   begin
  3234.     P := Current;
  3235.     repeat
  3236.       if Forwards then P := P^.Next else P := P^.Prev;
  3237.     until ((P^.State and (sfVisible + sfDisabled) = sfVisible) and
  3238.       (P^.Options and ofSelectable <> 0)) or (P = Current);
  3239.     if P <> Current then FindNext := P;
  3240.   end;
  3241. end;
  3242.  
  3243. function TGroup.FocusNext(Forwards: Boolean): Boolean;
  3244. var
  3245.   P: PView;
  3246. begin
  3247.   P := FindNext(Forwards);
  3248.   FocusNext := True;
  3249.   if P <> nil then FocusNext := P^.Focus;
  3250. end;
  3251.  
  3252. procedure TGroup.ForEach(P: Pointer); assembler;
  3253. var
  3254.   ALast: Pointer;
  3255. asm
  3256.         LES     DI,Self
  3257.         LES     DI,ES:[DI].TGroup.Last
  3258.         MOV     AX,ES
  3259.         OR      AX,DI
  3260.         JE      @@4
  3261.         MOV     WORD PTR ALast[2],ES
  3262.         MOV     WORD PTR ALast[0],DI
  3263.         LES     DI,ES:[DI].TView.Next
  3264. @@1:    CMP     DI,WORD PTR ALast[0]
  3265.         JNE     @@2
  3266.         MOV     AX,ES
  3267.         CMP     AX,WORD PTR ALast[2]
  3268.         JE      @@3
  3269. @@2:    PUSH    WORD PTR ES:[DI].TView.Next[2]
  3270.         PUSH    WORD PTR ES:[DI].TView.Next[0]
  3271.         PUSH    ES
  3272.         PUSH    DI
  3273.         PUSH    WORD PTR [BP]
  3274.         CALL    P
  3275.         POP     DI
  3276.         POP     ES
  3277.         JMP     @@1
  3278. @@3:    PUSH    WORD PTR [BP]
  3279.         CALL    P
  3280. @@4:
  3281. end;
  3282.  
  3283. procedure TGroup.FreeBuffer;
  3284. begin
  3285.   if (Options and ofBuffered <> 0) and (Buffer <> nil) then
  3286.     DisposeCache(Pointer(Buffer));
  3287. end;
  3288.  
  3289. { Allocate a group buffer if the group is exposed, buffered, and
  3290.   its area is less than 32768 bytes }
  3291.  
  3292. procedure TGroup.GetBuffer; assembler;
  3293. asm
  3294.     LES    DI,Self
  3295.         TEST    ES:[DI].State,sfExposed
  3296.         JZ    @@1
  3297.         TEST    ES:[DI].Options,ofBuffered
  3298.         JZ    @@1
  3299.         MOV    AX,ES:[DI].Buffer.Word[0]
  3300.         OR    AX,ES:[DI].Buffer.Word[2]
  3301.         JNZ    @@1
  3302.         MOV    AX,ES:[DI].TView.Size.X
  3303.     MUL    ES:[DI].TView.Size.Y
  3304.         JO    @@1
  3305.         SHL    AX,1
  3306.         JC    @@1
  3307.         JS    @@1
  3308.         LEA    DI,[DI].TView.Buffer
  3309.         PUSH    ES
  3310.         PUSH    DI
  3311.         PUSH    AX
  3312.         CALL    NewCache
  3313. @@1:
  3314. end;
  3315.  
  3316. procedure TGroup.GetData(var Rec);
  3317. type
  3318.   Bytes = array[0..65534] of Byte;
  3319. var
  3320.   I: Word;
  3321.   V: PView;
  3322. begin
  3323.   I := 0;
  3324.   if Last <> nil then
  3325.   begin
  3326.     V := Last;
  3327.     repeat
  3328.       V^.GetData(Bytes(Rec)[I]);
  3329.       Inc(I, V^.DataSize);
  3330.       V := V^.Prev;
  3331.     until V = Last;
  3332.   end;
  3333. end;
  3334.  
  3335. function TGroup.GetHelpCtx: Word;
  3336. var
  3337.   H: Word;
  3338. begin
  3339.   H:= hcNoContext;
  3340.   if Current <> nil then H := Current^.GetHelpCtx;
  3341.   if H = hcNoContext then H := TView.GetHelpCtx;
  3342.   GetHelpCtx := H;
  3343. end;
  3344.  
  3345. procedure TGroup.GetSubViewPtr(var S: TStream; var P);
  3346. var
  3347.   Index: Word;
  3348. begin
  3349.   S.Read(Index, SizeOf(Word));
  3350.   if Index > 0 then
  3351.     Pointer(P) := At(Index)
  3352.   else
  3353.     Pointer(P) := nil;
  3354. end;
  3355.  
  3356. procedure TGroup.HandleEvent(var Event: TEvent);
  3357.  
  3358. procedure DoHandleEvent(P: PView); far;
  3359. begin
  3360.   if (P = nil) or ((P^.State and sfDisabled <> 0)
  3361.     and (Event.What and (PositionalEvents or FocusedEvents) <> 0)) then Exit;
  3362.   case Phase of
  3363.     phPreProcess: if P^.Options and ofPreProcess = 0 then Exit;
  3364.     phPostProcess: if P^.Options and ofPostProcess = 0 then Exit;
  3365.   end;
  3366.   if Event.What and P^.EventMask <> 0 then P^.HandleEvent(Event);
  3367. end;
  3368.  
  3369. function ContainsMouse(P: PView): Boolean; far;
  3370. begin
  3371.   ContainsMouse := (P^.State and sfVisible <> 0) and
  3372.     P^.MouseInView(Event.Where);
  3373. end;
  3374.  
  3375. begin
  3376.   TView.HandleEvent(Event);
  3377.   if Event.What and FocusedEvents <> 0 then
  3378.   begin
  3379.     Phase := phPreProcess;
  3380.     ForEach(@DoHandleEvent);
  3381.     Phase := phFocused;
  3382.     DoHandleEvent(Current);
  3383.     Phase := phPostProcess;
  3384.     ForEach(@DoHandleEvent);
  3385.   end else
  3386.   begin
  3387.     Phase := phFocused;
  3388.     if (Event.What and PositionalEvents <> 0) then
  3389.       DoHandleEvent(FirstThat(@ContainsMouse)) else
  3390.       ForEach(@DoHandleEvent);
  3391.   end;
  3392. end;
  3393.  
  3394. function TGroup.IndexOf(P: PView): Integer; assembler;
  3395. asm
  3396.         LES     DI,Self
  3397.         LES     DI,ES:[DI].TGroup.Last
  3398.         MOV     AX,ES
  3399.         OR      AX,DI
  3400.         JE      @@3
  3401.         MOV     CX,DI
  3402.         MOV     BX,ES
  3403.         XOR     AX,AX
  3404. @@1:    INC     AX
  3405.         LES     DI,ES:[DI].TView.Next
  3406.         MOV     DX,ES
  3407.         CMP     DI,P.Word[0]
  3408.         JNE     @@2
  3409.         CMP     DX,P.Word[2]
  3410.         JE      @@3
  3411. @@2:    CMP     DI,CX
  3412.         JNE     @@1
  3413.         CMP     DX,BX
  3414.         JNE     @@1
  3415.         XOR     AX,AX
  3416. @@3:
  3417. end;
  3418.  
  3419. procedure TGroup.Insert(P: PView);
  3420. begin
  3421.   InsertBefore(P, First);
  3422. end;
  3423.  
  3424. procedure TGroup.InsertBefore(P, Target: PView);
  3425. var
  3426.   SaveState: Word;
  3427. begin
  3428.   if (P <> nil) and (P^.Owner = nil) and
  3429.     ((Target = nil) or (Target^.Owner = @Self)) then
  3430.   begin
  3431.     if P^.Options and ofCenterX <> 0 then
  3432.       P^.Origin.X := (Size.X - P^.Size.X) div 2;
  3433.     if P^.Options and ofCenterY <> 0 then
  3434.       P^.Origin.Y := (Size.Y - P^.Size.Y) div 2;
  3435.     SaveState := P^.State;
  3436.     P^.Hide;
  3437.     InsertView(P, Target);
  3438.     if SaveState and sfVisible <> 0 then P^.Show;
  3439.     if State and sfActive <> 0 then
  3440.       P^.SetState(sfActive, True);
  3441.   end;
  3442. end;
  3443.  
  3444. procedure TGroup.InsertView(P, Target: PView);
  3445. begin
  3446.   P^.Owner := @Self;
  3447.   if Target <> nil then
  3448.   begin
  3449.     Target := Target^.Prev;
  3450.     P^.Next := Target^.Next;
  3451.     Target^.Next := P;
  3452.   end else
  3453.   begin
  3454.     if Last = nil then P^.Next := P else
  3455.     begin
  3456.       P^.Next := Last^.Next;
  3457.       Last^.Next := P;
  3458.     end;
  3459.     Last := P;
  3460.   end;
  3461. end;
  3462.  
  3463. procedure TGroup.Lock;
  3464. begin
  3465.   if (Buffer <> nil) or (LockFlag <> 0) then Inc(LockFlag);
  3466. end;
  3467.  
  3468. procedure TGroup.PutSubViewPtr(var S: TStream; P: PView);
  3469. var
  3470.   Index: Word;
  3471. begin
  3472.   if P = nil then Index := 0
  3473.   else Index := IndexOf(P);
  3474.   S.Write(Index, SizeOf(Word));
  3475. end;
  3476.  
  3477. procedure TGroup.Redraw;
  3478. begin
  3479.   DrawSubViews(First, nil);
  3480. end;
  3481.  
  3482. procedure TGroup.RemoveView(P: PView); assembler;
  3483. asm
  3484.         PUSH    DS
  3485.         LDS     SI,Self
  3486.         LES     DI,P
  3487.         LDS     SI,DS:[SI].TGroup.Last
  3488.         PUSH    BP
  3489.         MOV     AX,DS
  3490.         OR      AX,SI
  3491.         JE      @@7
  3492.         MOV     AX,SI
  3493.         MOV     DX,DS
  3494.         MOV     BP,ES
  3495. @@1:    MOV     BX,WORD PTR DS:[SI].TView.Next[0]
  3496.         MOV     CX,WORD PTR DS:[SI].TView.Next[2]
  3497.         CMP     CX,BP
  3498.         JE      @@5
  3499. @@2:    CMP     CX,DX
  3500.         JE      @@4
  3501. @@3:    MOV     SI,BX
  3502.         MOV     DS,CX
  3503.         JMP     @@1
  3504. @@4:    CMP     BX,AX
  3505.         JNE     @@3
  3506.         JMP     @@7
  3507. @@5:    CMP     BX,DI
  3508.         JNE     @@2
  3509.         MOV     BX,WORD PTR ES:[DI].TView.Next[0]
  3510.         MOV     CX,WORD PTR ES:[DI].TView.Next[2]
  3511.         MOV     DS:WORD PTR [SI].TView.Next[0],BX
  3512.         MOV     DS:WORD PTR [SI].TView.Next[2],CX
  3513.         CMP     DX,BP
  3514.         JNE     @@7
  3515.         CMP     AX,DI
  3516.         JNE     @@7
  3517.         CMP     CX,BP
  3518.         JNE     @@6
  3519.         CMP     BX,DI
  3520.         JNE     @@6
  3521.         XOR     SI,SI
  3522.         MOV     DS,SI
  3523. @@6:    POP     BP
  3524.         PUSH    BP
  3525.         LES     DI,Self
  3526.         MOV     WORD PTR ES:[DI].TView.Last[0],SI
  3527.         MOV     WORD PTR ES:[DI].TView.Last[2],DS
  3528. @@7:    POP     BP
  3529.         POP     DS
  3530. end;
  3531.  
  3532. procedure TGroup.ResetCurrent;
  3533. begin
  3534.   SetCurrent(FirstMatch(sfVisible, ofSelectable), NormalSelect);
  3535. end;
  3536.  
  3537. procedure TGroup.ResetCursor;
  3538. begin
  3539.   if Current <> nil then Current^.ResetCursor;
  3540. end;
  3541.  
  3542. procedure TGroup.SelectNext(Forwards: Boolean);
  3543. var
  3544.   P: PView;
  3545. begin
  3546.   P := FindNext(Forwards);
  3547.   if P <> nil then P^.Select;
  3548. end;
  3549.  
  3550. procedure TGroup.SetCurrent(P: PView; Mode: SelectMode);
  3551.  
  3552. procedure SelectView(P: PView; Enable: Boolean);
  3553. begin
  3554.   if P <> nil then P^.SetState(sfSelected, Enable);
  3555. end;
  3556.  
  3557. procedure FocusView(P: PView; Enable: Boolean);
  3558. begin
  3559.   if (State and sfFocused <> 0) and (P <> nil) then
  3560.     P^.SetState(sfFocused, Enable);
  3561. end;
  3562.  
  3563. begin
  3564.   if Current <> P then
  3565.   begin
  3566.     Lock;
  3567.     FocusView(Current, False);
  3568.     if Mode <> EnterSelect then SelectView(Current, False);
  3569.     if Mode <> LeaveSelect then SelectView(P, True);
  3570.     FocusView(P, True);
  3571.     Current := P;
  3572.     Unlock;
  3573.   end;
  3574. end;
  3575.  
  3576. procedure TGroup.SetData(var Rec);
  3577. type
  3578.   Bytes = array[0..65534] of Byte;
  3579. var
  3580.   I: Word;
  3581.   V: PView;
  3582. begin
  3583.   I := 0;
  3584.   if Last <> nil then
  3585.   begin
  3586.     V := Last;
  3587.     repeat
  3588.       V^.SetData(Bytes(Rec)[I]);
  3589.       Inc(I, V^.DataSize);
  3590.       V := V^.Prev;
  3591.     until V = Last;
  3592.   end;
  3593. end;
  3594.  
  3595. procedure TGroup.SetState(AState: Word; Enable: Boolean);
  3596.  
  3597. procedure DoSetState(P: PView); far;
  3598. begin
  3599.   P^.SetState(AState, Enable);
  3600. end;
  3601.  
  3602. procedure DoExpose(P: PView); far;
  3603. begin
  3604.   if P^.State and sfVisible <> 0 then P^.SetState(sfExposed, Enable);
  3605. end;
  3606.  
  3607. begin
  3608.   TView.SetState(AState, Enable);
  3609.   case AState of
  3610.     sfActive, sfDragging:
  3611.       begin
  3612.         Lock;
  3613.         ForEach(@DoSetState);
  3614.         Unlock;
  3615.       end;
  3616.     sfFocused:
  3617.       if Current <> nil then Current^.SetState(sfFocused, Enable);
  3618.     sfExposed:
  3619.       begin
  3620.         ForEach(@DoExpose);
  3621.         if not Enable then FreeBuffer;
  3622.       end;
  3623.   end;
  3624. end;
  3625.  
  3626. procedure TGroup.Store(var S: TStream);
  3627. var
  3628.   Count: Integer;
  3629.   OwnerSave: PGroup;
  3630.  
  3631. procedure DoPut(P: PView); far;
  3632. begin
  3633.   S.Put(P);
  3634. end;
  3635.  
  3636. begin
  3637.   TView.Store(S);
  3638.   OwnerSave := OwnerGroup;
  3639.   OwnerGroup := @Self;
  3640.   Count := IndexOf(Last);
  3641.   S.Write(Count, SizeOf(Word));
  3642.   ForEach(@DoPut);
  3643.   PutSubViewPtr(S, Current);
  3644.   OwnerGroup := OwnerSave;
  3645. end;
  3646.  
  3647. procedure TGroup.Unlock;
  3648. begin
  3649.   if LockFlag <> 0 then
  3650.   begin
  3651.     Dec(LockFlag);
  3652.     if LockFlag = 0 then DrawView;
  3653.   end;
  3654. end;
  3655.  
  3656. function TGroup.Valid(Command: Word): Boolean;
  3657.  
  3658. function IsInvalid(P: PView): Boolean; far;
  3659. begin
  3660.   IsInvalid := not P^.Valid(Command);
  3661. end;
  3662.  
  3663. begin
  3664.   Valid := True;
  3665.   if Command = cmReleasedFocus then
  3666.   begin
  3667.     if (Current <> nil) and (Current^.Options and ofValidate <> 0) then
  3668.       Valid := Current^.Valid(Command);
  3669.   end
  3670.   else
  3671.     Valid := FirstThat(@IsInvalid) = nil;
  3672. end;
  3673.  
  3674. { TWindow }
  3675.  
  3676. constructor TWindow.Init(var Bounds: TRect; ATitle: TTitleStr;
  3677.   ANumber: Integer);
  3678. begin
  3679.   TGroup.Init(Bounds);
  3680.   State := State or sfShadow;
  3681.   Options := Options or (ofSelectable + ofTopSelect);
  3682.   GrowMode := gfGrowAll + gfGrowRel;
  3683.   Flags := wfMove + wfGrow + wfClose + wfZoom;
  3684.   Title := NewStr(ATitle);
  3685.   Number := ANumber;
  3686.   Palette := wpBlueWindow;
  3687.   InitFrame;
  3688.   if Frame <> nil then Insert(Frame);
  3689.   GetBounds(ZoomRect);
  3690. end;
  3691.  
  3692. constructor TWindow.Load(var S: TStream);
  3693. begin
  3694.   TGroup.Load(S);
  3695.   S.Read(Flags, SizeOf(Byte) + SizeOf(TRect) + 2 * SizeOf(Integer));
  3696.   GetSubViewPtr(S, Frame);
  3697.   Title := S.ReadStr;
  3698. end;
  3699.  
  3700. destructor TWindow.Done;
  3701. begin
  3702.   TGroup.Done;
  3703.   DisposeStr(Title);
  3704. end;
  3705.  
  3706. procedure TWindow.Close;
  3707. begin
  3708.   if Valid(cmClose) then Free;
  3709. end;
  3710.  
  3711. function TWindow.GetPalette: PPalette;
  3712. const
  3713.   P: array[wpBlueWindow..wpGrayWindow] of string[Length(CBlueWindow)] =
  3714.     (CBlueWindow, CCyanWindow, CGrayWindow);
  3715. begin
  3716.   GetPalette := @P[Palette];
  3717. end;
  3718.  
  3719. function TWindow.GetTitle(MaxSize: Integer): TTitleStr;
  3720. begin
  3721.   if Title <> nil then GetTitle := Title^
  3722.   else GetTitle := '';
  3723. end;
  3724.  
  3725. procedure TWindow.HandleEvent(var Event: TEvent);
  3726. var
  3727.   Limits: TRect;
  3728.   Min, Max: TPoint;
  3729. begin
  3730.   TGroup.HandleEvent(Event);
  3731.   if (Event.What = evCommand) then
  3732.     case Event.Command of
  3733.       cmResize:
  3734.         if Flags and (wfMove + wfGrow) <> 0 then
  3735.         begin
  3736.           Owner^.GetExtent(Limits);
  3737.           SizeLimits(Min, Max);
  3738.           DragView(Event, DragMode or (Flags and (wfMove + wfGrow)),
  3739.             Limits, Min, Max);
  3740.           ClearEvent(Event);
  3741.         end;
  3742.       cmClose:
  3743.         if (Flags and wfClose <> 0) and
  3744.           ((Event.InfoPtr = nil) or (Event.InfoPtr = @Self)) then
  3745.         begin
  3746.           ClearEvent(Event);
  3747.           if State and sfModal = 0 then Close else
  3748.           begin
  3749.             Event.What := evCommand;
  3750.             Event.Command := cmCancel;
  3751.             PutEvent(Event);
  3752.             ClearEvent(Event);
  3753.           end;
  3754.         end;
  3755.       cmZoom:
  3756.         if (Flags and wfZoom <> 0) and
  3757.           ((Event.InfoPtr = nil) or (Event.InfoPtr = @Self)) then
  3758.         begin
  3759.           Zoom;
  3760.           ClearEvent(Event);
  3761.         end;
  3762.     end
  3763.   else if Event.What = evKeyDown then
  3764.     case Event.KeyCode of
  3765.       kbTab:
  3766.         begin
  3767.           FocusNext(False);
  3768.           ClearEvent(Event);
  3769.         end;
  3770.       kbShiftTab:
  3771.         begin
  3772.           FocusNext(True);
  3773.           ClearEvent(Event);
  3774.         end;
  3775.       else
  3776.         if GetAltChar(Event.KeyCode) = #240 then
  3777.           if Message(Frame, evBroadcast, cmWindowMenu, nil) <> nil then
  3778.             ClearEvent(Event);
  3779.     end
  3780.   else if (Event.What = evBroadcast) and (Event.Command = cmSelectWindowNum)
  3781.          and (Event.InfoInt = Number) and (Options and ofSelectable <> 0) then
  3782.   begin
  3783.     Select;
  3784.     ClearEvent(Event);
  3785.   end;
  3786. end;
  3787.  
  3788. procedure TWindow.InitFrame;
  3789. var
  3790.   R: TRect;
  3791. begin
  3792.   GetExtent(R);
  3793.   Frame := New(PFrame, Init(R));
  3794. end;
  3795.  
  3796. procedure TWindow.SetState(AState: Word; Enable: Boolean);
  3797. var
  3798.   WindowCommands: TCommandSet;
  3799. begin
  3800.   TGroup.SetState(AState, Enable);
  3801.   if AState = sfSelected then
  3802.     SetState(sfActive, Enable);
  3803.   if (AState = sfSelected) or ((AState = sfExposed) and
  3804.     (State and sfSelected <> 0)) then
  3805.   begin
  3806.     WindowCommands := [cmNext, cmPrev];
  3807.     if Flags and wfGrow + wfMove <> 0 then
  3808.       WindowCommands := WindowCommands + [cmResize];
  3809.     if Flags and wfClose <> 0 then
  3810.       WindowCommands := WindowCommands + [cmClose];
  3811.     if Flags and wfZoom <> 0 then
  3812.       WindowCommands := WindowCommands + [cmZoom];
  3813.     if Enable then EnableCommands(WindowCommands)
  3814.     else DisableCommands(WindowCommands);
  3815.   end;
  3816. end;
  3817.  
  3818. function TWindow.StandardScrollBar(AOptions: Word): PScrollBar;
  3819. var
  3820.   R: TRect;
  3821.   S: PScrollBar;
  3822. begin
  3823.   GetExtent(R);
  3824.   if AOptions and sbVertical = 0 then
  3825.     R.Assign(R.A.X, R.B.Y-1, R.B.X-2, R.B.Y) else
  3826.     R.Assign(R.B.X-2,R.A.Y+1,R.B.X,R.B.Y-1);
  3827.   S := New(PScrollBar, Init(R));
  3828.   Insert(S);
  3829.   if AOptions and sbHandleKeyboard <> 0 then
  3830.     S^.Options := S^.Options or ofPostProcess;
  3831.   StandardScrollBar := S;
  3832.   Flags := Flags or wfBottomLine;
  3833. end;
  3834.  
  3835. procedure TWindow.SizeLimits(var Min, Max: TPoint);
  3836. begin
  3837.   TView.SizeLimits(Min, Max);
  3838.   Min.X := MinWinSize.X;
  3839.   Min.Y := MinWinSize.Y;
  3840. end;
  3841.  
  3842. procedure TWindow.Store(var S: TStream);
  3843. begin
  3844.   TGroup.Store(S);
  3845.   S.Write(Flags, SizeOf(Byte) + SizeOf(TRect) + 2 * SizeOf(Integer));
  3846.   PutSubViewPtr(S, Frame);
  3847.   S.WriteStr(Title);
  3848. end;
  3849.  
  3850. procedure TWindow.Zoom;
  3851. var
  3852.   R: TRect;
  3853.   Max, Min: TPoint;
  3854. begin
  3855.   SizeLimits(Min, Max);
  3856.   if Longint(Size) <> Longint(Max) then
  3857.   begin
  3858.     GetBounds(ZoomRect);
  3859.     Longint(R.A) := 0;
  3860.     R.B := Max;
  3861.     Locate(R);
  3862.   end else Locate(ZoomRect);
  3863. end;
  3864.  
  3865. { Message dispatch function }
  3866.  
  3867. function Message(Receiver: PView; What, Command: Word;
  3868.   InfoPtr: Pointer): Pointer;
  3869. var
  3870.   Event: TEvent;
  3871. begin
  3872.   Message := nil;
  3873.   if Receiver <> nil then
  3874.   begin
  3875.     Event.What := What;
  3876.     Event.Command := Command;
  3877.     Event.InfoPtr := InfoPtr;
  3878.     Receiver^.HandleEvent(Event);
  3879.     if Event.What = evNothing then Message := Event.InfoPtr;
  3880.   end;
  3881. end;
  3882.  
  3883. { Views registration procedure }
  3884.  
  3885. procedure RegisterViews;
  3886. begin
  3887.   RegisterType(RView);
  3888.   RegisterType(RFrame);
  3889.   RegisterType(RScrollBar);
  3890.   RegisterType(RScroller);
  3891.   RegisterType(RListViewer);
  3892.   RegisterType(RGroup);
  3893.   RegisterType(RWindow);
  3894. end;
  3895.  
  3896. procedure InvertColor(var Color: Byte);
  3897. begin
  3898.   Color := ((Color and $F0) shr 4) or ((Color and $0F) shl 4);
  3899. end;
  3900.  
  3901. end.
  3902.