home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / l / l040 / 1.ddi / TVGREP.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1992-10-27  |  19.4 KB  |  797 lines

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