home *** CD-ROM | disk | FTP | other *** search
/ PC-X 1998 July / pcx23_9807.iso / PC-XUSER / PC-XUSER.16 / OOP / TVDEMO.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1998-01-02  |  18.3 KB  |  692 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Demo                            }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. program TVDemo;
  9.  
  10. {$X+,S-}
  11. {$M 16384,8192,655360}
  12.  
  13. { Turbo Vision demo program. This program uses many of the Turbo
  14.   Vision standard and demo units, including:
  15.  
  16.     StdDlg    - Open file browser, change directory tree.
  17.     MsgBox    - Simple dialog to display messages.
  18.     ColorSel  - Color customization.
  19.     Gadgets   - Shows system time and available heap space.
  20.     AsciiTab  - ASCII table.
  21.     Calendar  - View a month at a time
  22.     Calc      - Desktop calculator.
  23.     HelpFile  - Context sensitive help.
  24.     MouseDlg  - Mouse options dialog.
  25.     Puzzle    - Simple brain puzzle.
  26.     Editors   - Text Editor object.
  27.  
  28.   And of course this program includes many standard Turbo Vision
  29.   objects and behaviors (menubar, desktop, status line, dialog boxes,
  30.   mouse support, window resize/move/tile/cascade).
  31. }
  32.  
  33. uses
  34.   Dos, Objects, Drivers, Memory, Views, Menus, Dialogs, StdDlg, HistList,
  35.   MsgBox, App, DemoCmds, Gadgets, Puzzle, Calendar, AsciiTab, Calc,
  36.   HelpFile, DemoHelp, ColorSel, MouseDlg, Editors,
  37.   PCX_App, PCX_Dlg, PCX_Util;
  38.  
  39. { If you get a FILE NOT FOUND error when compiling this program
  40.   from a DOS IDE, change to the \BP\EXAMPLES\DOS\TVDEMO directory
  41.   (use File|Change dir).
  42.  
  43.   This will enable the compiler to find all of the units used by
  44.   this program.
  45. }
  46.  
  47. const
  48.   HeapSize = 48 * (1024 div 16);  { Save 48k heap for main program }
  49.  
  50.   { Desktop file signature information }
  51.   SignatureLen = 21;
  52.   DSKSignature : string[SignatureLen] = 'TV Demo Desktop File'#26;
  53.   cmAbout      = 1111;
  54.  
  55. var
  56.   ClipWindow: PEditWindow;
  57.  
  58. type
  59.  
  60.   { TTVDemo }
  61.  
  62.   PTVDemo = ^TTVDemo;
  63.   TTVDemo = object(TPCXApplication)
  64.     Clock: PClockView;
  65.     Heap : PHeapView;
  66.     constructor Init;
  67.     procedure FileOpen(WildCard: PathStr);
  68.     function  OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  69.     procedure GetEvent(var Event: TEvent); virtual;
  70.     function  GetPalette: PPalette; virtual;
  71.     procedure HandleEvent(var Event: TEvent); virtual;
  72.     procedure Idle; virtual;
  73.     procedure InitMenuBar; virtual;
  74.     procedure InitStatusLine; virtual;
  75.     procedure LoadDesktop(var S: TStream);
  76.     procedure OutOfMemory; virtual;
  77.     procedure StoreDesktop(var S: TStream);
  78.   end;
  79.  
  80. { CalcHelpName }
  81.  
  82. function CalcHelpName: PathStr;
  83. var
  84.   EXEName: PathStr;
  85.   Dir: DirStr;
  86.   Name: NameStr;
  87.   Ext: ExtStr;
  88. begin
  89.   if Lo(DosVersion) >= 3 then EXEName := ParamStr(0)
  90.   else EXEName := FSearch('TVDEMO.EXE', GetEnv('PATH'));
  91.   FSplit(EXEName, Dir, Name, Ext);
  92.   if Dir[Length(Dir)] = '\' then Dec(Dir[0]);
  93.   CalcHelpName := FSearch('DEMOHELP.HLP', Dir);
  94. end;
  95.  
  96. function CreateFindDialog: PPCXBlueDialog;
  97. var
  98.   D: PPCXBlueDialog;
  99.   Control: PView;
  100.   R: TRect;
  101. begin
  102.   R.Assign(0, 0, 38, 12);
  103.   D := New(PPCXBlueDialog, Init(R, 'Find'));
  104.   with D^ do
  105.   begin
  106.     Options := Options or ofCentered;
  107.  
  108.     R.Assign(3, 3, 32, 4);
  109.     Control := New(PInputLine, Init(R, 80));
  110.     Insert(Control);
  111.     R.Assign(2, 2, 15, 3);
  112.     Insert(New(PLabel, Init(R, '~T~ext to find', Control)));
  113.     R.Assign(32, 3, 35, 4);
  114.     Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  115.  
  116.     R.Assign(3, 5, 35, 7);
  117.     Insert(New(PCheckBoxes, Init(R,
  118.       NewSItem('~C~ase sensitive',
  119.       NewSItem('~W~hole words only', nil)))));
  120.  
  121.     R.Assign(14, 9, 24, 11);
  122.     Insert(New(PPCXButton, Init(R, 'O~K~', cmOk, bfDefault)));
  123.     Inc(R.A.X, 12); Inc(R.B.X, 12);
  124.     Insert(New(PPCXButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  125.  
  126.     SelectNext(False);
  127.   end;
  128.   CreateFindDialog := D;
  129. end;
  130.  
  131. function CreateReplaceDialog: PPCXBlueDialog;
  132. var
  133.   D: PPCXBlueDialog;
  134.   Control: PView;
  135.   R: TRect;
  136. begin
  137.   R.Assign(0, 0, 40, 16);
  138.   D := New(PPCXBlueDialog, Init(R, 'Replace'));
  139.   with D^ do
  140.   begin
  141.     Options := Options or ofCentered;
  142.  
  143.     R.Assign(3, 3, 34, 4);
  144.     Control := New(PInputLine, Init(R, 80));
  145.     Insert(Control);
  146.     R.Assign(2, 2, 15, 3);
  147.     Insert(New(PLabel, Init(R, '~T~ext to find', Control)));
  148.     R.Assign(34, 3, 37, 4);
  149.     Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
  150.  
  151.     R.Assign(3, 6, 34, 7);
  152.     Control := New(PInputLine, Init(R, 80));
  153.     Insert(Control);
  154.     R.Assign(2, 5, 12, 6);
  155.     Insert(New(PLabel, Init(R, '~N~ew text', Control)));
  156.     R.Assign(34, 6, 37, 7);
  157.     Insert(New(PHistory, Init(R, PInputLine(Control), 11)));
  158.  
  159.     R.Assign(3, 8, 37, 12);
  160.     Insert(New(PCheckBoxes, Init(R,
  161.       NewSItem('~C~ase sensitive',
  162.       NewSItem('~W~hole words only',
  163.       NewSItem('~P~rompt on replace',
  164.       NewSItem('~R~eplace all', nil)))))));
  165.  
  166.     R.Assign(17, 13, 27, 15);
  167.     Insert(New(PPCXButton, Init(R, 'O~K~', cmOk, bfDefault)));
  168.     R.Assign(28, 13, 38, 15);
  169.     Insert(New(PPCXButton, Init(R, 'Cancel', cmCancel, bfNormal)));
  170.  
  171.     SelectNext(False);
  172.   end;
  173.   CreateReplaceDialog := D;
  174. end;
  175.  
  176. function DoEditDialog(Dialog: Integer; Info: Pointer): Word; far;
  177. var
  178.   R: TRect;
  179.   T: TPoint;
  180. begin
  181.   case Dialog of
  182.     edOutOfMemory:
  183.       DoEditDialog := MessageBox('Not enough memory for this operation.',
  184.         nil, mfError + mfOkButton);
  185.     edReadError:
  186.       DoEditDialog := MessageBox('Error reading file %s.',
  187.         @Info, mfError + mfOkButton);
  188.     edWriteError:
  189.       DoEditDialog := MessageBox('Error writing file %s.',
  190.         @Info, mfError + mfOkButton);
  191.     edCreateError:
  192.       DoEditDialog := MessageBox('Error creating file %s.',
  193.         @Info, mfError + mfOkButton);
  194.     edSaveModify:
  195.       DoEditDialog := MessageBox('%s has been modified. Save?',
  196.         @Info, mfInformation + mfYesNoCancel);
  197.     edSaveUntitled:
  198.       DoEditDialog := MessageBox('Save untitled file?',
  199.         nil, mfInformation + mfYesNoCancel);
  200.     edSaveAs:
  201.       DoEditDialog := Application^.ExecuteDialog(New(PFileDialog, Init('*.*',
  202.         'Save file as', '~N~ame', fdOkButton, 101)), Info);
  203.     edFind:
  204.       DoEditDialog := Application^.ExecuteDialog(CreateFindDialog, Info);
  205.     edSearchFailed:
  206.       DoEditDialog := MessageBox('Search string not found.',
  207.         nil, mfError + mfOkButton);
  208.     edReplace:
  209.       DoEditDialog := Application^.ExecuteDialog(CreateReplaceDialog, Info);
  210.     edReplacePrompt:
  211.       begin
  212.         { Avoid placing the dialog on the same line as the cursor }
  213.         R.Assign(0, 1, 40, 8);
  214.         R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  215.         Desktop^.MakeGlobal(R.B, T);
  216.         Inc(T.Y);
  217.         if TPoint(Info).Y <= T.Y then
  218.           R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  219.         DoEditDialog := MessageBoxRect(R, 'Replace this occurence ?',
  220.           nil, mfYesNoCancel + mfInformation);
  221.       end;
  222.   end;
  223. end;
  224.  
  225. { TTVDemo }
  226. constructor TTVDemo.Init;
  227. var
  228.   R: TRect;
  229.   I: Integer;
  230.   FileName: PathStr;
  231. begin
  232.   MaxHeapSize := HeapSize;
  233.   inherited Init('PC-X User Extended Turbo Vision Demo', '', '', '');
  234.   RegisterObjects;
  235.   RegisterViews;
  236.   RegisterMenus;
  237.   RegisterDialogs;
  238.   RegisterApp;
  239.   RegisterHelpFile;
  240.   RegisterPuzzle;
  241.   RegisterCalendar;
  242.   RegisterAsciiTab;
  243.   RegisterCalc;
  244.   RegisterEditors;
  245.  
  246.   { Initialize demo gadgets }
  247.  
  248.   GetExtent(R);
  249.   R.A.X := R.B.X - 9; R.B.Y := R.A.Y + 1;
  250.   Clock := New(PClockView, Init(R));
  251.   Insert(Clock);
  252.  
  253.   GetExtent(R);
  254.   Dec(R.B.X);
  255.   R.A.X := R.B.X - 9; R.A.Y := R.B.Y - 1;
  256.   Heap := New(PHeapView, Init(R));
  257.   Insert(Heap);
  258.  
  259.   DisableCommands([cmSave, cmSaveAs, cmCut, cmCopy, cmPaste, cmClear,
  260.     cmUndo, cmFind, cmReplace, cmSearchAgain, cmCloseAll]);
  261.   EditorDialog := DoEditDialog;
  262.   ClipWindow := OpenEditor('', False);
  263.   if ClipWindow <> nil then
  264.   begin
  265.     Clipboard := ClipWindow^.Editor;
  266.     Clipboard^.CanUndo := False;
  267.   end;
  268.  
  269.   for I := 1 to ParamCount do
  270.   begin
  271.     FileName := ParamStr(I);
  272.     if FileName[Length(FileName)] = '\' then
  273.       FileName := FileName + '*.*';
  274.     if (Pos('?', FileName) = 0) and (Pos('*', FileName) = 0) then
  275.       OpenEditor(FExpand(FileName), True)
  276.     else FileOpen(FileName);
  277.   end;
  278. end;
  279.  
  280. function TTVDemo.OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  281. var
  282.   P: PView;
  283.   R: TRect;
  284. begin
  285.   DeskTop^.GetExtent(R);
  286.   P := Application^.ValidView(New(PEditWindow,
  287.     Init(R, FileName, wnNoNumber)));
  288.   if not Visible then P^.Hide;
  289.   DeskTop^.Insert(P);
  290.   OpenEditor := PEditWindow(P);
  291. end;
  292.  
  293. procedure TTVDemo.FileOpen(WildCard: PathStr);
  294. var
  295.   FileName: FNameStr;
  296. begin
  297.   FileName := '*.*';
  298.   if ExecuteDialog(New(PFileDialog, Init(WildCard, 'Open a file',
  299.     '~N~ame', fdOpenButton + fdHelPButton, 100)), @FileName) <> cmCancel then
  300.     OpenEditor(FileName, True);
  301. end;
  302.  
  303. procedure TTVDemo.GetEvent(var Event: TEvent);
  304. var
  305.   W: PWindow;
  306.   HFile: PHelpFile;
  307.   HelpStrm: PDosStream;
  308. const
  309.   HelpInUse: Boolean = False;
  310. begin
  311.   inherited GetEvent(Event);
  312.   case Event.What of
  313.     evCommand:
  314.       if (Event.Command = cmHelp) and not HelpInUse then
  315.       begin
  316.         HelpInUse := True;
  317.         HelpStrm := New(PDosStream, Init(CalcHelpName, stOpenRead));
  318.         HFile := New(PHelpFile, Init(HelpStrm));
  319.         if HelpStrm^.Status <> stOk then
  320.         begin
  321.           MessageBox('Could not open help file.', nil, mfError + mfOkButton);
  322.           Dispose(HFile, Done);
  323.         end
  324.         else
  325.         begin
  326.           W := New(PHelpWindow,Init(HFile, GetHelpCtx));
  327.           if ValidView(W) <> nil then
  328.           begin
  329.             ExecView(W);
  330.             Dispose(W, Done);
  331.           end;
  332.           ClearEvent(Event);
  333.         end;
  334.         HelpInUse := False;
  335.       end;
  336.     evMouseDown:
  337.       if Event.Buttons <> 1 then Event.What := evNothing;
  338.   end;
  339. end;
  340.  
  341. function TTVDemo.GetPalette: PPalette;
  342. const
  343.   CNewColor = CPCXColor + CHelpColor;
  344.   CNewBlackWhite = CPCXBlackWhite + CHelpBlackWhite;
  345.   CNewMonochrome = CPCXMonochrome + CHelpMonochrome;
  346.   P: array[apColor..apMonochrome] of string[Length(CNewColor)] =
  347.     (CNewColor, CNewBlackWhite, CNewMonochrome);
  348. begin
  349.   GetPalette := @P[AppPalette];
  350. end;
  351.  
  352. procedure TTVDemo.HandleEvent(var Event: TEvent);
  353.  
  354. procedure ChangeDir;
  355. var
  356.   D: PChDirDialog;
  357. begin
  358.   D := New(PChDirDialog, Init(cdNormal + cdHelPButton, 101));
  359.   D^.HelpCtx := hcFCChDirDBox;
  360.   ExecuteDialog(D, nil);
  361. end;
  362.  
  363. procedure Puzzle;
  364. var
  365.   P: PPuzzleWindow;
  366. begin
  367.   P := New(PPuzzleWindow, Init);
  368.   P^.HelpCtx := hcPuzzle;
  369.   InsertWindow(P);
  370. end;
  371.  
  372. procedure Calendar;
  373. var
  374.   P: PCalendarWindow;
  375. begin
  376.   P := New(PCalendarWindow, Init);
  377.   P^.HelpCtx := hcCalendar;
  378.   InsertWindow(P);
  379. end;
  380.  
  381. procedure About;
  382. var
  383.   D: PPCXBlueDialog;
  384.   Control: PView;
  385.   R: TRect;
  386. begin
  387.   R.Assign(0, 0, 40, 11);
  388.   D := New(PPCXBlueDialog, Init(R, 'About'));
  389.   with D^ do
  390.   begin
  391.     Options := Options or ofCentered;
  392.  
  393.     R.Grow(-1, -1);
  394.     Dec(R.B.Y, 3);
  395.     Insert(New(PStaticText, Init(R,
  396.       #13 +
  397.       ^C'Turbo Vision Demo'#13 +
  398.       #13 +
  399.       ^C'Copyright (c) 1992'#13 +
  400.       #13 +
  401.       ^C'Borland International')));
  402.  
  403.     R.Assign(15, 8, 25, 10);
  404.     Insert(New(PPCXButton, Init(R, 'O~K', cmOk, bfDefault)));
  405.   end;
  406.   if ValidView(D) <> nil then
  407.   begin
  408.     Desktop^.ExecView(D);
  409.     Dispose(D, Done);
  410.   end;
  411. end;
  412.  
  413. procedure AsciiTab;
  414. var
  415.   P: PAsciiChart;
  416. begin
  417.   P := New(PAsciiChart, Init);
  418.   P^.HelpCtx := hcAsciiTable;
  419.   InsertWindow(P);
  420. end;
  421.  
  422. procedure Calculator;
  423. var
  424.   P: PCalculator;
  425. begin
  426.   P := New(PCalculator, Init);
  427.   P^.HelpCtx := hcCalculator;
  428.   InsertWindow(P);
  429. end;
  430.  
  431. procedure Colors;
  432. var
  433.   D: PColorDialog;
  434. begin
  435.   D := New(PColorDialog, Init('',
  436.     ColorGroup('Desktop',       DesktopColorItems(nil),
  437.     ColorGroup('Menus',         MenuColorItems(nil),
  438.     ColorGroup('Dialogs/Calc',  DialogColorItems(dpGrayDialog, nil),
  439.     ColorGroup('Editor/Puzzle', WindowColorItems(wpBlueWindow, nil),
  440.     ColorGroup('Ascii table',   WindowColorItems(wpGrayWindow, nil),
  441.     ColorGroup('Calendar',
  442.       WindowColorItems(wpCyanWindow,
  443.       ColorItem('Current day',       22, nil)),
  444.       nil))))))));
  445.  
  446.   D^.HelpCtx := hcOCColorsDBox;
  447.  
  448.   if ExecuteDialog(D, Application^.GetPalette) <> cmCancel then
  449.   begin
  450.     DoneMemory;    { Dispose all group buffers }
  451.     ReDraw;        { Redraw application with new palette }
  452.   end;
  453. end;
  454.  
  455. procedure Mouse;
  456. var
  457.   D: PDialog;
  458. begin
  459.   D := New(PMouseDialog, Init);
  460.   D^.HelpCtx := hcOMMouseDBox;
  461.   ExecuteDialog(D, @MouseReverse);
  462. end;
  463.  
  464. procedure RetrieveDesktop;
  465. var
  466.   S: PStream;
  467.   Signature: string[SignatureLen];
  468. begin
  469.   S := New(PBufStream, Init('TVDEMO.DSK', stOpenRead, 1024));
  470.   if LowMemory then OutOfMemory
  471.   else if S^.Status <> stOk then
  472.     MessageBox('Could not open desktop file', nil, mfOkButton + mfError)
  473.   else
  474.   begin
  475.     Signature[0] := Char(SignatureLen);
  476.     S^.Read(Signature[1], SignatureLen);
  477.     if Signature = DSKSignature then
  478.     begin
  479.       LoadDesktop(S^);
  480.       LoadIndexes(S^);
  481.       LoadHistory(S^);
  482.       if S^.Status <> stOk then
  483.         MessageBox('Error reading desktop file', nil, mfOkButton + mfError);
  484.     end
  485.     else
  486.       MessageBox('Error: Invalid Desktop file.', nil, mfOkButton + mfError);
  487.   end;
  488.   Dispose(S, Done);
  489. end;
  490.  
  491. procedure SaveDesktop;
  492. var
  493.   S: PStream;
  494.   F: File;
  495. begin
  496.   S := New(PBufStream, Init('TVDEMO.DSK', stCreate, 1024));
  497.   if not LowMemory and (S^.Status = stOk) then
  498.   begin
  499.     S^.Write(DSKSignature[1], SignatureLen);
  500.     StoreDesktop(S^);
  501.     StoreIndexes(S^);
  502.     StoreHistory(S^);
  503.     if S^.Status <> stOk then
  504.     begin
  505.       MessageBox('Could not create TVDEMO.DSK.', nil, mfOkButton + mfError);
  506.       {$I-}
  507.       Dispose(S, Done);
  508.       Assign(F, 'TVDEMO.DSK');
  509.       Erase(F);
  510.       Exit;
  511.     end;
  512.   end;
  513.   Dispose(S, Done);
  514. end;
  515.  
  516. procedure FileNew;
  517. begin
  518.   OpenEditor('', True);
  519. end;
  520.  
  521. procedure ShowClip;
  522. begin
  523.   ClipWindow^.Select;
  524.   ClipWindow^.Show;
  525. end;
  526.  
  527. begin
  528.   inherited HandleEvent(Event);
  529.   case Event.What of
  530.     evCommand:
  531.       begin
  532.         case Event.Command of
  533.           cmOpen: FileOpen('*.*');
  534.           cmNew: FileNew;
  535.           cmShowClip: ShowClip;
  536.           cmChangeDir: ChangeDir;
  537.           cmAbout: About;
  538.           cmPuzzle: Puzzle;
  539.           cmCalendar: Calendar;
  540.           cmAsciiTab: AsciiTab;
  541.           cmCalculator: Calculator;
  542.           cmColors: Colors;
  543.           cmMouse: Mouse;
  544.           cmSaveDesktop: SaveDesktop;
  545.           cmRetrieveDesktop: RetrieveDesktop;
  546.         else
  547.           Exit;
  548.         end;
  549.         ClearEvent(Event);
  550.       end;
  551.   end;
  552. end;
  553.  
  554. procedure TTVDemo.Idle;
  555.  
  556.   function IsTileable(P: PView): Boolean; far;
  557.   begin
  558.     IsTileable := (P^.Options and ofTileable <> 0) and
  559.       (P^.State and sfVisible <> 0);
  560.   end;
  561.  
  562. begin
  563.   inherited Idle;
  564.   Clock^.Update;
  565.   Heap^.Update;
  566.   if Desktop^.FirstThat(@IsTileable) <> nil
  567.   then EnableCommands([cmTile, cmCascade])
  568.   else DisableCommands([cmTile, cmCascade]);
  569. end;
  570.  
  571. procedure TTVDemo.InitMenuBar;
  572. var
  573.   R: TRect;
  574. begin
  575.   GetMenuBarExtent(R);
  576.   MenuBar := New(PPCXMenuBar, Init(R, NewMenu(
  577.     NewSubMenu('~'#240'~', hcSystem, NewMenu(
  578.       NewItem('~A~bout', '', kbNoKey, cmAbout, hcSAbout,
  579.       NewLine(
  580.       NewItem('~P~uzzle', '', kbNoKey, cmPuzzle, hcSPuzzle,
  581.       NewItem('Ca~l~endar', '', kbNoKey, cmCalendar, hcSCalendar,
  582.       NewItem('Ascii ~t~able', '', kbNoKey, cmAsciiTab, hcSAsciiTable,
  583.       NewItem('~C~alculator', '', kbNoKey, cmCalculator, hcCalculator, nil))))))),
  584.     NewSubMenu('~F~ile', hcFile, NewMenu(
  585.       StdFileMenuItems(nil)),
  586.     NewSubMenu('~E~dit', hcEdit, NewMenu(
  587.       StdEditMenuItems(
  588.       NewLine(
  589.       NewItem('~S~how clipboard', '', kbNoKey, cmShowClip, hcShowClip,
  590.       nil)))),
  591.     NewSubMenu('~S~earch', hcSearch, NewMenu(
  592.       NewItem('~F~ind...', '', kbNoKey, cmFind, hcFind,
  593.       NewItem('~R~eplace...', '', kbNoKey, cmReplace, hcReplace,
  594.       NewItem('~S~earch again', '', kbNoKey, cmSearchAgain, hcSearchAgain,
  595.       nil)))),
  596.     NewSubMenu('~W~indow', hcWindows, NewMenu(
  597.       StdWindowMenuItems(nil)),
  598.     NewSubMenu('~O~ptions', hcOptions, NewMenu(
  599.       NewItem('~M~ouse...', '', kbNoKey, cmMouse, hcOMouse,
  600.       NewItem('~C~olors...', '', kbNoKey, cmColors, hcOColors,
  601.       NewLine(
  602.       NewItem('~S~ave desktop', '', kbNoKey, cmSaveDesktop, hcOSaveDesktop,
  603.       NewItem('~R~etrieve desktop', '', kbNoKey, cmRetrieveDesktop, hcORestoreDesktop, nil)))))),
  604.       nil)))))))));
  605. end;
  606.  
  607. procedure TTVDemo.InitStatusLine;
  608. var
  609.   R: TRect;
  610. begin
  611.   GetExtent(R);
  612.   R.A.Y := R.B.Y - 1;
  613.   StatusLine := New(PStatusLine, Init(R,
  614.     NewStatusDef(0, $FFFF,
  615.       NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,
  616.       NewStatusKey('~F1~ Help', kbF1, cmHelp,
  617.       NewStatusKey('~F3~ Open', kbF3, cmOpen,
  618.       NewStatusKey('~Alt-F3~ Close', kbAltF3, cmClose,
  619.       NewStatusKey('~F5~ Zoom', kbF5, cmZoom,
  620.       NewStatusKey('', kbF10, cmMenu,
  621.       NewStatusKey('', kbCtrlF5, cmResize,
  622.       nil))))))),
  623.     nil)));
  624. end;
  625.  
  626. procedure TTVDemo.OutOfMemory;
  627. begin
  628.   MessageBox('Not enough memory available to complete operation.',
  629.     nil, mfError + mfOkButton);
  630. end;
  631.  
  632. { Since the safety pool is only large enough to guarantee that allocating
  633.   a window will not run out of memory, loading the entire desktop without
  634.   checking LowMemory could cause a heap error.  This means that each
  635.   window should be read individually, instead of using Desktop's Load.
  636. }
  637.  
  638. procedure TTVDemo.LoadDesktop(var S: TStream);
  639. var
  640.   P: PView;
  641.   Pal: PString;
  642.  
  643. procedure CloseView(P: PView); far;
  644. begin
  645.   Message(P, evCommand, cmClose, nil);
  646. end;
  647.  
  648. begin
  649.   if Desktop^.Valid(cmClose) then
  650.   begin
  651.     Desktop^.ForEach(@CloseView); { Clear the desktop }
  652.     repeat
  653.       P := PView(S.Get);
  654.       Desktop^.InsertBefore(ValidView(P), Desktop^.Last);
  655.     until P = nil;
  656.     Pal := S.ReadStr;
  657.     if Pal <> nil then
  658.     begin
  659.       Application^.GetPalette^ := Pal^;
  660.       DoneMemory;
  661.       Application^.ReDraw;
  662.       DisposeStr(Pal);
  663.     end;
  664.   end;
  665. end;
  666.  
  667. procedure TTVDemo.StoreDesktop(var S: TStream);
  668. var
  669.   Pal: PString;
  670.  
  671. procedure WriteView(P: PView); far;
  672. begin
  673.   if P <> Desktop^.Last then S.Put(P);
  674. end;
  675.  
  676. begin
  677.   Desktop^.ForEach(@WriteView);
  678.   S.Put(nil);
  679.   Pal := @Application^.GetPalette^;
  680.   S.WriteStr(Pal);
  681. end;
  682.  
  683.  
  684. var Demo: TTVDemo;
  685.  
  686. BEGIN
  687.   SetPCXGraphChars(True);
  688.   Demo.Init;
  689.   Demo.Run;
  690.   Demo.Done;
  691. END.
  692.