home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Pascal / BPASCAL.700 / D12 / GREPTV.ZIP / TVGREP.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1992-10-01  |  20.0 KB  |  832 lines

  1. {************************************************}
  2. {                                                }
  3. {   Turbo Vision Grep Demo                       }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. program TVGrep;
  9.  
  10. {$V-}
  11.  
  12. uses Dos, Strings, Objects, Drivers, Memory, Views, Menus, Dialogs, App,
  13.   MsgBox, HelpFile, GrepDlg, Regexp;
  14.  
  15. const
  16.   cmFindNext = 100;
  17.   cmFindPrev = 101;
  18.  
  19.   cmAbout = 1000;
  20.   cmView  = 1001;
  21.   cmStart = 1002;
  22.  
  23. const
  24.   cmUpdateStatus = 2000;
  25.   cmCloseResult  = 2001;
  26.  
  27. const
  28.   hcSearchWindow = 10;
  29.  
  30. type
  31.   PStatusView = ^TStatusView;
  32.   TStatusView = object(TView)
  33.     Message: String;
  34.     CurrentFile: PathStr;
  35.     constructor Init(var Bounds: TRect; const AMessage: String);
  36.     procedure Draw; virtual;
  37.     procedure HandleEvent(var Event: TEvent); virtual;
  38.   end;
  39.  
  40.   PStatusWindow = ^TStatusWindow;
  41.   TStatusWindow = object(TWindow)
  42.     constructor Init(const Message: String);
  43.   end;
  44.  
  45.   PResultViewer = ^TResultViewer;
  46.   TResultViewer = object(TListViewer)
  47.     Results: PStringCollection;
  48.     constructor Init(var Bounds: TRect; ScrollBar: PScrollBar;
  49.       AResults: PStringCollection);
  50.     destructor Done; virtual;
  51.     function GetText(Item: Integer; MaxLen: Integer): String; virtual;
  52.     procedure SelectItem(Item: Integer); virtual;
  53.   end;
  54.  
  55.   PResultDialog = ^TResultDialog;
  56.   TResultDialog = object(TDialog)
  57.     Request: TRequest;
  58.     FileList: PResultViewer;
  59.     constructor Init(const ARequest: TRequest; Results: PStringCollection);
  60.     destructor Done; virtual;
  61.     procedure HandleEvent(var Event: TEvent); virtual;
  62.   end;
  63.  
  64.   PLine = ^TLine;
  65.   TLine = object(TObject)
  66.     Line: PChar;
  67.     Hits: TRegMatch;
  68.     constructor Init(ALine: PChar; Regex: HRegexp; CaseSensitive: Boolean);
  69.     destructor Done; virtual;
  70.   end;
  71.  
  72.   PSearchViewer = ^TSearchViewer;
  73.   TSearchViewer = object(TScroller)
  74.     Lines: PCollection;
  75.     IsValid: Boolean;
  76.     Cur: Integer;
  77.     NumFinds: Integer;
  78.     constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar;
  79.       var AFileName: PathStr; const Request: TRequest);
  80.     destructor Done; virtual;
  81.     procedure CenterFind;
  82.     procedure Draw; virtual;
  83.     procedure FindNext;
  84.     procedure FindPrev;
  85.     procedure HandleEvent(var Event: TEvent); virtual;
  86.     procedure ReadFile(var FName: PathStr; Regex: HRegexp;
  87.       CaseSensitive: Boolean);
  88.     procedure SetState(AState: Word; Enable: Boolean); virtual;
  89.     procedure UpdateCommands;
  90.     function Valid(Command: Word): Boolean; virtual;
  91.   end;
  92.  
  93.   PSearchWindow = ^TSearchWindow;
  94.   TSearchWindow = object(TWindow)
  95.     ResultDlg: PResultDialog;
  96.     constructor Init(var Bounds: TRect; var AFilename: PathStr;
  97.       var Request: TRequest; AResultDlg: PResultDialog);
  98.     procedure HandleEvent(var Event: TEvent); virtual;
  99.   end;
  100.  
  101.   TSearch = object(TApplication)
  102.     Request: TRequest;
  103.     constructor Init;
  104.     procedure DoSearch;
  105.     procedure GetEvent(var Event: TEvent); virtual;
  106.     function  GetPalette: PPalette; virtual;
  107.     procedure HandleEvent(var Event: TEvent); virtual;
  108.     procedure Idle; virtual;
  109.     procedure InitMenuBar; virtual;
  110.     procedure InitStatusLine; virtual;
  111.     procedure GetRequest;
  112.   end;
  113.  
  114. { Utility functions }
  115.  
  116. function CalcPath(FileName: PathStr): DirStr;
  117. var
  118.   EXEName: PathStr;
  119.   Dir: DirStr;
  120.   Name: NameStr;
  121.   Ext: ExtStr;
  122. begin
  123.   if Lo(DosVersion) >= 3 then EXEName := ParamStr(0)
  124.   else EXEName := FSearch(FileName, GetEnv('PATH'));
  125.   FSplit(EXEName, Dir, Name, Ext);
  126.   if Dir[Length(Dir)] = '\' then Dec(Dir[0]);
  127.   CalcPath := Dir;
  128. end;
  129.  
  130. function CalcHelpName: PathStr;
  131. var
  132.   EXEName: PathStr;
  133.   Dir: DirStr;
  134.   Name: NameStr;
  135.   Ext: ExtStr;
  136. begin
  137.   Dir := CalcPath('TVGREP.EXE');
  138.   CalcHelpName := FSearch('TVGREP.HLP', Dir);
  139. end;
  140.  
  141. { TStatusView }
  142.  
  143. constructor TStatusView.Init(var Bounds: TRect; const AMessage: String);
  144. begin
  145.   inherited Init(Bounds);
  146.   CurrentFile := '';
  147.   Message := AMessage;
  148.   EventMask := EventMask or evBroadcast;
  149. end;
  150.  
  151. procedure TStatusView.Draw;
  152. var
  153.   S: String;
  154.   B: TDrawBuffer;
  155.   Color: Byte;
  156.   J: Integer;
  157. begin
  158.   Color := GetColor(6);
  159.   S := Message + CurrentFile;
  160.   MoveChar(B, ' ', Color, Size.X);
  161.   J := (Size.X - Length(S)) div 2;
  162.   if J < 0 then J := 0;
  163.   MoveStr(B, S, Color);
  164.   WriteLine(0, 0, Size.X, Size.Y, B);
  165. end;
  166.  
  167. procedure TStatusView.HandleEvent(var Event: TEvent);
  168. begin
  169.   inherited HandleEvent(Event);
  170.   case Event.What of
  171.     evBroadcast:
  172.       case Event.Command of
  173.         cmUpdateStatus:
  174.           begin
  175.             CurrentFile := PString(Event.InfoPtr)^;
  176.             DrawView;
  177.           end;
  178.       end;
  179.   end;
  180. end;
  181.  
  182. { TStatusWindow }
  183.  
  184. constructor TStatusWindow.Init(const Message: String);
  185. var
  186.   Bounds: TRect;
  187. begin
  188.   Bounds.Assign(0, 0, 60, 5);
  189.   inherited Init(Bounds, 'Status', wnNoNumber);
  190.   Options := Options or ofCentered;
  191.   Flags := 0;
  192.   Bounds.Assign(2, 2, 58, 3);
  193.   Insert(New(PStatusView, Init(Bounds, Message)));
  194. end;
  195.  
  196. { TResultViewer }
  197.  
  198. constructor TResultViewer.Init(var Bounds: TRect; ScrollBar: PScrollBar;
  199.   AResults: PStringCollection);
  200. begin
  201.   inherited Init(Bounds, 1, nil, ScrollBar);
  202.   Results := AResults;
  203.   SetRange(Results^.Count);
  204. end;
  205.  
  206. destructor TResultViewer.Done;
  207. begin
  208.   inherited Done;
  209.   Dispose(Results, Done);
  210. end;
  211.  
  212. function TResultViewer.GetText(Item: Integer; MaxLen: Integer): String;
  213. begin
  214.   GetText := PString(Results^.At(Item))^
  215. end;
  216.  
  217. procedure TResultViewer.SelectItem(Item: Integer);
  218. var
  219.   Event: TEvent;
  220. begin
  221.   Event.What := evCommand;
  222.   Event.Command := cmView;
  223.   PutEvent(Event);
  224. end;
  225.  
  226. { TResultDialog }
  227.  
  228. constructor TResultDialog.Init(const ARequest: TRequest;
  229.   Results: PStringCollection);
  230. var
  231.   R: TRect;
  232.   C: PView;
  233.   S: PScrollBar;
  234. begin
  235.   R.Assign(0, 0, 50, 17);
  236.   inherited Init(R, 'Search Results');
  237.   Options := Options or ofCentered;
  238.   Palette := dpBlueDialog;
  239.   Request := ARequest;
  240.  
  241.   R.Assign(1, 1, 49, 4);
  242.   C := New(PStaticText, Init(R, ''));
  243.   with C^ do Options := Options or ofFramed;
  244.   Insert(C);
  245.  
  246.   R.Assign(3, 1, 48, 2);
  247.   Insert(New(PStaticText, Init(R, 'Expression: ' + ARequest.Expression)));
  248.  
  249.   R.Move(0, 1);
  250.   Insert(New(PStaticText, Init(R, 'File mask:  ' + ARequest.FileMask)));
  251.  
  252.   R.Move(0, 1);
  253.   Insert(New(PStaticText, Init(R, 'Directory:  ' + ARequest.StartDir)));
  254.  
  255.   R.Assign(46, 7, 47, 13);
  256.   S := New(PScrollBar, Init(R));
  257.   Insert(S);
  258.  
  259.   R.Assign(3, 7, 46, 13);
  260.   FileList := New(PResultViewer, Init(R, S, Results));
  261.   Insert(FileList);
  262.  
  263.   R.Assign(2, 6, 8, 7);
  264.   Insert(New(PLabel, Init(R, '~F~iles', FileList)));
  265.  
  266.   R.Assign(37, 14, 47, 16);
  267.   Insert(New(PButton, Init(R, '~V~iew', cmView, bfDefault)));
  268.   SelectNext(False);
  269. end;
  270.  
  271. destructor TResultDialog.Done;
  272. begin
  273.   Message(Desktop, evBroadcast, cmCloseResult, @Self);
  274.   inherited Done;
  275. end;
  276.  
  277. procedure TResultDialog.HandleEvent(var Event: TEvent);
  278. var
  279.   R: TRect;
  280. begin
  281.   inherited HandleEvent(Event);
  282.   case Event.What of
  283.     evCommand:
  284.       case Event.Command of
  285.         cmView:
  286.           begin
  287.             Desktop^.GetExtent(R);
  288.             if FileLIst^.Results^.Count > 0 then
  289.               Application^.InsertWindow(New(PSearchWindow,
  290.                 Init(R, PString(FileList^.Results^.At(FileList^.Focused))^,
  291.                   Request, @Self)));
  292.             ClearEvent(Event);
  293.           end;
  294.       end;
  295.   end;
  296. end;
  297.  
  298. { TLine }
  299.  
  300. constructor TLine.Init(ALine: PChar; Regex: HRegexp; CaseSensitive: Boolean);
  301. begin
  302.   inherited Init;
  303.   Line := StrNew(ALine);
  304.  
  305.   if not CaseSensitive then StrUpper(ALine);
  306.   if RegExec(Regex, ALine, Hits) <> 0 then
  307.     FillChar(Hits, SizeOf(Hits), $FF);
  308. end;
  309.  
  310. destructor TLine.Done;
  311. begin
  312.   StrDispose(Line);
  313. end;
  314.  
  315. { TSearchViewer }
  316.  
  317. constructor TSearchViewer.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar;
  318.   var AFileName: PathStr; const Request: TRequest);
  319. var
  320.   Exp: array[0..255] of Char;
  321.   Regex: HRegexp;
  322.   Error: Integer;
  323.  
  324.   procedure DoCount(P: PLine); far;
  325.   begin
  326.     if P^.Hits.Start <> $FFFF then Inc(NumFinds);
  327.   end;
  328.  
  329. begin
  330.   inherited Init(Bounds, AHScrollBar, AVScrollBar);
  331.   GrowMode := gfGrowHiX + gfGrowHiY;
  332.   Lines := New(PCollection, Init(10, 10));
  333.   IsValid := True;
  334.  
  335.   StrPCopy(Exp, Request.Expression);
  336.   if Request.Options and roCase = 0 then StrUpper(Exp);
  337.   Regex := RegComp(Exp, Error);
  338.   ReadFile(AFileName, Regex, Request.Options and roCase <> 0);
  339.   RegFree(Regex);
  340.  
  341.   Lines^.ForEach(@DoCount);
  342.   Cur := 1;
  343. end;
  344.  
  345. destructor TSearchViewer.Done;
  346. begin
  347.   inherited Done;
  348.   Dispose(Lines, Done);
  349. end;
  350.  
  351. procedure TSearchViewer.CenterFind;
  352. var
  353.   CurFind: Integer;
  354.   Line: Integer;
  355.  
  356.   function IsFind(P: PLine): Boolean; far;
  357.   begin
  358.     Inc(Line);
  359.     if P^.Hits.Start <> $FFFF then Dec(CurFind);
  360.     IsFind := CurFind = 0;
  361.   end;
  362.  
  363. begin
  364.   CurFind := Cur;
  365.   Line := 0;
  366.   Lines^.FirstThat(@IsFind);
  367.   { Center on the screen }
  368.   Line := Line - Size.Y div 2;
  369.   if Line < 0 then Line := 0;
  370.   if Line > Limit.Y then Line := Limit.Y - Size.Y;
  371.   ScrollTo(0, Line);
  372. end;
  373.  
  374. procedure TSearchViewer.Draw;
  375. var
  376.   B: TDrawBuffer;
  377.   C: Word;
  378.   I, J: Integer;
  379.   S: String;
  380.   P: PLine;
  381.   HitBeg, HitEnd: Word;
  382. begin
  383.   C := GetColor($0201);
  384.   for I := 0 to Size.Y - 1 do
  385.   begin
  386.     MoveChar(B, ' ', C, Size.X);
  387.     HitBeg := $FFFF;
  388.     if Delta.Y + I < Lines^.Count then
  389.     begin
  390.       P := Lines^.At(Delta.Y + I);
  391.       S := '';
  392.       if (P <> nil) and (P^.Line <> nil) then
  393.         with P^ do
  394.         begin
  395.           if StrLen(Line) > Delta.X then
  396.           begin
  397.             S := StrPas(@Line[Delta.X]);
  398.             if Hits.Start <> $FFFF then
  399.             begin
  400.               if Hits.Stop > Delta.X then
  401.               begin
  402.                 HitEnd := Hits.Stop - Delta.X - 1;
  403.                 if Hits.Start < Delta.X then
  404.                   HitBeg := 0;
  405.               end;
  406.               if Hits.Start >= Delta.X then
  407.                 HitBeg := Hits.Start - Delta.X;
  408.             end;
  409.           end;
  410.         end;
  411.       MoveStr(B, S, C);
  412.       if HitBeg <> $FFFF then
  413.         for J := HitBeg to HitEnd do
  414.           WordRec(B[J]).Hi := WordRec(C).Hi;
  415.     end;
  416.     WriteLine(0, I, Size.X, 1, B);
  417.   end;
  418. end;
  419.  
  420. procedure TSearchViewer.FindNext;
  421. begin
  422.   if Cur < NumFinds then Inc(Cur);
  423.   CenterFind;
  424.   UpdateCommands;
  425. end;
  426.  
  427. procedure TSearchViewer.FindPrev;
  428. begin
  429.   if Cur > 1 then Dec(Cur);
  430.   CenterFind;
  431.   UpdateCommands;
  432. end;
  433.  
  434. procedure TSearchViewer.HandleEvent(var Event: TEvent);
  435. begin
  436.   inherited HandleEvent(Event);
  437.   case Event.What of
  438.     evCommand:
  439.       case Event.Command of
  440.         cmFindPrev: FindPrev;
  441.         cmFindNext: FindNext;
  442.       end;
  443.   end;
  444. end;
  445.  
  446. procedure TSearchViewer.ReadFile(var FName: PathStr; Regex: HRegexp;
  447.   CaseSensitive: Boolean);
  448. var
  449.   FileToSearch: Text;
  450.   Line: array[0..255] of Char;
  451.   MaxWidth: Integer;
  452.   E: TEvent;
  453.   W: PWindow;
  454. begin
  455.   IsValid := True;
  456.  
  457.   {$I-}
  458.   Assign(FileToSearch, FName);
  459.   Reset(FileToSearch);
  460.   if IOResult <> 0 then
  461.   begin
  462.     MessageBox('Cannot open file ' + FName + '.', nil, mfError + mfOkButton);
  463.     IsValid := False;
  464.   end
  465.   else
  466.   begin
  467.     W := Application^.InsertWindow(New(PStatusWindow, Init('Loading: ')));
  468.     Message(W, evBroadcast, cmUpdateStatus, @FName);
  469.     MaxWidth := 0;
  470.     while not Eof(FileToSearch) and not LowMemory do
  471.     begin
  472.       Readln(FileToSearch, Line);
  473.       if StrLen(Line) > MaxWidth then MaxWidth := StrLen(Line);
  474.       Lines^.Insert(New(PLine, Init(Line, Regex, CaseSensitive)));
  475.     end;
  476.     Close(FileToSearch);
  477.     Dispose(W, Done);
  478.   end;
  479.   {$I+}
  480.   SetLimit(MaxWidth, Lines^.Count);
  481. end;
  482.  
  483. procedure TSearchViewer.SetState(AState: Word; Enable: Boolean);
  484. begin
  485.   inherited SetState(AState, Enable);
  486.   case AState of
  487.     sfActive: UpdateCommands;
  488.     sfExposed:
  489.       if Enable then CenterFind;
  490.   end;
  491. end;
  492.  
  493. procedure TSearchViewer.UpdateCommands;
  494. begin
  495.   SetCmdState([cmFindNext], (State and sfActive <> 0) and (Cur < NumFinds));
  496.   SetCmdState([cmFindPrev], (State and sfActive <> 0) and (Cur > 1));
  497. end;
  498.  
  499. function TSearchViewer.Valid(Command: Word): Boolean;
  500. begin
  501.   Valid := IsValid;
  502. end;
  503.  
  504. { TSearchWindow }
  505.  
  506. constructor TSearchWindow.Init(var Bounds: TRect; var AFilename: PathStr;
  507.   var Request: TRequest; AResultDlg: PResultDialog);
  508. var
  509.   C: PView;
  510.   S: PScrollBar;
  511.   R, R1: TRect;
  512. begin
  513.   inherited Init(Bounds, AFilename, wnNoNumber);
  514.   ResultDlg := AResultDlg;
  515.   Options := Options or ofTileable;
  516.   HelpCtx := hcSearchWindow;
  517.  
  518. {  HelpCtx := hcSearchWindow;}
  519.  
  520.   GetExtent(R);
  521.   R.Grow(-1, -1);
  522.   R.B.Y := R.A.Y + 1;
  523.   C := New(PStaticText, Init(R, 'Expression: ' + Request.Expression));
  524.   with C^ do
  525.   begin
  526.     Options := Options or ofFramed;
  527.     GrowMode := gfGrowHiX;
  528.   end;
  529.   Insert(C);
  530.  
  531.   GetExtent(R);
  532.   R.Grow(-1, -2);
  533.   R.Move(0, 1);
  534.   R1.Assign(R.B.X, R.A.Y, R.B.X + 1, R.B.Y);
  535.   S := New(PScrollBar, Init(R1));
  536.   with S^ do Options := Options or ofPostProcess;
  537.   Insert(S);
  538.   Insert(New(PSearchViewer, Init(R,
  539.     StandardScrollBar(sbHorizontal + sbHandleKeyboard), S, AFilename,
  540.       Request)));
  541. end;
  542.  
  543. procedure TSearchWindow.HandleEvent(var Event: TEvent);
  544. begin
  545.   inherited HandleEvent(Event);
  546.   case Event.What of
  547.     evBroadcast:
  548.       case Event.Command of
  549.         cmCloseResult:
  550.           if Event.InfoPtr = ResultDlg then Close;
  551.       end;
  552.   end;
  553. end;
  554.  
  555. { TSearch }
  556.  
  557. constructor TSearch.Init;
  558. var
  559.   Event: TEvent;
  560.   R: TRect;
  561. begin
  562.   inherited Init;
  563.  
  564.   with Request do
  565.   begin
  566.     Expression := '';
  567.     FileMask := '*.PAS';
  568.     GetDir(0, StartDir);
  569.     Options := $00;
  570.   end;
  571.  
  572.   Event.What := evCommand;
  573.   Event.Command := cmStart;
  574.   PutEvent(Event);
  575. end;
  576.  
  577. procedure TSearch.DoSearch;
  578. var
  579.   Result: PStringCollection;
  580.   Exp: array[0..255] of Char;
  581.   W: PWindow;
  582.   Regex: HRegexp;
  583.   Error: Integer;
  584.  
  585.   function Search(const Filename: String): Boolean;
  586.   var
  587.     TextFile: Text;
  588.     Line: array[0..255] of Char;
  589.     Match: TRegMatch;
  590.   begin
  591.     Search := False;
  592.     Message(Desktop, evBroadcast, cmUpdateStatus, @Filename);
  593.     Assign(TextFile, Filename);
  594.     {$I-}
  595.     Reset(TextFile);
  596.     while not Eof(TextFile) do
  597.     begin
  598.       Readln(TextFile, Line);
  599.       if Request.Options and roCase = 0 then StrUpper(Line);
  600.       if RegExec(Regex, Line, Match) = 0 then
  601.       begin
  602.         Search := True;
  603.         Break;
  604.       end;
  605.     end;
  606.     Close(TextFile);
  607.   end;
  608.  
  609.   procedure SearchDir(const Dir: PathStr);
  610.   var
  611.     SR: SearchRec;
  612.   begin
  613.     with Request do
  614.     begin
  615.       FindFirst(Dir + FileMask, Archive, SR);
  616.       while DosError = 0 do
  617.       begin
  618.         if Search(Dir + SR.Name) then
  619.           Result^.Insert(NewStr(Dir + SR.Name));
  620.         FindNext(SR);
  621.       end;
  622.  
  623.       if Request.Options and roSubDir <> 0 then
  624.       begin
  625.         FindFirst(Dir + '*.*', Directory, SR);
  626.         while DosError = 0 do
  627.         begin
  628.           if (SR.Attr and Directory <> 0) and (SR.Name[1] <> '.') then
  629.             SearchDir(Dir + SR.Name + '\');
  630.           FindNext(SR);
  631.         end;
  632.       end;
  633.     end;
  634.   end;
  635.  
  636. begin
  637.   W := InsertWindow(New(PStatusWindow, Init('Searching: ')));
  638.  
  639.   if W <> nil then
  640.   begin
  641.     Result := New(PStringCollection, Init(5, 5));
  642.  
  643.     StrPCopy(Exp, Request.Expression);
  644.     if Request.Options and roCase = 0 then StrUpper(Exp);
  645.  
  646.     Regex := RegComp(Exp, Error);
  647.     SearchDir(Request.StartDir);
  648.     Dispose(W, Done);
  649.     RegFree(Regex);
  650.  
  651.     InsertWindow(New(PResultDialog, Init(Request, Result)));
  652.   end;
  653. end;
  654.  
  655. function TSearch.GetPalette: PPalette;
  656. const
  657.   CNewColor = CAppColor + CHelpColor;
  658.   CNewBlackWhite = CAppBlackWhite + CHelpBlackWhite;
  659.   CNewMonochrome = CAppMonochrome + CHelpMonochrome;
  660.   P: array[apColor..apMonochrome] of string[Length(CNewColor)] =
  661.     (CNewColor, CNewBlackWhite, CNewMonochrome);
  662. begin
  663.   GetPalette := @P[AppPalette];
  664. end;
  665.  
  666. procedure TSearch.Idle;
  667.  
  668.   function IsTileable(P: PView): Boolean; far;
  669.   begin
  670.     IsTileable := P^.Options and ofTileable <> 0;
  671.   end;
  672.  
  673. begin
  674.   inherited Idle;
  675.   if Desktop^.FirstThat(@IsTileable) <> nil then
  676.     EnableCommands([cmTile, cmCascade, cmCloseAll])
  677.   else
  678.     DisableCommands([cmTile, cmCascade, cmCloseAll]);
  679. end;
  680.  
  681. procedure TSearch.GetEvent(var Event: TEvent);
  682. var
  683.   W: PView;
  684.   HFile: PHelpFile;
  685.   HelpStrm: PDosStream;
  686.   AName: String;
  687. const
  688.   HelpInUse: Boolean = False;
  689. begin
  690.   inherited GetEvent(Event);
  691.   case Event.What of
  692.     evCommand:
  693.       if (Event.Command = cmHelp) and not HelpInUse then
  694.       begin
  695.         HelpInUse := True;
  696.         AName := CalcHelpName;
  697.         HelpStrm := New(PDosStream, Init(AName, stOpenRead));
  698.         HFile := New(PHelpFile, Init(HelpStrm));
  699.         if HelpStrm^.Status <> stOk then
  700.           MessageBox('Could not open help file.', nil, mfError + mfOkButton)
  701.         else
  702.         begin
  703.           W := ValidView(New(PHelpWindow, Init(HFile, GetHelpCtx)));
  704.           if W <> nil then
  705.           begin
  706.             ExecView(W);
  707.             Dispose(W, Done);
  708.           end;
  709.         end;
  710.         Dispose(HFile, Done);
  711.         HelpInUse := False;
  712.         ClearEvent(Event);
  713.       end;
  714.   end;
  715. end;
  716.  
  717. procedure TSearch.HandleEvent(var Event: TEvent);
  718.  
  719.   procedure About;
  720.   var
  721.     D: PDialog;
  722.     R: TRect;
  723.   begin
  724.     R.Assign(0, 0, 50, 9);
  725.     D := New(PDialog, Init(R, 'About'));
  726.     with D^ do begin
  727.       Options := Options or ofCentered;
  728.       R.Grow(-1, -1);
  729.       Dec(R.B.Y, 3);
  730.       Insert(New(PStaticText, Init(R,
  731.         #13 +
  732.         ^C'TVGrep' + #13 +
  733.         ^C'A Text Search Program' + #13 +
  734.         ^C'Copyright (c) 1992 Borland International'
  735.         )));
  736.       R.Assign(20, 6, 30, 8);
  737.       Insert(New(PButton, Init(R, 'O~K', cmOk, bfDefault)));
  738.     end;
  739.  
  740.     ExecuteDialog(D, nil);
  741.   end;
  742.  
  743.  
  744. begin
  745.   inherited HandleEvent(Event);
  746.   if Event.What = evCommand then
  747.   begin
  748.     case Event.Command of
  749.       cmStart: GetRequest;
  750.       cmAbout: About;
  751.       {cmViewFile: FileView(Event.InfoPtr);}
  752.     else
  753.       Exit;
  754.     end;
  755.     ClearEvent(Event);
  756.   end;
  757. end;
  758.  
  759. procedure TSearch.InitMenuBar;
  760. var
  761.   R: TRect;
  762. begin
  763.   GetExtent(R);
  764.   R.B.Y := R.A.Y + 1;
  765.   MenuBar := New(PMenuBar, Init(R, NewMenu(
  766.     NewSubMenu('~F~ile', hcNoContext, NewMenu(
  767.       NewItem('~S~tart grep...', 'F9', kbF9, cmStart, {hcGrepDialog}0,
  768.       NewLine(
  769.       NewItem('E~x~it', 'Alt+X', kbAltX, cmQuit, hcNoContext,
  770.       nil)))),
  771.     NewSubMenu('~W~indows', {hcWindows} 0, NewMenu(
  772.       StdWindowMenuItems(nil)),
  773.     NewSubMenu('~H~elp', {hcSystem} 0, NewMenu(
  774.       NewItem('~A~bout', '', kbNoKey, cmAbout, {hcSAbout} 0,
  775.       nil)),
  776.     nil))
  777.   ))));
  778. end;
  779.  
  780. procedure TSearch.InitStatusLine;
  781. var
  782.   R: TRect;
  783. begin
  784.   GetExtent(R);
  785.   R.A.Y := R.B.Y - 1;
  786.   StatusLine := New(PStatusLine, Init(R,
  787.     NewStatusDef(hcNoContext, {hcViewKey} 1,
  788.       NewStatusKey('', kbF10, cmMenu,
  789.       NewStatusKey('~F1~ Help', kbF1, cmHelp,
  790.       NewStatusKey('~Alt+X~ Exit', kbAltX, cmQuit,
  791.       NewStatusKey('~F9~ Start', kbF9, cmStart,
  792.       NewStatusKey('~Alt+F3~ Close', kbAltF3, cmClose,
  793.       StdStatusKeys(
  794.       nil)))))),
  795.     NewStatusDef(hcSearchWindow, hcSearchWindow,
  796.       NewStatusKey('', kbF10, cmMenu,
  797.       NewStatusKey('~F1~ Help', kbF1, cmHelp,
  798.       NewStatusKey('~Alt+X~ Exit', kbAltX, cmQuit,
  799.       NewStatusKey('~F9~ Start', kbF9, cmStart,
  800.       NewStatusKey('~Alt+F3~ Close', kbAltF3, cmClose,
  801.       NewStatusKey('~Alt+N~ Next', kbAltN, cmFindNext,
  802.       NewStatusKey('~Alt+P~ Prev', kbAltP, cmFindPrev,
  803.       StdStatusKeys(
  804.       nil)))))))),
  805.     nil))
  806.   ));
  807. end;
  808.  
  809. procedure TSearch.GetRequest;
  810. begin
  811.   if ExecuteDialog(New(PGrepDialog, Init), @Request) <> cmCancel then
  812.   begin
  813.     with Request do
  814.       if ((Length(StartDir) <> 2) or (StartDir[2] <> ':')) and
  815.         (StartDir[Length(StartDir)] <> '\') then
  816.       begin
  817.         Inc(StartDir[0]);
  818.         StartDir[Length(StartDir)] := '\';
  819.       end;
  820.     DoSearch;
  821.   end;
  822. end;
  823.  
  824. var
  825.   SearchApp: TSearch;
  826.  
  827. begin
  828.   SearchApp.Init;
  829.   SearchApp.Run;
  830.   SearchApp.Done;
  831. end.
  832.