home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Pascal / TP.7_1 / TP / EXAMPLES / TVDEMO / TVRDEMO.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1992-10-05  |  13.8 KB  |  578 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Demo                            }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. { Turbo Vision demo program. This program demonstrates the use of
  9.   resource files and overlays to build a Turbo Vision application.
  10.   This program duplicates the functionality of TVDEMO but gets the
  11.   definition of menus, status line, and various dialogs off of a
  12.   resource file. GENRDEMO.PAS generates the resource file that is used
  13.   by this program.  To build this program, execute the batch file,
  14.   MKRDEMO.BAT which will create the resource file and overlay file
  15.   and copy them into the TVRDEMO.EXE file where this program looks
  16.   for them.
  17.  
  18.   Note: This program is designed for real-mode use only.
  19. }
  20.  
  21. program TVRDemo;
  22.  
  23. {$X+,S-}
  24. {$M 16384,8192,655360}
  25.  
  26. uses
  27.   Dos, Objects, Drivers, Memory, Views, Menus, Dialogs, StdDlg, HistList,
  28.   MsgBox, App, DemoCmds, DemoStrs, Gadgets, Puzzle, Calendar, AsciiTab,
  29.   Calc, HelpFile, DemoHelp, ColorSel, MouseDlg, Editors, Overlay;
  30.  
  31. {$O Views}
  32. {$O Menus}
  33. {$O Dialogs}
  34. {$O StdDlg}
  35. {$O MsgBox}
  36. {$O App}
  37. {$O HelpFile}
  38. {$O Gadgets}
  39. {$O Puzzle}
  40. {$O Calendar}
  41. {$O AsciiTab}
  42. {$O Calc}
  43. {$O ColorSel}
  44. {$O MouseDlg}
  45. {$O Editors}
  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.  
  54. var
  55.   ClipWindow: PEditWindow;
  56.  
  57. type
  58.  
  59.   { TTVDemo }
  60.  
  61.   PTVDemo = ^TTVDemo;
  62.   TTVDemo = object(TApplication)
  63.     Clock: PClockView;
  64.     Heap: PHeapView;
  65.     constructor Init;
  66.     procedure FileOpen(WildCard: PathStr);
  67.     function OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  68.     procedure GetEvent(var Event: TEvent); virtual;
  69.     function GetPalette: PPalette; virtual;
  70.     procedure HandleEvent(var Event: TEvent); virtual;
  71.     procedure Idle; virtual;
  72.     procedure InitMenuBar; virtual;
  73.     procedure InitStatusLine; virtual;
  74.     procedure LoadDesktop(var S: TStream);
  75.     procedure OutOfMemory; virtual;
  76.     procedure StoreDesktop(var S: TStream);
  77.   end;
  78.  
  79. type
  80.   PProtectedStream = ^TProtectedStream;
  81.   TProtectedStream = object(TBufStream)
  82.     procedure Error(Code, Info: Integer); virtual;
  83.   end;
  84.  
  85. var
  86.   EXEName: PathStr;
  87.   RezFile: TResourceFile;
  88.   RezStream: PStream;
  89.   Strings: PStringList;
  90.  
  91. { CalcHelpName }
  92.  
  93. function CalcHelpName: PathStr;
  94. var
  95.   EXEName: PathStr;
  96.   Dir: DirStr;
  97.   Name: NameStr;
  98.   Ext: ExtStr;
  99. begin
  100.   if Lo(DosVersion) >= 3 then EXEName := ParamStr(0)
  101.   else EXEName := FSearch('TVDEMO.EXE', GetEnv('PATH'));
  102.   FSplit(EXEName, Dir, Name, Ext);
  103.   if Dir[Length(Dir)] = '\' then Dec(Dir[0]);
  104.   CalcHelpName := FSearch('DEMOHELP.HLP', Dir);
  105. end;
  106.  
  107. { Resource MessageBox wrappers }
  108.  
  109. function RMessageBox(StrNum: Word; Param: Pointer; Flags: Word): Word;
  110. begin
  111.   RMessageBox := MessageBox(Strings^.Get(StrNum), Param, Flags);
  112. end;
  113.  
  114. function RMessageBoxRect(var Rect: TRect; StrNum: Word; Param: Pointer;
  115.   Flags: Word): Word;
  116. begin
  117.   RMessageBoxRect := MessageBoxRect(Rect, Strings^.Get(StrNum), Param,
  118.     Flags);
  119. end;
  120.  
  121. { Editor dialog call-back }
  122.  
  123. function DoEditDialog(Dialog: Integer; Info: Pointer): Word; far;
  124. var
  125.   R: TRect;
  126.   T: TPoint;
  127.  
  128.   function ExecDialog(const Dialog: String; Param: Pointer): Word;
  129.   begin
  130.     Application^.ExecuteDialog(PDialog(RezFile.Get(Dialog)), Param);
  131.   end;
  132.  
  133. begin
  134.   case Dialog of
  135.     edOutOfMemory:
  136.       DoEditDialog := RMessageBox(sNoMem, nil, mfError + mfOkButton);
  137.     edReadError:
  138.       DoEditDialog := RMessageBox(sErrorReading, @Info, mfError + mfOkButton);
  139.     edWriteError:
  140.       DoEditDialog := RMessageBox(sErrorWriting, @Info, mfError + mfOkButton);
  141.     edCreateError:
  142.       DoEditDialog := RMessageBox(sErrorCreating, @Info, mfError + mfOkButton);
  143.     edSaveModify:
  144.       DoEditDialog := RMessageBox(sModified, @Info,
  145.         mfInformation + mfYesNoCancel);
  146.     edSaveUntitled:
  147.       DoEditDialog := RMessageBox(sSaveUntitled, nil,
  148.         mfInformation + mfYesNoCancel);
  149.     edSaveAs:
  150.       DoEditDialog := ExecDialog('SaveAsDialog', Info);
  151.     edFind:
  152.       DoEditDialog := ExecDialog('FindDialog', Info);
  153.     edSearchFailed:
  154.       DoEditDialog := RMessageBox(sStrNotFound, nil, mfError + mfOkButton);
  155.     edReplace:
  156.       DoEditDialog := ExecDialog('ReplaceDialog', Info);
  157.     edReplacePrompt:
  158.       begin
  159.         { Avoid placing the dialog on the same line as the cursor }
  160.         R.Assign(0, 1, 40, 8);
  161.         R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
  162.         Desktop^.MakeGlobal(R.B, T);
  163.         Inc(T.Y);
  164.         if TPoint(Info).Y <= T.Y then
  165.           R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
  166.         DoEditDialog := RMessageBoxRect(R, sReplace, nil,
  167.           mfYesNoCancel + mfInformation);
  168.       end;
  169.   end;
  170. end;
  171.  
  172. { TProtectedStream }
  173.  
  174. procedure TProtectedStream.Error(Code, Info: Integer);
  175. begin
  176.   DoneHistory;
  177.   DoneSysError;
  178.   DoneEvents;
  179.   DoneVideo;
  180.   DoneMemory;
  181.  
  182.   Writeln('Error in stream: Code = ', Code, ' Info = ', Info);
  183.   Halt(1);
  184. end;
  185.  
  186. { TTVDemo }
  187. constructor TTVDemo.Init;
  188. var
  189.   R: TRect;
  190.   I: Integer;
  191.   FileName: PathStr;
  192. begin
  193.   { Initalize editor heap }
  194.   MaxHeapSize := HeapSize;
  195.  
  196.   { Initialize resource file }
  197.   RezStream := New(PProtectedStream, Init(EXEName, stOpenRead, 4096));
  198.   RezFile.Init(RezStream);
  199.  
  200.   RegisterObjects;
  201.   RegisterViews;
  202.   RegisterMenus;
  203.   RegisterDialogs;
  204.   RegisterApp;
  205.   RegisterStdDlg;
  206.   RegisterColorSel;
  207.  
  208.   RegisterHelpFile;
  209.   RegisterPuzzle;
  210.   RegisterCalendar;
  211.   RegisterAsciiTab;
  212.   RegisterCalc;
  213.   RegisterEditors;
  214.  
  215.   RegisterType(RStringList);
  216.  
  217.   Strings := PStringList(RezFile.Get('Strings'));
  218.  
  219.   inherited Init;
  220.  
  221.   { Initialize demo gadgets }
  222.  
  223.   GetExtent(R);
  224.   R.A.X := R.B.X - 9; R.B.Y := R.A.Y + 1;
  225.   Clock := New(PClockView, Init(R));
  226.   Insert(Clock);
  227.  
  228.   GetExtent(R);
  229.   Dec(R.B.X);
  230.   R.A.X := R.B.X - 9; R.A.Y := R.B.Y - 1;
  231.   Heap := New(PHeapView, Init(R));
  232.   Insert(Heap);
  233.  
  234.   DisableCommands([cmSave, cmSaveAs, cmCut, cmCopy, cmPaste, cmClear,
  235.     cmUndo, cmFind, cmReplace, cmSearchAgain]);
  236.   EditorDialog := DoEditDialog;
  237.   ClipWindow := OpenEditor('', False);
  238.   if ClipWindow <> nil then
  239.   begin
  240.     Clipboard := ClipWindow^.Editor;
  241.     Clipboard^.CanUndo := False;
  242.   end;
  243.  
  244.   for I := 1 to ParamCount do
  245.   begin
  246.     FileName := ParamStr(I);
  247.     if FileName[Length(FileName)] = '\' then
  248.       FileName := FileName + '*.*';
  249.     if (Pos('?', FileName) = 0) and (Pos('*', FileName) = 0) then
  250.       OpenEditor(FExpand(FileName), True)
  251.     else FileOpen(FileName);
  252.   end;
  253. end;
  254.  
  255. function TTVDemo.OpenEditor(FileName: FNameStr; Visible: Boolean): PEditWindow;
  256. var
  257.   P: PView;
  258.   R: TRect;
  259. begin
  260.   DeskTop^.GetExtent(R);
  261.   P := Application^.ValidView(New(PEditWindow,
  262.     Init(R, FileName, wnNoNumber)));
  263.   if not Visible then P^.Hide;
  264.   DeskTop^.Insert(P);
  265.   OpenEditor := PEditWindow(P);
  266. end;
  267.  
  268. procedure TTVDemo.FileOpen(WildCard: PathStr);
  269. var
  270.   FileName: PathStr;
  271. begin
  272.   FileName := '*.*';
  273.   if ExecuteDialog(PDialog(RezFile.Get('FileOpenDialog')),
  274.       @FileName) <> cmCancel then
  275.     OpenEditor(FileName, True);
  276. end;
  277.  
  278. procedure TTVDemo.GetEvent(var Event: TEvent);
  279. var
  280.   W: PWindow;
  281.   HFile: PHelpFile;
  282.   HelpStrm: PDosStream;
  283. const
  284.   HelpInUse: Boolean = False;
  285. begin
  286.   TApplication.GetEvent(Event);
  287.   case Event.What of
  288.     evCommand:
  289.       if (Event.Command = cmHelp) and not HelpInUse then
  290.       begin
  291.         HelpInUse := True;
  292.         HelpStrm := New(PDosStream, Init(CalcHelpName, stOpenRead));
  293.         HFile := New(PHelpFile, Init(HelpStrm));
  294.         if HelpStrm^.Status <> stOk then
  295.         begin
  296.           RMessageBox(sErrorHelp, nil, mfError + mfOkButton);
  297.           Dispose(HFile, Done);
  298.         end
  299.         else
  300.         begin
  301.           W := New(PHelpWindow,Init(HFile, GetHelpCtx));
  302.           if ValidView(W) <> nil then
  303.           begin
  304.             ExecView(W);
  305.             Dispose(W, Done);
  306.           end;
  307.           ClearEvent(Event);
  308.         end;
  309.         HelpInUse := False;
  310.       end;
  311.     evMouseDown:
  312.       if Event.Buttons <> 1 then Event.What := evNothing;
  313.   end;
  314. end;
  315.  
  316. function TTVDemo.GetPalette: PPalette;
  317. const
  318.   CNewColor = CAppColor + CHelpColor;
  319.   CNewBlackWhite = CAppBlackWhite + CHelpBlackWhite;
  320.   CNewMonochrome = CAppMonochrome + CHelpMonochrome;
  321.   P: array[apColor..apMonochrome] of string[Length(CNewColor)] =
  322.     (CNewColor, CNewBlackWhite, CNewMonochrome);
  323. begin
  324.   GetPalette := @P[AppPalette];
  325. end;
  326.  
  327. procedure TTVDemo.HandleEvent(var Event: TEvent);
  328.  
  329. procedure ChangeDir;
  330. begin
  331.   ExecuteDialog(PDialog(RezFile.Get('ChDirDialog')), nil);
  332. end;
  333.  
  334. procedure Puzzle;
  335. var
  336.   P: PPuzzleWindow;
  337. begin
  338.   P := New(PPuzzleWindow, Init);
  339.   P^.HelpCtx := hcPuzzle;
  340.   InsertWindow(P);
  341. end;
  342.  
  343. procedure Calendar;
  344. var
  345.   P: PCalendarWindow;
  346. begin
  347.   P := New(PCalendarWindow, Init);
  348.   P^.HelpCtx := hcCalendar;
  349.   InsertWindow(P);
  350. end;
  351.  
  352. procedure About;
  353. var
  354.   D: PDialog;
  355.   Control: PView;
  356.   R: TRect;
  357. begin
  358.   ExecuteDialog(PDialog(RezFile.Get('AboutDialog')), nil);
  359. end;
  360.  
  361. procedure AsciiTab;
  362. var
  363.   P: PAsciiChart;
  364. begin
  365.   P := New(PAsciiChart, Init);
  366.   P^.HelpCtx := hcAsciiTable;
  367.   InsertWindow(P);
  368. end;
  369.  
  370. procedure Calculator;
  371. var
  372.   P: PCalculator;
  373. begin
  374.   P := New(PCalculator, Init);
  375.   P^.HelpCtx := hcCalculator;
  376.   InsertWindow(P);
  377. end;
  378.  
  379. procedure Colors;
  380. begin
  381.   if ExecuteDialog(PDialog(RezFile.Get('ColorSelectDialog')),
  382.     Application^.GetPalette) <> cmCancel then
  383.   begin
  384.     DoneMemory;
  385.     ReDraw;
  386.   end;
  387. end;
  388.  
  389. procedure Mouse;
  390. var
  391.   D: PDialog;
  392. begin
  393.   D := New(PMouseDialog, Init);
  394.   D^.HelpCtx := hcOMMouseDBox;
  395.   ExecuteDialog(D, @MouseReverse);
  396. end;
  397.  
  398. procedure RetrieveDesktop;
  399. var
  400.   S: PStream;
  401.   Signature: string[SignatureLen];
  402. begin
  403.   S := New(PBufStream, Init('TVRDEMO.DSK', stOpenRead, 1024));
  404.   if LowMemory then OutOfMemory
  405.   else if S^.Status <> stOk then
  406.     RMessageBox(sErrorOpenDesk, nil, mfOkButton + mfError)
  407.   else
  408.   begin
  409.     Signature[0] := Char(SignatureLen);
  410.     S^.Read(Signature[1], SignatureLen);
  411.     if Signature = DSKSignature then
  412.     begin
  413.       LoadDesktop(S^);
  414.       LoadIndexes(S^);
  415.       LoadHistory(S^);
  416.       if S^.Status <> stOk then
  417.         RMessageBox(sErrorReadingDesk, nil, mfOkButton + mfError);
  418.     end
  419.     else
  420.       RMessageBox(sDeskInvalid, nil, mfOkButton + mfError);
  421.   end;
  422.   Dispose(S, Done);
  423. end;
  424.  
  425. procedure SaveDesktop;
  426. var
  427.   S: PStream;
  428.   F: File;
  429. begin
  430.   S := New(PBufStream, Init('TVRDEMO.DSK', stCreate, 1024));
  431.   if not LowMemory and (S^.Status = stOk) then
  432.   begin
  433.     S^.Write(DSKSignature[1], SignatureLen);
  434.     StoreDesktop(S^);
  435.     StoreIndexes(S^);
  436.     StoreHistory(S^);
  437.     if S^.Status <> stOk then
  438.     begin
  439.       RMessageBox(sErrorDeskCreate, nil, mfOkButton + mfError);
  440.       {$I-}
  441.       Dispose(S, Done);
  442.       Assign(F, 'TVRDEMO.DSK');
  443.       Erase(F);
  444.       Exit;
  445.     end;
  446.   end;
  447.   Dispose(S, Done);
  448. end;
  449.  
  450. procedure FileNew;
  451. begin
  452.   OpenEditor('', True);
  453. end;
  454.  
  455. procedure ShowClip;
  456. begin
  457.   ClipWindow^.Select;
  458.   ClipWindow^.Show;
  459. end;
  460.  
  461. begin
  462.   inherited HandleEvent(Event);
  463.   case Event.What of
  464.     evCommand:
  465.       begin
  466.         case Event.Command of
  467.           cmOpen: FileOpen('*.*');
  468.           cmNew: FileNew;
  469.           cmShowClip: ShowClip;
  470.           cmChangeDir: ChangeDir;
  471.           cmAbout: About;
  472.           cmPuzzle: Puzzle;
  473.           cmCalendar: Calendar;
  474.           cmAsciiTab: AsciiTab;
  475.           cmCalculator: Calculator;
  476.           cmColors: Colors;
  477.           cmMouse: Mouse;
  478.           cmSaveDesktop: SaveDesktop;
  479.           cmRetrieveDesktop: RetrieveDesktop;
  480.         else
  481.           Exit;
  482.         end;
  483.         ClearEvent(Event);
  484.       end;
  485.   end;
  486. end;
  487.  
  488. procedure TTVDemo.Idle;
  489.  
  490. function IsTileable(P: PView): Boolean; far;
  491. begin
  492.   IsTileable := P^.Options and ofTileable <> 0;
  493. end;
  494.  
  495. begin
  496.   TApplication.Idle;
  497.   Clock^.Update;
  498.   Heap^.Update;
  499.   if Desktop^.FirstThat(@IsTileable) <> nil then
  500.     EnableCommands([cmTile, cmCascade])
  501.   else
  502.     DisableCommands([cmTile, cmCascade]);
  503. end;
  504.  
  505. procedure TTVDemo.InitMenuBar;
  506. begin
  507.   MenuBar := PMenuBar(RezFile.Get('MenuBar'));
  508. end;
  509.  
  510. procedure TTVDemo.InitStatusLine;
  511. begin
  512.   StatusLine := PStatusLine(RezFile.Get('StatusLine'));
  513. end;
  514.  
  515. procedure TTVDemo.OutOfMemory;
  516. begin
  517.   RMessageBox(sNoMem, nil, mfError + mfOkButton);
  518. end;
  519.  
  520. { Since the safety pool is only large enough to guarantee that allocating
  521.   a window will not run out of memory, loading the entire desktop without
  522.   checking LowMemory could cause a heap error.  This means that each
  523.   window should be read individually, instead of using Desktop's Load.
  524. }
  525.  
  526. procedure TTVDemo.LoadDesktop(var S: TStream);
  527. var
  528.   P: PView;
  529.  
  530. procedure CloseView(P: PView); far;
  531. begin
  532.   Message(P, evCommand, cmClose, nil);
  533. end;
  534.  
  535. begin
  536.   if Desktop^.Valid(cmClose) then
  537.   begin
  538.     Desktop^.ForEach(@CloseView); { Clear the desktop }
  539.     repeat
  540.       P := PView(S.Get);
  541.       Desktop^.InsertBefore(ValidView(P), Desktop^.Last);
  542.     until P = nil;
  543.   end;
  544. end;
  545.  
  546. procedure TTVDemo.StoreDesktop(var S: TStream);
  547.  
  548. procedure WriteView(P: PView); far;
  549. begin
  550.   if P <> Desktop^.Last then S.Put(P);
  551. end;
  552.  
  553. begin
  554.   Desktop^.ForEach(@WriteView);
  555.   S.Put(nil);
  556. end;
  557.  
  558. var
  559.   Demo: TTVDemo;
  560. begin
  561.   if Lo(DosVersion) >= 3 then EXEName := ParamStr(0)
  562.   else
  563.   begin
  564.     EXEName := FSearch('TVRDEMO.EXE', GetEnv('PATH'));
  565.     if EXEName = '' then PrintStr('TVRDEMO.EXE could not be found.'#13#10);
  566.   end;
  567.   OvrInit(EXEName);
  568.   OvrSetBuf(58 * 1024);
  569.   if OvrResult <> ovrOk then
  570.   begin
  571.     PrintStr('No overlays found in .EXE file.  Must use MKRDEMO.BAT to build.'#13#10);
  572.     Halt(1);
  573.   end;
  574.   Demo.Init;
  575.   Demo.Run;
  576.   Demo.Done;
  577. end.
  578.