home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TVG110.ZIP / T6DEMSRC.ZIP / TVDEMO.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1993-02-22  |  17.6 KB  |  640 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Pascal 6.0                             }
  4. {   Turbo Vision Demo                            }
  5. {   Copyright (c) 1990 by Borland International  }
  6. {                                                }
  7. {************************************************}
  8.  
  9. program TVDemo;
  10.  
  11. {$X+,S-}
  12. {$M 16384,8192,655360}
  13.  
  14. { Turbo Vision demo program. This program uses many of the Turbo
  15.   Vision standard and demo units, including:
  16.  
  17.     StdDlg    - Open file browser, change directory tree.
  18.     MsgBox    - Simple dialog to display messages.
  19.     ColorSel  - Color customization.
  20.     Gadgets   - Shows system time and available heap space.
  21.     AsciiTab  - ASCII table.
  22.     Calendar  - View a month at a time
  23.     Calc      - Desktop calculator.
  24.     FViewer   - Scroll through text files.
  25.     HelpFile  - Context sensitive help.
  26.     MouseDlg  - Mouse options dialog.
  27.     Puzzle    - Simple brain puzzle.
  28.  
  29.   And of course this program includes many standard Turbo Vision
  30.   objects and behaviors (menubar, desktop, status line, dialog boxes,
  31.   mouse support, window resize/move/tile/cascade).
  32. }
  33.  
  34. uses
  35.   TVGraph, TVGDefs, TVGWhiz, Styx,                    (*** TVGRAPH ***)
  36.   Dos, Objects, Drivers, Memory, Views, Menus, Dialogs, StdDlg, MsgBox, App,
  37.   DemoCmds, Gadgets, Puzzle, Calendar, AsciiTab, Calc, FViewer, HelpFile,
  38.   DemoHelp, ColorSel, MouseDlg;
  39.  
  40. type
  41.  
  42.   { TTVDemo }
  43.  
  44.   PTVDemo = ^TTVDemo;
  45.   TTVDemo = object(TVGApp)                            (*** TVGRAPH ***)
  46.     Clock: PClockView;
  47.     Heap: PHeapView;
  48.     constructor Init;
  49.     procedure FileOpen(WildCard: PathStr);
  50.     procedure GetEvent(var Event: TEvent); virtual;
  51.     function GetPalette: PPalette; virtual;
  52.     procedure HandleEvent(var Event: TEvent); virtual;
  53.     procedure Idle; virtual;
  54.     procedure InitMenuBar; virtual;
  55.     procedure InitStatusLine; virtual;
  56.     procedure LoadDesktop(var S: TStream);
  57.     procedure OutOfMemory; virtual;
  58.     procedure StoreDesktop(var S: TStream);
  59.     procedure ViewFile(FileName: PathStr);
  60.   end;
  61.  
  62. { CalcHelpName }
  63.  
  64. function CalcHelpName: PathStr;
  65. var
  66.   EXEName: PathStr;
  67.   Dir: DirStr;
  68.   Name: NameStr;
  69.   Ext: ExtStr;
  70. begin
  71.   if Lo(DosVersion) >= 3 then EXEName := ParamStr(0)
  72.   else EXEName := FSearch('TVDEMO.EXE', GetEnv('PATH'));
  73.   FSplit(EXEName, Dir, Name, Ext);
  74.   if Dir[Length(Dir)] = '\' then Dec(Dir[0]);
  75.   CalcHelpName := FSearch('DEMOHELP.HLP', Dir);
  76. end;
  77.  
  78.  
  79. { TTVDemo }
  80. constructor TTVDemo.Init;
  81. var
  82.   R: TRect;
  83.   I: Integer;
  84.   FileName: PathStr;
  85. begin
  86.   BGIPath:='D:\BP\UNITS6';                      (*** TVGRAPH ***)
  87.   TVGApp.Init;                                  (*** TVGRAPH ***)
  88.   ShadowSize.X:=0;
  89.   ShadowSize.Y:=0;
  90.   RegisterObjects;
  91.   RegisterViews;
  92.   RegisterMenus;
  93.   RegisterDialogs;
  94.   RegisterApp;
  95.   RegisterHelpFile;
  96.   RegisterPuzzle;
  97.   RegisterCalendar;
  98.   RegisterAsciiTab;
  99.   RegisterCalc;
  100.   RegisterFViewer;
  101.   RegisterStyx;                                 (*** TVGRAPH ***)
  102.  
  103.   GetExtent(R);
  104.   R.A.X := R.B.X - 9; R.B.Y := R.A.Y + 1;
  105.   Clock := New(PClockView, Init(R));
  106.   Insert(Clock);
  107.  
  108.   GetExtent(R);
  109.   Dec(R.B.X);
  110.   R.A.X := R.B.X - 9; R.A.Y := R.B.Y - 1;
  111.   Heap := New(PHeapView, Init(R));
  112.   Insert(Heap);
  113.  
  114.   for I := 1 to ParamCount do
  115.   begin
  116.     FileName := ParamStr(I);
  117.     if FileName[Length(FileName)] = '\' then
  118.       FileName := FileName + '*.*';
  119.     if (Pos('?', FileName) = 0) and (Pos('*', FileName) = 0) then
  120.       ViewFile(FExpand(FileName))
  121.     else FileOpen(FileName);
  122.   end;
  123.  
  124. end;
  125.  
  126. procedure TTVDemo.FileOpen(WildCard: PathStr);
  127. var
  128.   D: PFileDialog;
  129.   FileName: PathStr;
  130. begin
  131.   D := New(PFileDialog, Init(WildCard, 'Open a File',
  132.     '~N~ame', fdOpenButton + fdHelpButton, 100));
  133.   D^.HelpCtx := hcFOFileOpenDBox;
  134.   if ValidView(D) <> nil then
  135.   begin
  136.     if Desktop^.ExecView(D) <> cmCancel then
  137.     begin
  138.       D^.GetFileName(FileName);
  139.       ViewFile(FileName);
  140.     end;
  141.     Dispose(D, Done);
  142.   end;
  143. end;
  144.  
  145. procedure TTVDemo.GetEvent(var Event: TEvent);
  146. var
  147.   W: PWindow;
  148.   HFile: PHelpFile;
  149.   HelpStrm: PDosStream;
  150. const
  151.   HelpInUse: Boolean = False;
  152. begin
  153.   TVGApp.GetEvent(Event);                               (*** TVGRAPH ***)
  154.   case Event.What of
  155.     evCommand:
  156.       if (Event.Command = cmHelp) and not HelpInUse then
  157.       begin
  158.         HelpInUse := True;
  159.         HelpStrm := New(PDosStream, Init(CalcHelpName, stOpenRead));
  160.         HFile := New(PHelpFile, Init(HelpStrm));
  161.         if HelpStrm^.Status <> stOk then
  162.         begin
  163.           MessageBox('Could not open help file.', nil, mfError + mfOkButton);
  164.           Dispose(HFile, Done);
  165.         end
  166.         else
  167.         begin
  168.           W := New(PHelpWindow,Init(HFile, GetHelpCtx));
  169.           if ValidView(W) <> nil then
  170.           begin
  171.             ExecView(W);
  172.             Dispose(W, Done);
  173.           end;
  174.           ClearEvent(Event);
  175.         end;
  176.         HelpInUse := False;
  177.       end;
  178.     evMouseDown:
  179.       if Event.Buttons <> 1 then Event.What := evNothing;
  180.   end;
  181. end;
  182.  
  183. function TTVDemo.GetPalette: PPalette;
  184. const
  185.   CNewColor = CColor + CHelpColor;
  186.   CNewBlackWhite = CBlackWhite + CHelpBlackWhite;
  187.   CNewMonochrome = CMonochrome + CHelpMonochrome;
  188.   P: array[apColor..apMonochrome] of string[Length(CNewColor)] =
  189.     (CNewColor, CNewBlackWhite, CNewMonochrome);
  190. begin
  191.   GetPalette := @P[AppPalette];
  192. end;
  193.  
  194. procedure TTVDemo.HandleEvent(var Event: TEvent);
  195.  
  196. procedure ChangeDir;
  197. var
  198.   D: PChDirDialog;
  199. begin
  200.   D := New(PChDirDialog, Init(cdNormal + cdHelpButton, 101));
  201.   D^.HelpCtx := hcFCChDirDBox;
  202.   if ValidView(D) <> nil then
  203.   begin
  204.     DeskTop^.ExecView(D);
  205.     Dispose(D, Done);
  206.   end;
  207. end;
  208.  
  209. procedure Tile;
  210. var
  211.   R: TRect;
  212. begin
  213.   Desktop^.GetExtent(R);
  214.   Desktop^.Tile(R);
  215. end;
  216.  
  217. procedure Cascade;
  218. var
  219.   R: TRect;
  220. begin
  221.   Desktop^.GetExtent(R);
  222.   Desktop^.Cascade(R);
  223. end;
  224.  
  225. procedure Puzzle;
  226. var
  227.   P: PPuzzleWindow;
  228. begin
  229.   P := New(PPuzzleWindow, Init);
  230.   P^.HelpCtx := hcPuzzle;
  231.   Desktop^.Insert(ValidView(P));
  232. end;
  233.  
  234. procedure Calendar;
  235. var
  236.   P: PCalendarWindow;
  237. begin
  238.   P := New(PCalendarWindow, Init);
  239.   P^.HelpCtx := hcCalendar;
  240.   Desktop^.Insert(ValidView(P));
  241. end;
  242.  
  243. procedure About;
  244. var
  245.   D: PDialog;
  246.   Control: PView;
  247.   R: TRect;
  248. begin
  249.   R.Assign(0, 0, 40, 11);
  250.   D := New(PDialog, Init(R, 'About'));
  251.   with D^ do
  252.   begin
  253.     Options := Options or ofCentered;
  254.  
  255.     R.Grow(-1, -1);
  256.     Dec(R.B.Y, 3);
  257.     Insert(New(PStaticText, Init(R,
  258.       #13 +
  259.       ^C'Turbo Vision Demo'#13 +
  260.       #13 +
  261.       ^C'Copyright (c) 1990'#13 +
  262.       #13 +
  263.       ^C'Borland International')));
  264.  
  265.     R.Assign(15, 8, 25, 10);
  266.     Insert(New(PButton, Init(R, 'O~K', cmOk, bfDefault)));
  267.   end;
  268.   if ValidView(D) <> nil then
  269.   begin
  270.     Desktop^.ExecView(D);
  271.     Dispose(D, Done);
  272.   end;
  273. end;
  274.  
  275. procedure AsciiTab;
  276. var
  277.   P: PAsciiChart;
  278. begin
  279.   P := New(PAsciiChart, Init);
  280.   P^.HelpCtx := hcAsciiTable;
  281.   Desktop^.Insert(ValidView(P));
  282. end;
  283.  
  284. procedure OpenStyx;                                        (*** TVGRAPH ***)
  285. var                                                        (*** TVGRAPH ***)
  286.   P: PStyxDemo;                                            (*** TVGRAPH ***)
  287. begin                                                      (*** TVGRAPH ***)
  288.   P := New(PStyxDemo, Init);                               (*** TVGRAPH ***)
  289.   P^.HelpCtx := hcNoContext;                               (*** TVGRAPH ***)
  290.   Desktop^.Insert(ValidView(P));                           (*** TVGRAPH ***)
  291. end;                                                       (*** TVGRAPH ***)
  292.  
  293. procedure Calculator;
  294. var
  295.   P: PCalculator;
  296. begin
  297.   P := New(PCalculator, Init);
  298.   P^.HelpCtx := hcCalculator;
  299.   if ValidView(P) <> nil then
  300.     Desktop^.Insert(P);
  301. end;
  302.  
  303. procedure Colors;
  304. var
  305.   D: PColorDialog;
  306. begin
  307.   D := New(PColorDialog, Init('',
  308.     ColorGroup('Desktop',
  309.       ColorItem('Color',             32, nil),
  310.     ColorGroup('Menus',
  311.       ColorItem('Normal',            2,
  312.       ColorItem('Disabled',          3,
  313.       ColorItem('Shortcut',          4,
  314.       ColorItem('Selected',          5,
  315.       ColorItem('Selected disabled', 6,
  316.       ColorItem('Shortcut selected', 7, nil)))))),
  317.     ColorGroup('Dialogs/Calc',
  318.       ColorItem('Frame/background',  33,
  319.       ColorItem('Frame icons',       34,
  320.       ColorItem('Scroll bar page',   35,
  321.       ColorItem('Scroll bar icons',  36,
  322.       ColorItem('Static text',       37,
  323.  
  324.       ColorItem('Label normal',      38,
  325.       ColorItem('Label selected',    39,
  326.       ColorItem('Label shortcut',    40,
  327.  
  328.       ColorItem('Button normal',     41,
  329.       ColorItem('Button default',    42,
  330.       ColorItem('Button selected',   43,
  331.       ColorItem('Button disabled',   44,
  332.       ColorItem('Button shortcut',   45,
  333.       ColorItem('Button shadow',     46,
  334.  
  335.       ColorItem('Cluster normal',    47,
  336.       ColorItem('Cluster selected',  48,
  337.       ColorItem('Cluster shortcut',  49,
  338.  
  339.       ColorItem('Input normal',      50,
  340.       ColorItem('Input selected',    51,
  341.       ColorItem('Input arrow',       52,
  342.  
  343.       ColorItem('History button',    53,
  344.       ColorItem('History sides',     54,
  345.       ColorItem('History bar page',  55,
  346.       ColorItem('History bar icons', 56,
  347.  
  348.       ColorItem('List normal',       57,
  349.       ColorItem('List focused',      58,
  350.       ColorItem('List selected',     59,
  351.       ColorItem('List divider',      60,
  352.  
  353.       ColorItem('Information pane',  61, nil))))))))))))))))))))))))))))),
  354.     ColorGroup('Viewer',
  355.       ColorItem('Frame passive',      8,
  356.       ColorItem('Frame active',       9,
  357.       ColorItem('Frame icons',       10,
  358.       ColorItem('Scroll bar page',   11,
  359.       ColorItem('Scroll bar icons',  12,
  360.       ColorItem('Text',              13, nil)))))),
  361.     ColorGroup('Puzzle',
  362.       ColorItem('Frame passive',      8,
  363.       ColorItem('Frame active',       9,
  364.       ColorItem('Frame icons',       10,
  365.       ColorItem('Scroll bar page',   11,
  366.       ColorItem('Scroll bar icons',  12,
  367.       ColorItem('Normal text',       13,
  368.       ColorItem('Highlighted text',  14, nil))))))),
  369.     ColorGroup('Calendar',
  370.       ColorItem('Frame passive',     16,
  371.       ColorItem('Frame active',      17,
  372.       ColorItem('Frame icons',       18,
  373.       ColorItem('Scroll bar page',   19,
  374.       ColorItem('Scroll bar icons',  20,
  375.       ColorItem('Normal text',       21,
  376.       ColorItem('Current day',       22, nil))))))),
  377.     ColorGroup('Ascii table',
  378.       ColorItem('Frame passive',     24,
  379.       ColorItem('Frame active',      25,
  380.       ColorItem('Frame icons',       26,
  381.       ColorItem('Scroll bar page',   27,
  382.       ColorItem('Scroll bar icons',  28,
  383.       ColorItem('Text',              29, nil)))))), nil)))))))));
  384.  
  385.   D^.HelpCtx := hcOCColorsDBox;
  386.   if ValidView(D) <> nil then
  387.   begin
  388.     D^.SetData(Application^.GetPalette^);
  389.     if Desktop^.ExecView(D) <> cmCancel then
  390.     begin
  391.       Application^.GetPalette^ := D^.Pal;
  392.       DoneMemory;  { Dispose all group buffers }
  393.       ReDraw;      { Redraw application with new palette }
  394.     end;
  395.     Dispose(D, Done);
  396.   end;
  397. end;
  398.  
  399. procedure Mouse;
  400. var
  401.   D: PDialog;
  402. begin
  403.   D := New(PMouseDialog, Init);
  404.   D^.HelpCtx := hcOMMouseDBox;
  405.   if ValidView(D) <> nil then
  406.   begin
  407.     D^.SetData(MouseReverse);
  408.     if Desktop^.ExecView(D) <> cmCancel then
  409.       D^.GetData(MouseReverse);
  410.   end;
  411. end;
  412.  
  413. procedure DosShell;
  414. begin
  415.   DoneSysError;
  416.   DoneEvents;
  417.   DoneVideo;
  418.   DoneMemory;
  419.   SetMemTop(HeapPtr);
  420.   PrintStr('Type EXIT to return...');
  421.   SwapVectors;
  422.   Exec(GetEnv('COMSPEC'), '');
  423.   SwapVectors;
  424.   SetMemTop(HeapEnd);
  425.   InitMemory;
  426.   InitVideo;
  427.   InitEvents;
  428.   InitSysError;
  429.   Redraw;
  430. end;
  431.  
  432. procedure RetrieveDesktop;
  433. var
  434.   S: PStream;
  435. begin
  436.   S := New(PBufStream, Init('TVDEMO.DSK', stOpenRead, 1024));
  437.   if LowMemory then OutOfMemory
  438.   else if S^.Status <> stOk then
  439.     MessageBox('Could not open desktop file', nil, mfOkButton + mfError)
  440.   else
  441.   begin
  442.     LoadDesktop(S^);
  443.     if S^.Status <> stOk then
  444.       MessageBox('Error reading desktop file', nil, mfOkButton + mfError);
  445.   end;
  446.   Dispose(S, Done);
  447. end;
  448.  
  449. procedure SaveDesktop;
  450. var
  451.   S: PStream;
  452.   F: File;
  453. begin
  454.   S := New(PBufStream, Init('TVDEMO.DSK', stCreate, 1024));
  455.   if not LowMemory and (S^.Status = stOk) then
  456.   begin
  457.     StoreDesktop(S^);
  458.     if S^.Status <> stOk then
  459.     begin
  460.       MessageBox('Could not create TVDEMO.DSK.', nil, mfOkButton + mfError);
  461.       {$I-}
  462.       Dispose(S, Done);
  463.       Assign(F, 'TVDEMO.DSK');
  464.       Erase(F);
  465.       Exit;
  466.     end;
  467.   end;
  468.   Dispose(S, Done);
  469. end;
  470.  
  471.  
  472. begin
  473.   TVGApp.HandleEvent(Event);                                 (*** TVGRAPH ***)
  474.   case Event.What of
  475.     evCommand:
  476.       begin
  477.         case Event.Command of
  478.           cmFOpen: FileOpen('*.*');
  479.           cmChDir: ChangeDir;
  480.           cmCascade: Cascade;
  481.           cmTile: Tile;
  482.           cmAbout: About;
  483.           cmPuzzle: Puzzle;
  484.           cmCalendar: Calendar;
  485.           cmAsciiTab: AsciiTab;
  486.           cmCalculator: Calculator;
  487.           cmColors: Colors;
  488.           cmMouse: Mouse;
  489.           cmDosShell: DosShell;
  490.           cmSaveDesktop: SaveDesktop;
  491.           cmRetrieveDesktop: RetrieveDesktop;
  492.           cmStyx: OpenStyx;                               (*** TVGRAPH ***)
  493.         else
  494.           Exit;
  495.         end;
  496.         ClearEvent(Event);
  497.       end;
  498.   end;
  499. end;
  500.  
  501. procedure TTVDemo.Idle;
  502.  
  503. function IsTileable(P: PView): Boolean; far;
  504. begin
  505.   IsTileable := P^.Options and ofTileable <> 0;
  506. end;
  507.  
  508. procedure DoProdStyx(P: PView); far;                      (*** TVGRAPH ***)
  509. begin                                                     (*** TVGRAPH ***)
  510.   Message(P, evCommand,cmTVGraphProd, nil);               (*** TVGRAPH ***)
  511. end;                                                      (*** TVGRAPH ***)
  512.  
  513. begin
  514.   TVGApp.Idle;                                            (*** TVGRAPH ***)
  515.   Clock^.Update;
  516.   Heap^.Update;
  517.  
  518.   Desktop^.ForEach(@DoProdStyx);                          (*** TVGRAPH ***)
  519.  
  520.   if Desktop^.FirstThat(@IsTileable) <> nil then
  521.     EnableCommands([cmTile, cmCascade])
  522.   else
  523.     DisableCommands([cmTile, cmCascade]);
  524. end;
  525.  
  526. procedure TTVDemo.InitMenuBar;
  527. var
  528.   R: TRect;
  529. begin
  530.   GetExtent(R);
  531.   R.B.Y := R.A.Y+1;
  532.   MenuBar := New(PMenuBar, Init(R, NewMenu(
  533.     NewSubMenu('~'#240'~', hcSystem, NewMenu(
  534.       NewItem('~A~bout', '', kbNoKey, cmAbout, hcSAbout,
  535.       NewLine(
  536.       NewItem('~P~uzzle', '', kbNoKey, cmPuzzle, hcSPuzzle,
  537.       NewItem('Ca~l~endar', '', kbNoKey, cmCalendar, hcSCalendar,
  538.       NewItem('Ascii ~t~able', '', kbNoKey, cmAsciiTab, hcSAsciiTable,
  539.       NewItem('~S~tyx', '', kbNoKey, cmStyx, hcNoContext,     (*** TVGRAPH ***)
  540.       NewItem('~C~alculator', '', kbNoKey, cmCalculator, hcCalculator, nil)))))))),
  541.     NewSubMenu('~F~ile', hcFile, NewMenu(
  542.       NewItem('~O~pen...', 'F3', kbF3, cmFOpen, hcFOpen,
  543.       NewItem('~C~hange dir...', '', kbNoKey, cmChDir, hcFChangeDir,
  544.       NewLine(
  545.       NewItem('~D~OS shell', '', kbNoKey, cmDosShell, hcFDosShell,
  546.       NewItem('E~x~it', 'Alt-X', kbAltX, cmQuit, hcFExit, nil)))))),
  547.     NewSubMenu('~W~indows', hcWindows, NewMenu(
  548.       NewItem('~R~esize/move','Ctrl-F5', kbCtrlF5, cmResize, hcWSizeMove,
  549.       NewItem('~Z~oom', 'F5', kbF5, cmZoom, hcWZoom,
  550.       NewItem('~N~ext', 'F6', kbF6, cmNext, hcWNext,
  551.       NewItem('~C~lose', 'Alt-F3', kbAltF3, cmClose, hcWClose,
  552.       NewItem('~T~ile', '', kbNoKey, cmTile, hcWTile,
  553.       NewItem('C~a~scade', '', kbNoKey, cmCascade, hcWCascade, nil))))))),
  554.     NewSubMenu('~O~ptions', hcOptions, NewMenu(
  555.       NewItem('~M~ouse...', '', kbNoKey, cmMouse, hcOMouse,
  556.       NewItem('~C~olors...', '', kbNoKey, cmColors, hcOColors,
  557.       NewLine(
  558.       NewItem('~S~ave desktop', '', kbNoKey, cmSaveDesktop, hcOSaveDesktop,
  559.       NewItem('~R~etrieve desktop', '', kbNoKey, cmRetrieveDesktop, hcORestoreDesktop, nil)))))), nil)))))));
  560. end;
  561.  
  562. procedure TTVDemo.InitStatusLine;
  563. var
  564.   R: TRect;
  565. begin
  566.   GetExtent(R);
  567.   R.A.Y := R.B.Y - 1;
  568.   StatusLine := New(PStatusLine, Init(R,
  569.     NewStatusDef(0, $FFFF,
  570.       NewStatusKey('~F1~ Help', kbF1, cmHelp,
  571.       NewStatusKey('~F3~ Open', kbF3, cmFOpen,
  572.       NewStatusKey('~Alt-F3~ Close', kbAltF3, cmClose,
  573.       NewStatusKey('~F5~ Zoom', kbF5, cmZoom,
  574.       NewStatusKey('', kbF10, cmMenu,
  575.       NewStatusKey('', kbCtrlF5, cmResize, nil)))))), nil)));
  576. end;
  577.  
  578. procedure TTVDemo.OutOfMemory;
  579. begin
  580.   MessageBox('Not enough memory available to complete operation.',
  581.     nil, mfError + mfOkButton);
  582. end;
  583.  
  584. { Since the safety pool is only large enough to guarantee that allocating
  585.   a window will not run out of memory, loading the entire desktop without
  586.   checking LowMemory could cause a heap error.  This means that each
  587.   window should be read individually, instead of using Desktop's Load.
  588. }
  589.  
  590. procedure TTVDemo.LoadDesktop(var S: TStream);
  591. var
  592.   P: PView;
  593.  
  594. procedure CloseView(P: PView); far;
  595. begin
  596.   Message(P, evCommand, cmClose, nil);
  597. end;
  598.  
  599. begin
  600.   if Desktop^.Valid(cmClose) then
  601.   begin
  602.     Desktop^.ForEach(@CloseView); { Clear the desktop }
  603.     repeat
  604.       P := PView(S.Get);
  605.       Desktop^.InsertBefore(ValidView(P), Desktop^.Last);
  606.     until P = nil;
  607.   end;
  608. end;
  609.  
  610. procedure TTVDemo.StoreDesktop(var S: TStream);
  611.  
  612. procedure WriteView(P: PView); far;
  613. begin
  614.   if P <> Desktop^.Last then S.Put(P);
  615. end;
  616.  
  617. begin
  618.   Desktop^.ForEach(@WriteView);
  619.   S.Put(nil);
  620. end;
  621.  
  622. procedure TTVDemo.ViewFile(FileName: PathStr);
  623. var
  624.   W: PWindow;
  625. begin
  626.   W := New(PFileWindow,Init(FileName));
  627.   W^.HelpCtx := hcViewer;
  628.   if ValidView(W) <> nil then
  629.     Desktop^.Insert(W);
  630. end;
  631.  
  632. var
  633.   Demo: TTVDemo;
  634.  
  635. begin
  636.   Demo.Init;
  637.   Demo.Run;
  638.   Demo.Done;
  639. end.
  640.