{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,R+,S+,V-,X+}
{$M 16384,8192,655360}
Program WordSearch;

Uses FViewer, Objects, Menus, Dialogs, App, Views, Drivers, Crt;

CONST
   StringLength=10;
   InputLineLength=30;
   FileNameLength=40;
   WindowWidth=120;
   TextBufferSize=15000;
   LeadingChars=5000;
   CRLF: ARRAY[1..2] OF Char = #13#10;
   LineOfStars:ARRAY[1..81] OF Char='*******************************************************************************'#13#10;
   Spaces=
'                                                                                                                            ';

   hcFileMenu=1000;
   hcOpenOutputFile=1003;
   hcCloseOutputFile=1004;
   hcOutputToFile=1005;
   hcPrintOutputFile=1024;
   hcViewOutputFile=1025;
   hcSaveAll=1026;
   hcAboutBox=1006;
   hcExit=1007;
   hcSearchMenu=1008;
   hcViewFile=1025;
   hcWordSearch=1009;
   hcLogicalAndSearch=1010;
   hcOptionsMenu=1011;
   hcLogicalAndOptions=1012;
   hcSaveConfirmationOptions=1013;
   hcAutoWindowSizeOptions=1014;
   hcAutoTilingOptions=1021;
   hcSaveDivisionOptions=1022;
   hcSaveOptions=1023;
   hcWindowMenu=1015;
   hcZoom=1016;
   hcResize=1017;
   hcTile=1018;
   hcCascade=1019;
   hcNext=1020;
   hcTableOfContents=1027;
   hcClose=1099;

   hcSearchWindow=1200;
   hcInfoBox=1100;

   hcDialog=1101;
   hcNothing=1102;
   hcAutoText=1103;
   hcDialogOpt=1104;
   hcAndDialog=1106;
   hcNoAutoTile=1107;
   hcAutoTile=1108;
   hcNoDivision=1109;
   hcBlankLine=1110;
   hcStars=1111;
   hcNoAutoSize=1112;
   hcAutoSize=1113;
   hcFinalDialog=1199;

   hcBlank=65000;

   cmCloseOutputFile=101;
   cmWordSearch=102;
   cmAndSearch=103;
   cmOutputToFile=104;
   cmSaveAll=107;
   cmPrintOutputFile=105;
   cmViewOutputFile=106;

   cmOpenOutputFile=1001;
   cmLogicalAndOptions=1002;
   cmSaveConfirmationOptions=1003;
   cmAutoSizingOptions=1004;
   cmAutoTilingOptions=1005;
   cmSaveDivisionOptions=1006;
   cmSaveOptions=1007;
   cmAboutBox=1008;

   cmForward=200;
   cmBack=201;

   cmOverWrite=2000;
   cmAppend=2001;

   cmViewFile=3000;
   cmCabinet=3001;
   cmSenator=3002;
   cmSenasst=3003;
   cmRep=3004;
   cmRepAsst=3005;
   cmCmte=3006;
   cmFederal=3007;
   cmEmbassy=3008;
   cmLocal=3009;
   cmCourts=3010;
   cmStates=3011;
   cmCorp=3012;
   cmFinance=3013;
   cmEstate=3014;
   cmLabor=3015;
   cmInterest=3016;
   cmThink=3017;
   cmAssn=3018;
   cmLaw=3019;
   cmConsult=3020;
   cmPrad=3021;
   cmClub=3022;
   cmTV=3023;
   cmNewsServ=3024;
   cmRadio=3025;
   cmMedia=3026;
   cmPub=3027;
   cmMag=3028;
   cmNewsLet=3029;
   cmSynCol=3030;
   cmPaper=3031;
   cmForeign=3032;

   ToC:ARRAY[cmViewFile..cmForeign] OF Word =
       (0,                              {view file}
        0,0,0,0,0,0,0,0,0,0,0,          {government}
        0,3686,4762,5562,6020,7534,     {corporate}
        0,0,0,0,0,                      {professional}
        0,0,0,0,0,0,0,0,0,0);           {media}


   SearchCommands=[cmWordSearch,cmAndSearch];
   OutputCommands=[cmSaveAll,cmOutputToFile];
   CloseOutputCommands=[cmViewOutputFile,cmPrintOutputFile,cmCloseOutputFile];

   MaxWords = $FFF0 DIV SizeOf(Word);
   MaxAndRecs = MaxWords DIV 2;
   MaxAndWords = 4;

TYPE
   Str10=String[StringLength];
   Str30=String[InputLineLength+1];
   Str50=String[FileNameLength];
   HighlightArray=ARRAY[1..4] OF Str30;
   FinalRec =
      RECORD
         WordStr  :Str10;
         FirstAddr:LongInt;
         Occur    :Word;
      END;

   AndRec =
      RECORD
         Lo,High:Word;
      END;

   AddrRecordPtr=^AddrRecord;
   AddrRecord = Array[1..MaxWords] OF Word;

   AndRecPtr=^AndRecs;
   AndRecs=ARRAY[1..MaxAndRecs] OF AndRec;

   PFileStatusLine=^TFileStatusLine;
   TFileStatusLine=Object(TView)
         PrevStr:String[82];
         CONSTRUCTOR Init;
         PROCEDURE   Draw; VIRTUAL;
      END;

   PHintStatusLine=^THintStatusLine;
   THintStatusLine=Object(TStatusLine)
         FUNCTION Hint(HC:Word):String; VIRTUAL;
      END;

   POverwriteWarning=^TOverwriteWarning;
   TOverwriteWarning=Object(TDialog)
         CONSTRUCTOR Init(BadFN:Str50);
         PROCEDURE   HandleEvent(var Event:TEvent); VIRTUAL;
      END;

   PGetSearchWordDialog=^TGetSearchWordDialog;
   TGetSearchWordDialog=Object(TDialog)
         CONSTRUCTOR Init;
      END;

   PGetSearchWordsDialog=^TGetSearchWordsDialog;
   TGetSearchWordsDialog=Object(TDialog)
         CONSTRUCTOR Init;
      END;

   PTextFileWindow=^TTextFileWindow;
   TTextFileWindow=Object(TWindow)
         CONSTRUCTOR Init(var Bounds:TRect; WinTitle:String;ListStart:AddrRecordPtr;ListLen:Word;
                              HighLightStr:HighlightArray;NumOfWords:Byte);
         DESTRUCTOR  Done; VIRTUAL;
      END;

   PTextFileInterior=^TTextFileInterior;
   TTextFileInterior=Object(TScroller)
         TextFile  :FILE;
         LineIndex :FILE OF LongInt;
         TextBuffer:ARRAY[1..TextBufferSize] OF Char;
         LineBuffer:ARRAY[0..22,0..MaxViewWidth-1] OF Word;
         BufStart,
         BufStop   :Longint;
         LastLine,
         LineBufStart,
         LineBufEnd:Longint;{longint instead of word so -1 can be used as flag}
         Address   :AddrRecordPtr;
         CurrAddr,
         NumOfAddr :Word;
         SearchStr :HighlightArray;
         NumOfWords:Byte;
         CONSTRUCTOR Init(var Bounds:TRect; AHScrollBar, AVScrollBar:PScrollBar;ListStart:AddrRecordPtr;
                          ListLen:Word;HighLightStr:HighlightArray;NumOfWrds:Byte);
         PROCEDURE   Draw; VIRTUAL;
         PROCEDURE   AutoSize;
         PROCEDURE   ReadBuffer(StartAddress:LongInt);
         PROCEDURE   HandleEvent(var Event:TEvent); VIRTUAL;
         DESTRUCTOR  Done; VIRTUAL;
      END;

   PSaveConfirmationOptions=^TSaveConfirmationOptions;
   TSaveConfirmationOptions=Object(TDialog)
         CONSTRUCTOR Init;
      END;

   PLogicalAndOptions=^TLogicalAndOptions;
   TLogicalAndOptions=Object(TDialog)
         CONSTRUCTOR Init;
      END;

   PAutoTilingOptions=^TAutoTilingOptions;
   TAutoTilingOptions=Object(TDialog)
         CONSTRUCTOR Init;
      END;

   PAutoSizingOptions=^TAutoSizingOptions;
   TAutoSizingOptions=Object(TDialog)
         CONSTRUCTOR Init;
      END;

   PSaveDivisionOptions=^TSaveDivisionOptions;
   TSaveDivisionOptions=Object(TDialog)
         CONSTRUCTOR Init;
      END;

   WordSearchObj=Object(TApplication)
         {administrative bunginess}
         FileStatusLine:PFileStatusLine;
         CONSTRUCTOR Init;
         PROCEDURE   InitMenuBar; VIRTUAL;
         PROCEDURE   InitStatusLine; VIRTUAL;
         PROCEDURE   HandleEvent(var Event: TEvent); VIRTUAL;
         PROCEDURE   Idle; VIRTUAL;
         {REAL bunginess}
         FUNCTION  NotEnoughMemory:Boolean;
         FUNCTION  AskFileName(Question:String;var Answer:Str50):Word;
         PROCEDURE OpenTextFile;
         PROCEDURE OpenOutputFile;
         PROCEDURE CloseOutputFile;
         PROCEDURE PrintOutputFile;
         PROCEDURE ViewOutputFile;
         PROCEDURE AboutBox;
         PROCEDURE ViewFile(ToCNum:Word);
         PROCEDURE WordSearch;
         PROCEDURE LogicalAndSearch;
         PROCEDURE LogicalAndOptions;
         PROCEDURE SaveConfirmationOptions;
         PROCEDURE AutoTilingOptions;
         PROCEDURE AutoSizingOptions;
         PROCEDURE SaveDivisionOptions;
         PROCEDURE SaveOptions;
      END;

   ConfirmationTypes=(None,AutoText,DialogBox);
   OKButtonTypes=(OKButton,NoOKButton);
   DivisionTypes=(Nothing,BlankLine,Stars);

   OptionRec = RECORD
      LogicalAndDistance :Byte;
      SaveConfirmation   :ConfirmationTypes;
      SaveDivision       :DivisionTypes;
      AutoTiling,
      AutoSizing         :Boolean;
   END;

VAR {global variables}
   TextFileName,
   OutputFileName,
   Ind1FileName,
   Ind2FileName,
   Ind3FileName      : String[FileNameLength];
   TextFileNameD,
   OutputFileNameD   : String[17];
   NewFile,
   FilesGone,
   OutputFileSelected: Boolean;
   HiColor           : Byte;
   MyOptions         : OptionRec;

{********************administrative bunginess********************************}

CONSTRUCTOR WordSearchObj.Init;
   VAR
      OptionFile :FILE OF OptionRec;
   BEGIN
      OpenTextFile;
      IF FilesGone THEN Exit;
      TApplication.Init;
      OutputFileSelected:=FALSE;
      OutputFileNameD:='No file selected';
      Assign(OptionFile,'wrdsrch.cfg');
      {$I-} Reset(OptionFile); {$I+}
      IF IOResult > 0 THEN
         BEGIN
            MyOptions.SaveConfirmation:=DialogBox;
            MyOptions.LogicalAndDistance:=5;
            MyOptions.AutoTiling:=TRUE;
            MyOptions.AutoSizing:=FALSE;
            MyOptions.SaveDivision:=BlankLine;
         END
      ELSE
         BEGIN
            Read(OptionFile,MyOptions);
            Close(OptionFile);
         END;
      EnableCommands(SearchCommands);
      DisableCommands(OutputCommands);
      DisableCommands(CloseOutputCommands);
      FileStatusLine:=New(PFileStatusLine, Init);
      Insert(FileStatusLine);
      IF ScreenMode=smCO80 THEN HiColor:=119 ELSE HiColor:=127;
      AboutBox;
   END;

PROCEDURE WordSearchObj.InitMenuBar;
   VAR
      R  : TRect;
   BEGIN
      GetExtent(R);
      R.B.Y:=R.A.Y+1;
      MenuBar:=New(PMenuBar, Init(R, NewMenu(
         NewSubMenu('~F~ile',hcFileMenu, NewMenu(
            NewItem('~V~iew The Capital Source','',kbNoKey,cmViewFile,hcViewFile,
            NewItem('Open A ~P~ersonal File','F3',kbF3,cmOpenOutputFile,hcOpenOutputFile,
            NewItem('~C~lose Personal File','Shift-F3',kbShiftF3,cmCloseOutputFile,hcCloseOutputFile,
            NewItem('~S~ave Window to Personal File','F10',kbF10,cmOutputToFile,hcOutputToFile,
            NewItem('Save ~A~ll Occurrences','Alt-F10', kbAltF10,cmSaveAll,hcSaveAll,
            NewItem('P~r~int Personal File','Shift-F10',kbShiftF10,cmPrintOutputFile,hcPrintOutputFile,
            NewItem('~E~xamine Personal File','',kbNoKey,cmViewOutputFile,hcViewOutputFile,
            NewLine(
            NewItem('A~b~out','',kbNoKey,cmAboutBox,hcAboutBox,
            NewItem('E~x~it','Alt-X',kbAltX,cmQuit,hcExit,
            nil))))))))))),
         NewSubMenu('~S~earch',hcSearchMenu, NewMenu(
            NewItem('~S~ingle-Word Search','F4',kbF4,cmWordSearch,hcWordSearch,
            NewItem('~M~ultiple-Word Search','Alt-F4',kbAltF4,cmAndSearch,hcLogicalAndSearch,
            nil))),
         NewSubMenu('~O~ptions',hcOptionsMenu, NewMenu(
            NewItem('~M~ultiple-Word Search Distance','',kbNoKey,cmLogicalAndOptions,hcLogicalAndOptions,
            NewItem('~S~ave Confirmation','',kbNoKey,cmSaveConfirmationOptions,hcSaveConfirmationOptions,
            NewItem('Auto ~W~indow Sizing','',kbNoKey,cmAutoSizingOptions,hcAutoWindowSizeOptions,
            NewItem('Auto ~T~iling', '', kbNoKey, cmAutoTilingOptions, hcAutoTilingOptions,
            NewItem('~D~ivision Between Saves', '', kbNoKey, cmSaveDivisionOptions, hcSaveDivisionOptions,
            NewLine(
            NewItem('Save ~O~ptions To Disk', '', kbNoKey, cmSaveOptions, hcSaveOptions,
            nil)))))))),
         NewSubMenu('~W~indow',hcWindowMenu, NewMenu(
            NewItem('~Z~oom','F5',kbF5,cmZoom,hcZoom,
            NewItem('~M~ove/Resize','Ctrl-F5',kbCtrlF5,cmResize,hcResize,
            NewItem('~T~ile','Alt-F5',kbAltF5,cmTile,hcTile,
            NewItem('c~A~scade','Shift-F5',kbShiftF5,cmCascade,hcCascade,
            NewItem('~N~ext','F6',kbF6,cmNext,hcNext,
            NewItem('~C~lose','Alt-F3',kbAltF3,cmClose,hcClose,
            nil))))))),
         NewSubMenu('~T~able of Contents', hcTableOfContents, NewMenu(
            NewSubMenu('Government', hcTableOfContents, NewMenu(
               NewItem('Cabinet','',kbNoKey,cmCabinet,hcTableOfContents,
               NewItem('Senate Members','',kbNoKey,cmSenator,hcTableOfContents,
               NewItem('Senate Aides','',kbNoKey,cmSenAsst,hcTableOfContents,
               NewItem('House Members','',kbNoKey,cmRep,hcTableOfContents,
               NewItem('House Aides','',kbNoKey,cmRepAsst,hcTableOfContents,
               NewItem('Committees','',kbNoKey,cmCmte,hcTableOfContents,
               NewItem('Federal Agencies','',kbNoKey,cmFederal,hcTableOfContents,
               NewItem('Embassies','',kbNoKey,cmEmbassy,hcTableOfContents,
               NewItem('DC Government','',kbNoKey,cmLocal,hcTableOfContents,
               NewItem('Courts','',kbNoKey,cmCourts,hcTableOfContents,
               NewItem('State Reps.','',kbNoKey,cmStates,hcTableOfContents,
               nil)))))))))))),
            NewSubMenu('Corporate', hcTableOfContents, NewMenu(
               NewItem('Corporate Offices','',kbNoKey,cmCorp,hcTableOfContents,
               NewItem('Financial Institutions','',kbNoKey,cmFinance,hcTableOfContents,
               NewItem('Real Estate Companies','',kbNoKey,cmEstate,hcTableOfContents,
               NewItem('Labor Unions','',kbNoKey,cmLabor,hcTableOfContents,
               NewItem('Interest Groups','',kbNoKey,cmInterest,hcTableOfContents,
               NewItem('Think Tanks','',kbNoKey,cmThink,hcTableOfContents,
               nil))))))),
            NewSubMenu('Professional', hcTableOfContents, NewMenu(
               NewItem('Trade/Professional Assn.','',kbNoKey,cmAssn,hcTableOfContents,
               NewItem('Law Firms','',kbNoKey,cmLaw,hcTableOfContents,
               NewItem('Political Consultants','',kbNoKey,cmConsult,hcTableOfContents,
               NewItem('PR/Advertising Companies','',kbNoKey,cmPrad,hcTableOfContents,
               NewItem('Private Clubs','',kbNoKey,cmClub,hcTableOfContents,
               nil)))))),
            NewSubMenu('Media', hcTableOfContents, NewMenu(
               NewItem('Television Stations','',kbNoKey,cmTV,hcTableOfContents,
               NewItem('News Services','',kbNoKey,cmNewsServ,hcTableOfContents,
               NewItem('Radio Stations','',kbNoKey,cmRadio,hcTableOfContents,
               NewItem('Media Organizations','',kbNoKey,cmMedia,hcTableOfContents,
               NewItem('Publishing Companies','',kbNoKey,cmPub,hcTableOfContents,
               NewItem('Magazines/Trade Journals','',kbNoKey,cmMag,hcTableOfContents,
               NewItem('Newsletters','',kbNoKey,cmNewsLet,hcTableOfContents,
               NewItem('Syndicated Columnists','',kbNoKey,cmSynCol,hcTableOfContents,
               NewItem('Daily Newspapers','',kbNoKey,cmPaper,hcTableOfContents,
               NewItem('Foreign Press','',kbNoKey,cmForeign,hcTableOfContents,
               nil))))))))))),
             nil))))),
      nil))))))));
   END;

PROCEDURE WordSearchObj.InitStatusLine;
   VAR
      R:TRect;
   BEGIN
      GetExtent(R);
      R.A.Y:=R.B.Y-1;
      StatusLine:=New(PHintStatusLine, Init(R,
         NewStatusDef(hcDragging, hcDragging,
            NewStatusKey('~'#24#25#26#27'~ Move', kbNoKey, cmError,
            NewStatusKey('~Shift-'#24#25#26#27'~ Resize', kbNoKey, cmError,
            NewStatusKey('~'#17#196#217'~ Done', kbNoKey, cmError,
            NewStatusKey('~Esc~ Cancel', kbNoKey, cmError,
            nil)))),
         NewStatusDef(hcNoContext, hcNoContext,
            NewStatusKey('~F1~ Menu', kbF1, cmMenu,
            NewStatusKey('~F4~ Single-Word Search', kbF4, cmWordSearch,
            NewStatusKey('~Alt-F4~ Multiple-Word Search', kbAltF4, cmAndSearch,
            nil))),
         NewStatusDef(hcFileMenu, hcClose,
            NewStatusKey('~Esc~ Cancel', kbEsc, cmCancel,
            nil),
         NewStatusDef(hcAndDialog, hcAndDialog,
            NewStatusKey('~Tab~ Move between lines', kbNoKey, cmError,
            NewStatusKey('~'#17#196#217'~ Done', kbEnter, cmOK,
            NewStatusKey('~Esc~ Cancel', kbEsc, cmCancel,
            nil))),
         NewStatusDef(hcDialog, hcFinalDialog,
            NewStatusKey('~'#17#196#217'~ Done', kbEnter, cmOK,
            NewStatusKey('~Esc~ Cancel', kbEsc, cmCancel,
            nil)),
         NewStatusDef(hcSearchWindow, hcSearchWindow,
            NewStatusKey('~Tab~ Next', kbTab, cmForward,
            NewStatusKey('~Shift-Tab~ Prev', kbShiftTab, cmBack,
            NewStatusKey('~Ctrl-F5~ Move/Resize', kbNoKey, cmError,
            NewStatusKey('~F5~ Zoom', kbF5, cmZoom,
            NewStatusKey('~F10~ Save', kbF10, cmOutputToFile,
            NewStatusKey('~Alt-F3~ Close', kbAltF3, cmClose,
            NewStatusKey('',kbCtrlF5, cmResize,
            NewStatusKey('',kbF1,cmMenu,
            nil)))))))),
         NewStatusDef(hcInfoBox, hcInfoBox,
            NewStatusKey('~'#17#196#217'~ OK', kbEnter, cmOK,
            nil),
         NewStatusDef(hcBlank,hcBlank,
            nil,
         nil))))))))));
   END;

FUNCTION THintStatusLine.Hint(HC:Word):String;
   BEGIN
      CASE HC OF
         hcFileMenu:Hint:='Open, close, view and print files; save to disk; exit; etc.';
         hcOpenOutputFile:Hint:='Select a file to write window information to';
         hcCloseOutputFile:Hint:='Close the Personal File which is currently open';
         hcOutputToFile:Hint:='Append information in the active window to the Personal File';
         hcPrintOutputFile:Hint:='Copy the information in the Personal File to the printer';
         hcSaveAll:Hint:='Save all occurrences in the active window to the Personal File';
         hcViewOutputFile:Hint:='View the information already saved to the Personal File';
         hcAboutBox:Hint:='See The Capital Search''s copyright message';
         hcExit:Hint:='Exit The Capital Search and return to DOS';
         hcSearchMenu:Hint:='Various methods of searching the input file';
         hcViewFile:Hint:='View the file without searching for a specific word';
         hcWordSearch:Hint:='Search for occurrences a word in The Capital Source';
         hcLogicalAndSearch:Hint:='Search for words which appear near each other in The Cap. Source';
         hcOptionsMenu:Hint:='Options which change how The Capital Search acts';
         hcLogicalAndOptions:Hint:='Number of lines which can separate words that are "together"';
         hcAutoWindowSizeOptions:Hint:='Automatically size window around one "record"';
         hcSaveConfirmationOptions:Hint:='Confirmation given after saving a window to the Personal File';
         hcAutoTilingOptions:Hint:='Automatically rearrange windows so you can see all of them';
         hcSaveDivisionOptions:Hint:='Division written between windows saved in the Personal File';
         hcSaveOptions:Hint:='Make current options the defaults for future uses of The C. S.';
         hcWindowMenu:Hint:='Functions to operate screen windows';
         hcZoom:Hint:='Make active window fill the screen (or small again after a zoom)';
         hcResize:Hint:='Adjust the position and size of the active window';
         hcTile:Hint:='Rearrange and resize search windows so all are visible';
         hcCascade:Hint:='Rearrange and resize search windows so all titles are visible';
         hcNext:Hint:='If there is more than one window open, make the next one active';
         hcClose:Hint:='Take the active window off the desktop';
         hcTableOfContents:Hint:='Skip to a specific point in The Capital Source';
         hcNothing:Hint:='No confirmation will appear after saving a window';
         hcAutoText:Hint:='A confirmation will appear for 2 seconds and disappear';
         hcDialogOpt:Hint:='A confirmation will appear and wait for you to press OK';
         hcAutoTile:Hint:='The desktop will be tiled after a search window is added';
         hcNoAutoTile:Hint:='The desktop will not retile itself automatically';
         hcNoDivision:Hint:='No divisions between each saved window';
         hcBlankLine:Hint:='A blank line will appear between each saved window';
         hcStars:Hint:='A row of stars will appear between each saved window';
         hcNoAutoSize:Hint:='The window will never automatically resize itself';
         hcAutoSize:Hint:='The window will always resize itself around each record';
      ELSE Hint:='';
      END;
   END;

PROCEDURE Tile;
   VAR
     R: TRect;
   BEGIN
     Desktop^.GetExtent(R);
     Desktop^.Tile(R);
   END;

PROCEDURE WordSearchObj.HandleEvent;

   PROCEDURE Cascade;
      VAR
        R: TRect;
      BEGIN
        Desktop^.GetExtent(R);
        Desktop^.Cascade(R);
      END;

   BEGIN{handleEvent}
      TApplication.HandleEvent(Event);
      IF Event.What = evCommand THEN
         BEGIN
            CASE Event.Command OF
               cmAboutBox       : AboutBox;
               cmOpenOutputFile : OpenOutputFile;
               cmCloseOutputFile: CloseOutputFile;
               cmViewOutputFile : ViewOutputFile;
               cmPrintOutputFile: PrintOutputFile;
               cmViewFile       : ViewFile(Event.Command);
               cmWordSearch     : WordSearch;
               cmAndSearch      : LogicalAndSearch;
               cmTile           : Tile;
               cmCascade        : Cascade;
               cmCorp..cmThink  : ViewFile(Event.Command);
               cmLogicalAndOptions       : LogicalAndOptions;
               cmSaveConfirmationOptions : SaveConfirmationOptions;
               cmAutoTilingOptions       : AutoTilingOptions;
               cmAutoSizingOptions       : AutoSizingOptions;
               cmSaveDivisionOptions     : SaveDivisionOptions;
               cmSaveOptions             : SaveOptions;
            ELSE
               Exit;
            END;{case}
            ClearEvent(Event);
         END;{if}
   END;{HandleEvent}

FUNCTION FindWordInIndex(AddrStr:Str10;var OneRec:FinalRec):Boolean;
   VAR
      MidPoint,
      First,
      Last :Word;
      X:Byte;
      Found:Boolean;
      Ind1File:FILE OF FinalRec;
   BEGIN
      FOR X:=1 TO Length(AddrStr) DO IF AddrStr[X] IN ['A'..'Z'] THEN
         AddrStr[X]:=Chr(Ord(AddrStr[X])+32);
      Assign(Ind1File,Ind1FileName);
      Reset(Ind1File);
      Found:=FALSE;
      First:=0;
      Last:=FileSize(Ind1File)-1;
      WHILE (First <= Last) AND (NOT Found) DO
         BEGIN
            MidPoint := (First + Last) DIV 2;
            Seek(Ind1File, MidPoint);
            Read(Ind1File, OneRec);
            IF OneRec.WordStr=AddrStr THEN Found:=TRUE
            ELSE IF OneRec.WordStr > AddrStr THEN Last:=MidPoint-1
               ELSE First:=MidPoint+1;
         END;
      FindWordInIndex:=Found;
      Close(Ind1File);
   END;

PROCEDURE Say(TitleString:Str30;SayString:String;Button:OKButtonTypes);
   VAR
      Box :PDialog;
      R   :TRect;
      View:PView;
   BEGIN
      R.Assign(1,1,9+Length(SayString),9);
      Box:=New(PDialog, Init(R, TitleString));
      WITH Box^ DO
         BEGIN
            DragMode:=dmLimitAll;
            Options:=Options OR ofCentered;
            Flags:=wfClose;
            HelpCtx:=hcInfoBox;
         END;
      R.Assign(4,2,6+Length(SayString),3);
      Box^.Insert(New(PStaticText, Init(R, SayString)));
      IF Button=OKButton THEN
         BEGIN
            R.Assign(1,5,11,7);
            View:=New(PButton, Init(R, 'OK', cmOK, bfDefault));
            View^.Options:=View^.Options OR ofCenterX;
            Box^.Insert(View);
            DeskTop^.ExecView(Box);
         END
      ELSE
         BEGIN
            DeskTop^.Insert(Box);
            Delay(2000);
            DeskTop^.Delete(Box);
         END;
      Dispose(Box, Done);
   END;

FUNCTION WordSearchObj.AskFileName(Question:String;var Answer:Str50):Word;
   VAR
      R        :TRect;
      OneView  :PView;
      Box      :PDialog;
   BEGIN
      R.Assign(0,0,15+Length(Question),14);
      Box:=New(PDialog, Init(R, 'Open A File'));
      Box^.HelpCtx:=hcDialog;
      Box^.Options:=Box^.Options OR ofCentered;
      Box^.DragMode:=dmLimitAll;
      R.Assign(8,3,9+Length(Question),4);
      Box^.Insert(New(PStaticText, Init(R, Question)));
      R.Assign(0,6,29,7);
      OneView:=New(PInputLine, Init(R, FileNameLength));
      OneView^.Options:=OneView^.Options OR ofCenterX;
      Box^.Insert(OneView);
      R.Assign(9,10,19,12);
      Box^.Insert(New(PButton, Init(R, '~O~K',cmOK,bfDefault)));
      R.Assign(24,10,34,12);
      Box^.Insert(New(PButton, Init(R, '~C~ancel',cmCancel,bfNormal)));
      OneView^.Select;
      Box^.SetData(Answer);
      AskFileName:=ExecView(Box);
      Box^.GetData(Answer);
      Dispose(Box, Done);
   END;

CONSTRUCTOR TFileStatusLine.Init;
   VAR
      R:TRect;
   BEGIN
      DeskTop^.GetBounds(R);
      R.A.Y:=R.B.Y-1;
      TView.Init(R);
      DeskTop^.GetBounds(R);
      Dec(R.B.Y);
      DeskTop^.SetBounds(R);
   END;

PROCEDURE TFileStatusLine.Draw;
   VAR
      TempStr:String[82];
      MemFree:String[6];
      DrawBuf:TDrawBuffer;
      Col    :Byte;
   BEGIN                               {51=green 15=red bk w/flashing let.}
      IF MaxAvail < 22*1024 THEN Col:=15 ELSE Col:=51;
      Str(MaxAvail/1024:0:1,MemFree);
      TempStr:='THE CAPITAL SEARCH (C) 1991 ³ Personal File: '+OutputFileNameD;
      TempStr:=TempStr+' ³ ~'+MemFree+'K RAM Free~      ';
      IF TempStr<>PrevStr THEN
         BEGIN
            MoveCStr(DrawBuf,TempStr,GetColor(Col) SHL 8 + GetColor(17));
            WriteLine(0,0,80,1,DrawBuf);
            PrevStr:=TempStr;
         END;
   END;

PROCEDURE WordSearchObj.Idle;
   BEGIN
      TApplication.Idle;
      IF CommandEnabled(cmZoom) THEN EnableCommands([cmTile, cmCascade])
         ELSE DisableCommands([cmTile, cmCascade]);
      FileStatusLine^.Draw;
   END;

{***********************REAL bunginess***************************************}

CONSTRUCTOR TOverwriteWarning.Init(BadFN:Str50);
   VAR
      Line  :PView;
      Box   :PDialog;
      R     :TRect;
   BEGIN
      R.Assign(0,0,60,10);
      TDialog.Init(R, 'WARNING');
      Options:=Options OR ofCentered;
      DragMode:=dmLimitAll;
      R.Assign(0,2,25+Length(BadFN),3);
      Line:=New(PStaticText, Init(R, Concat('The file ',BadFN,' already exists.')));
      Line^.Options:=Line^.Options OR ofCenterX;
      Insert(Line);
      R.Assign(5,4,55,5);
      Insert(New(PStaticText, Init(R, 'Would you like to overwrite (delete) the old file')));
      R.Assign(5,5,57,6);
      Insert(New(PStaticText, Init(R, 'or append (write new information to the end of it)?')));
      R.Assign(10,7,20,09);
      Insert(New(PButton, Init(R, '~A~ppend',cmAppend,bfNormal)));
      R.Assign(23,7,36,09);
      Insert(New(PButton, Init(R, '~O~verwrite',cmOverwrite,bfNormal)));
      R.Assign(39,7,49,09);
      Insert(New(PButton, Init(R, '~C~ancel',cmCancel,bfDefault)));
   END;

PROCEDURE TOverwriteWarning.HandleEvent(var Event:TEvent);

   BEGIN
     IF Event.What = evCommand THEN
        BEGIN
          CASE Event.Command OF
             cmOverwrite      : BEGIN
                                   NewFile:=TRUE;
                                   Event.Command:=cmOK;
                                END;
             cmAppend         : BEGIN
                                   NewFile:=FALSE;
                                   Event.Command:=cmOK;
                                END;
          END;{case}
        END;{if}
     TDialog.HandleEvent(Event);
   END;{HandleEvent}

CONSTRUCTOR TGetSearchWordDialog.Init;
   VAR
      R: TRect;
      OneView: PView;
   BEGIN
      R.Assign(20,5,59,20);
      TDialog.Init(R, 'Single Word Search');
      Options:=Options OR ofCentered;
      DragMode:=dmLimitAll;
      HelpCtx:=hcDialog;
      R.Assign(1,3,20,4);
      OneView:=New(PStaticText, Init(R, 'Please enter a word'));
      OneView^.Options:=OneView^.Options OR ofCenterX;
      Insert(OneView);
      R.Assign(1,4,20,5);
      OneView:=New(PStaticText, Init(R, 'to search for:'));
      OneView^.Options:=OneView^.Options OR ofCenterX;
      Insert(OneView);
      R.Assign(1,5,28,6);
      OneView:=New(PInputLine, Init(R, InputLineLength));
      OneView^.Options:=OneView^.Options OR ofCentered;
      Insert(OneView);
      R.Assign(7,11,17,13);
      Insert(New(PButton, Init(R, '~O~K', cmOK, bfDefault)));
      R.Assign(22,11,32,13);
      Insert(New(PButton, Init(R, '~C~ancel', cmCancel, bfNormal)));
      OneView^.Select;
   END;

CONSTRUCTOR TGetSearchWordsDialog.Init;
   VAR
      R         : TRect;
      OneView,
      FirstView : PView;
      X         : Byte;
   BEGIN
      R.Assign(20,0,59,21);
      TDialog.Init(R, 'Multiple-Word Search');
      Options:=Options OR ofCentered;
      DragMode:=dmLimitAll;
      HelpCtx:=hcAndDialog;
      R.Assign(1,2,22,3);
      OneView:=New(PStaticText, Init(R, 'Search for the words:'));
      OneView^.Options:=OneView^.Options OR ofCenterX;
      Insert(OneView);
      FOR X:=1 TO MaxAndWords DO
         BEGIN
            R.Assign(1,X*4,28,X*4+1);
            OneView:=New(PInputLine, Init(R, InputLineLength));
            OneView^.Options:=OneView^.Options OR ofCenterX;
            Insert(OneView);
            IF X=1 THEN FirstView:=OneView;
            IF X<MaxAndWords THEN
               BEGIN
                  R.Assign(1,X*4+2,4,X*4+3);
                  OneView:=New(PStaticText, Init(R, 'AND'));
                  OneView^.Options:=OneView^.Options OR ofCenterX;
                  Insert(OneView);
               END;
         END;
      R.Assign(7,18,17,20);
      Insert(New(PButton, Init(R, '~O~K', cmOK, bfDefault)));
      R.Assign(22,18,32,20);
      Insert(New(PButton, Init(R, '~C~ancel', cmCancel, bfNormal)));
      FirstView^.Select;
   END;

CONSTRUCTOR TSaveConfirmationOptions.Init;
   VAR
      OneView:PRadioButtons;
      R      :TRect;
   BEGIN
      R.Assign(10,4,72,18);
      TDialog.Init(R,'Save Confirmation Options');
      Options:=Options OR ofCentered;
      DragMode:=dmLimitAll;
      HelpCtx:=hcDialog;
      R.Assign(6,2,59,3);
      Insert(New(PStaticText, Init(R, 'This option adjusts what you see after you save the')));
      R.Assign(2,3,60,4);
      Insert(New(PStaticText, Init(R, 'contents of a window to disk using the F10 key.  "Nothing"')));
      R.Assign(2,4,59,5);
      Insert(New(PStaticText, Init(R, 'means there will be no confirmation; "Auto Text" means a')));
      R.Assign(2,5,59,6);
      Insert(New(PStaticText, Init(R, 'message will appear for 2 seconds and then disappear;')));
      R.Assign(2,6,59,7);
      Insert(New(PStaticText, Init(R, '"Dialog Box" means a message will appear and wait for you')));
      R.Assign(2,7,59,8);
      Insert(New(PStaticText, Init(R, 'to push the "OK" button before continuing.')));
      R.Assign(37,9,47,11);
      Insert(New(PButton, Init(R, 'OK', cmOK, bfDefault)));
      R.Assign(37,11,47,13);
      Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
      R.Assign(16,9,32,12);
      OneView:=New(PRadioButtons, Init(R,
         NewSItem('~N~othing',
         NewSItem('~A~uto text',
         NewSItem('~D~ialog box',
         nil)))));
      OneView^.HelpCtx:=hcNothing;
      Insert(OneView);
   END;

CONSTRUCTOR TLogicalAndOptions.Init;
   VAR
      OneView:PInputLine;
      R      :TRect;
   BEGIN
      R.Assign(10,4,75,19);
      TDialog.Init(R,'Multiple-Word Search Options');
      Options:=Options OR ofCentered;
      DragMode:=dmLimitAll;
      HelpCtx:=hcDialog;
      R.Assign(37,10,47,12);
      Insert(New(PButton, Init(R, 'OK', cmOK, bfDefault)));
      R.Assign(37,12,47,14);
      Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
      R.Assign(14,11,24,12);
      Insert(New(PStaticText, Init(R, 'Distance: ')));
      R.Assign(26,11,30,12);
      OneView:=New(PInputLine, Init(R, 2));
      OneView^.HelpCtx:=hcDialog;
      Insert(OneView);
      OneView^.Options:=OneView^.Options OR ofSelectable;
      R.Assign(6,2,64,3);
      Insert(New(PStaticText, Init(R, 'This option adjusts how many lines apart two words can be')));
      R.Assign(2,3,64,4);
      Insert(New(PStaticText, Init(R, 'which are considered "together" by the Multiple-Word Search.')));
      R.Assign(2,4,64,5);
      Insert(New(PStaticText, Init(R, 'For example, if you specify the Distance to be 5 lines and')));
      R.Assign(2,5,64,6);
      Insert(New(PStaticText, Init(R, 'then perform a Multiple-Word Search on two words, those two')));
      R.Assign(2,6,64,7);
      Insert(New(PStaticText, Init(R, 'words would have to be no more than 5 lines apart to be')));
      R.Assign(2,7,64,8);
      Insert(New(PStaticText, Init(R, 'considered "found" and shown to you.  A value of 0 means the')));
      R.Assign(2,8,64,9);
      Insert(New(PStaticText, Init(R, 'search words must all appear on the same line.')));
      OneView^.Select;
   END;

CONSTRUCTOR TAutoTilingOptions.Init;
   VAR
      OneView:PRadioButtons;
      R      :TRect;
   BEGIN
      R.Assign(10,4,70,18);
      TDialog.Init(R,'Auto Window Tiling Options');
      Options:=Options OR ofCentered;
      DragMode:=dmLimitAll;
      HelpCtx:=hcDialog;
      R.Assign(6,2,59,3);
      Insert(New(PStaticText, Init(R, 'This option adjusts whether or not The C. S. should')));
      R.Assign(2,3,59,4);
      Insert(New(PStaticText, Init(R, 'automatically rearrange and resize the windows on the')));
      R.Assign(2,4,59,5);
      Insert(New(PStaticText, Init(R, '"desktop" so that you can see all of them at once (as if')));
      R.Assign(2,5,59,6);
      Insert(New(PStaticText, Init(R, 'you had chosen the "Tile" option from the Window menu.)')));
      R.Assign(2,6,59,7);
      Insert(New(PStaticText, Init(R, 'If you activate this option, the desktop will retile')));
      R.Assign(2,7,59,8);
      Insert(New(PStaticText, Init(R, 'itself every time you add a search window to it.')));
      R.Assign(37,9,47,11);
      Insert(New(PButton, Init(R, 'OK', cmOK, bfDefault)));
      R.Assign(37,11,47,13);
      Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
      R.Assign(14,09,34,11);
      OneView:=New(PRadioButtons, Init(R,
         NewSItem('~N~o Auto Tiling',
         NewSItem('~A~uto Tiling',
         nil))));
      OneView^.HelpCtx:=hcNoAutoTile;
      Insert(OneView);
   END;

CONSTRUCTOR TAutoSizingOptions.Init;
   VAR
      OneView:PRadioButtons;
      R      :TRect;
   BEGIN
      R.Assign(10,4,70,18);
      TDialog.Init(R,'Auto Window Sizing Options');
      Options:=Options OR ofCentered;
      DragMode:=dmLimitAll;
      HelpCtx:=hcDialog;
      R.Assign(6,2,59,3);
      Insert(New(PStaticText, Init(R, 'This option adjusts whether or not The C. S. should')));
      R.Assign(2,3,59,4);
      Insert(New(PStaticText, Init(R, 'automatically adjust the size of the search window so')));
      R.Assign(2,4,59,5);
      Insert(New(PStaticText, Init(R, 'that only one record at a time is visible.  This is')));
      R.Assign(2,5,59,6);
      Insert(New(PStaticText, Init(R, 'useful if you are saving many records to your Personal')));
      R.Assign(2,6,59,7);
      Insert(New(PStaticText, Init(R, 'File and do not want to resize the window for each')));
      R.Assign(2,7,59,8);
      Insert(New(PStaticText, Init(R, 'name and address you save.')));
      R.Assign(37,9,47,11);
      Insert(New(PButton, Init(R, 'OK', cmOK, bfDefault)));
      R.Assign(37,11,47,13);
      Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
      R.Assign(14,09,34,11);
      OneView:=New(PRadioButtons, Init(R,
         NewSItem('~N~o Auto Sizing',
         NewSItem('~A~uto Sizing',
         nil))));
      OneView^.HelpCtx:=hcNoAutoSize;
      Insert(OneView);
   END;

CONSTRUCTOR TSaveDivisionOptions.Init;
   VAR
      OneView:PRadioButtons;
      R      :TRect;
   BEGIN
      R.Assign(10,4,73,18);
      TDialog.Init(R,'Save Division Options');
      Options:=Options OR ofCentered;
      DragMode:=dmLimitAll;
      HelpCtx:=hcDialog;
      R.Assign(6,2,62,3);
      Insert(New(PStaticText, Init(R, 'This option adjusts whether or not there is a division')));
      R.Assign(2,3,59,4);
      Insert(New(PStaticText, Init(R, 'between each window you save to the Personal File.  For')));
      R.Assign(2,4,59,5);
      Insert(New(PStaticText, Init(R, 'example, if you choose "Blank Line," a blank line will be')));
      R.Assign(2,5,62,6);
      Insert(New(PStaticText, Init(R, 'written to the Personal File right after you save a window')));
      R.Assign(2,6,62,7);
      Insert(New(PStaticText, Init(R, 'to it.  If you choose "No Division," the Personal File will')));
      R.Assign(2,7,62,8);
      Insert(New(PStaticText, Init(R, 'be a continuous stream of data with no divisions.')));
      R.Assign(37,9,47,11);
      Insert(New(PButton, Init(R, 'OK', cmOK, bfDefault)));
      R.Assign(37,11,47,13);
      Insert(New(PButton, Init(R, 'Cancel', cmCancel, bfNormal)));
      R.Assign(14,09,32,12);
      OneView:=New(PRadioButtons, Init(R,
         NewSItem('~N~o Division',
         NewSItem('~B~lank Line',
         NewSItem('Row of ~S~tars',
         nil)))));
      OneView^.HelpCtx:=hcNoDivision;
      Insert(OneView);
   END;

CONSTRUCTOR TTextFileWindow.Init(var Bounds:TRect; WinTitle:String;ListStart:AddrRecordPtr;
                                 ListLen:Word;HighLightStr:HighlightArray;NumOfWords:Byte);
   VAR
      HScrollBar, VScrollBar: PScrollBar;
      Interior : PTextFileInterior;
      R: TRect;
   BEGIN
      TWindow.Init(Bounds, WinTitle, wnNoNumber);
      Options:=Options OR ofTileable;
      HelpCtx:=hcSearchWindow;
      IF NumOfWords=0 THEN DisableCommands([cmForward,cmBack])
         ELSE EnableCommands([cmForward,cmBack]);
      VScrollBar:=StandardScrollBar(sbVertical + sbHandleKeyboard);
      HScrollBar:=StandardScrollBar(sbHorizontal + sbHandleKeyboard);
      GetExtent(Bounds);
      Bounds.Grow(-1,-1);
      Interior:=New(PTextFileInterior, Init(Bounds, HScrollBar, VScrollBar, ListStart, ListLen, HighLightStr, NumOfWords));
      Insert(Interior);
      IF MyOptions.AutoSizing THEN Interior^.AutoSize;
   END;

DESTRUCTOR TTextFileWindow.Done;
   VAR
      R:TRect;
   BEGIN
      DeskTop^.Lock;
      TWindow.Done;
      IF MyOptions.AutoTiling THEN Tile;
      DeskTop^.Unlock;
   END;

CONSTRUCTOR TTextFileInterior.Init(var Bounds:TRect; AHScrollBar, AVScrollBar:PScrollBar;
                                   ListStart:AddrRecordPtr;ListLen:Word;HighLightStr:HighlightArray;NumOfWrds:Byte);
   VAR
      X,Y:Byte;
   BEGIN
      TScroller.Init(Bounds,AHScrollBar,AVScrollBar);
      GrowMode:=GrowMode OR (gfGrowHiX+gfGrowHiY);
      Assign(TextFile,TextFileName);
      Assign(LineIndex,Ind3FileName);
      Reset(LineIndex);
      LastLine:=FileSize(LineIndex)-1;
      Close(LineIndex);
      Address:=ListStart;
      NumOfAddr:=ListLen;
      NumOfWords:=NumOfWrds;
      SearchStr:=HighLightStr;
      FOR X:=1 TO NumOfWords DO
         FOR Y:=1 TO Length(SearchStr[X]) DO IF SearchStr[X][Y] IN ['A'..'Z'] THEN
         SearchStr[X][Y]:=Chr(Ord(SearchStr[X][Y])+32);
      LineBufStart:=-1;
      LineBufEnd:=-1;
      IF OutputFileSelected THEN EnableCommands(OutputCommands);
      SetLimit(78,LastLine);
      ScrollTo(0,Address^[1]);
      ScrollDraw;
   END;

PROCEDURE TTextFileInterior.AutoSize;
   TYPE
      Str4  = ARRAY[1..4] OF Char;
      PStr4 = ^Str4;
   VAR
      LinesBack,
      LinesForward :Byte;
      CurrPos      :Word;
      ActOfs       :LongInt;
      Str4Ptr      :PStr4;
   BEGIN
      LinesForward:=0;
      LinesBack:=0;
      Reset(LineIndex);
      Seek(LineIndex,Delta.Y);
      Read(LineIndex,ActOfs);
      Close(LineIndex);
      ReadBuffer(ActOfs);
      CurrPos:=ActOfs-BufStart+1;
      Str4Ptr:=@TextBuffer[CurrPos];
      WHILE (CurrPos>1) AND (Str4Ptr^<>#13#10#13#10) DO
         BEGIN
            IF TextBuffer[CurrPos]=#13 THEN Inc(LinesBack);
            Dec(CurrPos);
            Str4Ptr:=@TextBuffer[CurrPos];
         END;
      IF CurrPos=BufStart THEN ScrollTo(Delta.X,Delta.Y-LinesBack)
         ELSE ScrollTo(Delta.X,Delta.Y-LinesBack+1);
      Inc(CurrPos,4);
      Str4Ptr:=@TextBuffer[CurrPos];
      WHILE (CurrPos<TextBufferSize-1) AND (Str4Ptr^<>#13#10#13#10) DO
         BEGIN
            IF TextBuffer[CurrPos]=#13 THEN Inc(LinesForward);
            Inc(CurrPos);
            Str4Ptr:=@TextBuffer[CurrPos];
         END;
      Owner^.GrowTo(Owner^.Size.X,LinesForward+3);
      ScrollDraw;
   END;

PROCEDURE TTextFileInterior.HandleEvent(var Event: TEvent);

   PROCEDURE GoForward;
      BEGIN
         IF MyOptions.AutoSizing THEN ScrollTo(Delta.X,Delta.Y+Size.Y);
         IF Address^[1] > Delta.Y THEN
            BEGIN
               ScrollTo(Delta.X,Address^[1]);
               IF MyOptions.AutoSizing THEN AutoSize;
               ScrollDraw;
               Exit;
            END;
         CurrAddr:=1;
         REPEAT
            Inc(CurrAddr);
         UNTIL (CurrAddr>=NumOfAddr) OR
               ((Address^[CurrAddr-1] <= Delta.Y) AND (Address^[CurrAddr] > Delta.Y));
         IF (CurrAddr>NumOfAddr) OR (Address^[CurrAddr] <= Delta.Y)
            THEN
               BEGIN
                  IF MyOptions.AutoSizing THEN ScrollTo(Delta.X,Delta.Y-Size.Y);
                  DeskTop^.Unlock;
                  Say('Search Error','No subsequent occurrences.',OKButton);
                  DeskTop^.Lock;
               END
         ELSE
            BEGIN
               ScrollTo(Delta.X,Address^[CurrAddr]);
               IF MyOptions.AutoSizing THEN AutoSize;
               ScrollDraw;
            END;
      END;

   PROCEDURE GoBack;
      BEGIN
         CurrAddr:=1;
         REPEAT
            IF (Address^[CurrAddr] < Delta.Y) AND
               ((CurrAddr = NumOfAddr) OR (Address^[CurrAddr+1] >= Delta.Y))
                  THEN
                     BEGIN
                        ScrollTo(Delta.X,Address^[CurrAddr]);
                        IF MyOptions.AutoSizing THEN AutoSize;
                        ScrollDraw;
                        Exit;
                     END;
            CurrAddr:=CurrAddr+1;
         UNTIL CurrAddr > NumOfAddr;
         DeskTop^.Unlock;
         Say('Search Error', 'No previous occurrences.',OKButton);
         DeskTop^.Lock;
      END;

   PROCEDURE SaveToFile;
      VAR
         LineIndex:FILE OF Longint;
         OutputFile:FILE;
         BufferPos:Longint;
         BytesToWrite:Longint;
      BEGIN
         Assign(LineIndex,Ind3FileName);
         Reset(LineIndex);
         Seek(LineIndex,LineBufStart);
         Read(LineIndex,BufferPos);
         Seek(LineIndex,LineBufStart+Size.Y);
         Read(LineIndex,BytesToWrite);
         BytesToWrite:=BytesToWrite-BufferPos;
         Close(LineIndex);
         BufferPos:=BufferPos-BufStart+1;
         Assign(OutputFile,OutputFileName);
         IF NewFile=TRUE THEN
            BEGIN
               Rewrite(OutputFile,1);
               NewFile:=FALSE;
            END
         ELSE
            BEGIN
               Reset(OutputFile,1);
               Seek(OutputFile,FileSize(OutputFile));
            END;
         BlockWrite(OutputFile,TextBuffer[BufferPos],BytesToWrite);
         IF MyOptions.SaveDivision=BlankLine THEN BlockWrite(OutputFile,CRLF,SizeOf(CRLF));
         IF MyOptions.SaveDivision=Stars THEN
            BlockWrite(OutputFile,LineOfStars,SizeOf(LineOfStars));
         Close(OutputFile);
         IF MyOptions.SaveConfirmation=DialogBox THEN Say('Save Confirmation','Window saved to Personal File.',OKButton);
         IF MyOptions.SaveConfirmation=AutoText THEN Say('Save Confirmation','Window saved to Personal File.',NoOKButton);
      END;

   PROCEDURE SaveAll;
      VAR
         D         : PDialog;
         R         : TRect;
         OrigOpts  : OptionRec;
         OrigDelta : TPoint;
         OrigWin   : TRect;
         X         : Word;
      BEGIN
         R.Assign(0, 0, 40, 7);
         D := New(PDialog, Init(R, 'Working . . .'));
         with D^ do
            BEGIN
               Options:=Options or ofCentered;
               HelpCtx:=hcBlank;
               DragMode:=dmLimitAll;
               R.Assign(1,3,39,4);
               Insert(New(PStaticText, Init(R,^C'Working, please wait . . .')));
            END;
         DeskTop^.Insert(D);
         OrigOpts:=MyOptions;
         OrigDelta:=Delta;
         Owner^.GetBounds(OrigWin);
         MyOptions.SaveConfirmation:=NONE;
         MyOptions.AutoSizing:=TRUE;
         DeskTop^.Lock;
         Delta.Y:=0;
         FOR X:=1 TO NumOfAddr DO
            BEGIN
               GoForward;
               SaveToFile;
            END;
         Owner^.Locate(OrigWin);
         ScrollTo(OrigDelta.X,OrigDelta.Y);
         MyOptions:=OrigOpts;
         DeskTop^.Unlock;
         DeskTop^.Delete(D);
         Dispose(D, Done);
         IF MyOptions.SaveConfirmation=DialogBox THEN
            Say('Save Confirmation','All occurrences saved to Personal File.',OKButton);
         IF MyOptions.SaveConfirmation=AutoText THEN
            Say('Save Confirmation','All occurrences saved to Personal File.',NoOKButton);
      END;

   BEGIN
      TScroller.HandleEvent(Event);
      IF (Event.What=evCommand) THEN
         IF (Event.Command=cmForward) OR (Event.Command=cmBack) THEN
            BEGIN
               DeskTop^.Lock;
               IF Event.KeyCode=cmForward THEN GoForward ELSE GoBack;
               ClearEvent(Event);
               DeskTop^.Unlock;
            END;
      IF (Event.What=evCommand) AND (Event.Command=cmOutputToFile) THEN
         BEGIN
            SaveToFile;
            ClearEvent(Event);
         END;
      IF (Event.What=evCommand) AND (Event.Command=cmSaveAll) THEN
         BEGIN
            SaveAll;
            ClearEvent(Event);
         END;
   END;

PROCEDURE TTextFileInterior.ReadBuffer(StartAddress:LongInt);
   VAR
      CharsRead:Word;
   BEGIN
      IF StartAddress < LeadingChars THEN BufStart:=0
         ELSE BufStart:=StartAddress-LeadingChars;
      Reset(TextFile,1);
      Seek(TextFile,BufStart);
      BlockRead(TextFile,TextBuffer,TextBufferSize,CharsRead);
      Close(TextFile);
      BufStop:=BufStart+CharsRead;
   END;

PROCEDURE TTextFileInterior.Draw;
   LABEL
      DrawWindow;
   VAR
      ActualOffset:LongInt;
      FormatStart,FormatEnd,X,Y,Z,
      HStart:Byte;
      BufferPos,WinEnd:Word;
      NextChar:Char;
      TempString,
      TempStringSave :String;

   PROCEDURE GetActualOffset;
      BEGIN
         Reset(LineIndex);
         IF WinEnd>LastLine THEN Seek(LineIndex,LastLine)
            ELSE Seek(LineIndex,WinEnd);
         Read(LineIndex,ActualOffset);
         IF ActualOffset+Size.X>BufStop THEN ReadBuffer(ActualOffset);
         Seek(LineIndex,Delta.Y+FormatStart);
         Read(LineIndex,ActualOffset);
         Close(LineIndex);
         IF ActualOffset<BufStart THEN ReadBuffer(ActualOffset);
         BufferPos:=ActualOffset-BufStart+1;
      END;

   PROCEDURE FindFormatBounds;
      VAR
         X:Byte;
      BEGIN
         IF (Delta.Y=LineBufStart) AND (WinEnd>LineBufEnd) THEN
            BEGIN
               FormatStart:=LineBufEnd-Delta.Y-2;
               FormatEnd:=Size.Y-1;
            END
         ELSE IF (Delta.Y=LineBufStart-1) AND (WinEnd=LineBufEnd-1) THEN
            BEGIN
               FOR X:=Size.Y-1 DOWNTO 1 DO LineBuffer[X]:=LineBuffer[X-1];
               FormatStart:=0;
               FormatEnd:=0;
            END
         ELSE IF (Delta.Y=LineBufStart+1) AND (WinEnd=LineBufEnd+1) THEN
            BEGIN
               FOR X:=0 TO Size.Y-2 DO LineBuffer[X]:=LineBuffer[X+1];
               FormatStart:=Size.Y-1;
               FormatEnd:=FormatStart;
            END
         ELSE
            BEGIN
               FormatStart:=0;
               FormatEnd:=Size.Y-1;
            END;
      END;

   PROCEDURE HighlightSearchWords;
      VAR
         X,Z:Byte;
      BEGIN
         FOR X:=1 TO Length(TempString) DO IF TempString[X] IN ['A'..'Z']
            THEN TempString[X]:=Chr(Ord(TempString[X])+32);
         TempStringSave:=TempString;
         IF NumOfWords>0 THEN FOR Z:=1 TO NumOfWords DO
            BEGIN
               TempString:=TempStringSave;
               REPEAT
                  HStart:=Pos(SearchStr[Z],TempString);
                  IF HStart>0 THEN
                     BEGIN
                        FOR X:=HStart-1 TO HStart+Length(SearchStr[Z])-2 DO
                           LineBuffer[Y,X]:=LineBuffer[Y,X] OR (HiColor SHL 8);
                        FOR X:=1 TO HStart DO TempString[X]:=' ';
                     END;
               UNTIL HStart=0;
            END;
      END;

   BEGIN
      IF Delta.Y+Size.Y-1>LastLine THEN Delta.Y:=LastLine-Size.Y+1;
      WinEnd:=Delta.Y+Size.Y-1;
      IF (Delta.Y=LineBufStart) AND (WinEnd<=LineBufEnd) THEN GOTO DrawWindow
         ELSE FindFormatBounds;
      GetActualOffset;
      FOR Y:=FormatStart TO FormatEnd DO
         BEGIN
            TempString:=Spaces;
            X:=1;
            NextChar:=TextBuffer[BufferPos];
            WHILE NextChar<>#13 DO
               BEGIN
                  IF NextChar<>#9 THEN TempString[X]:=NextChar
                  ELSE IF X MOD 8 > 0 THEN X:=X+(8-(X MOD 8));
                  Inc(BufferPos);
                  Inc(X);
                  NextChar:=TextBuffer[BufferPos];
               END;
            Inc(BufferPos);
            Inc(BufferPos);
            MoveStr(LineBuffer[Y],TempString,GetColor(1));
            HighlightSearchWords;
         END;
   DrawWindow:
      FOR Y:=0 TO Size.Y-1 DO
         BEGIN
            WriteLine(0,Y,Size.X,1,LineBuffer[Y,Delta.X]);
         END;
      LineBufStart:=Delta.Y;
      LineBufEnd:=Delta.Y+Size.Y-1;
   END;{TTextFileInterior.Draw}

DESTRUCTOR TTextFileInterior.Done;
   BEGIN
      FreeMem(Address,NumOfAddr*SizeOf(Word));
      TScroller.Done;
      IF NOT CommandEnabled(cmZoom) THEN DisableCommands(OutputCommands);
   END;

{****************************************************************************}

PROCEDURE WordSearchObj.OpenTextFile;
   VAR
      InputLn,
      Temp1,Temp2,
      Temp3,TempT:Str50;
      TempFile:FILE;
   BEGIN
      InputLn:=ParamStr(0);
      IF Copy(InputLn,Length(InputLn)-8,9)='TURBO.EXE' THEN
         InputLn:='capsourc.txt'
      ELSE
         InputLn:=Copy(ParamStr(0),1,Length(ParamStr(0))-6)+'capsourc.txt';
      TempT:=InputLn;
      {$I-}
      Assign(TempFile,TempT);
      Reset(TempFile);
      {$I+}
      IF IOResult>0 THEN FilesGone:=TRUE
      ELSE
         BEGIN
            Close(TempFile);
            IF Pos('.',InputLn)>0 THEN
               System.Delete(InputLn,Pos('.',InputLn),Length(InputLn)-Pos('.',InputLn)+1);
            Temp1:=InputLn+'.in1';
            Temp2:=InputLn+'.in2';
            Temp3:=InputLn+'.in3';
            {$I-}
            Assign(TempFile,Temp1);
            Reset(TempFile);
            {$I+}
            IF IOResult>0 THEN FilesGone:=TRUE
            ELSE
               BEGIN
                  Close(TempFile);
                  EnableCommands(SearchCommands);
                  TextFileName:=TempT;
                  IF Length(TempT)<=15 THEN TextFileNameD:=TempT+Copy(Spaces,1,16-Length(TempT))
                     ELSE TextFileNameD:=Copy(TempT,Length(TempT)-15,16);
                  Ind1FileName:=Temp1;
                  Ind2FileName:=Temp2;
                  Ind3FileName:=Temp3;
                  FilesGone:=FALSE;
               END;
         END;
   END;

PROCEDURE WordSearchObj.OpenOutputFile;
   VAR
      InputLn:Str50;
      BoxResult:Word;
      TempFile:FILE;
      OverwriteWarning:POverwriteWarning;
   BEGIN
      InputLn:='';
      BoxResult:=AskFileName('Enter name of Personal File:',InputLn);
      IF (BoxResult <> cmCancel) AND (InputLn<>'') THEN
         BEGIN
            OutputFileName:=InputLn;
            {$I-}
            Assign(TempFile,OutputFileName);
            Reset(TempFile);
            {$I+}
            BoxResult:=cmOK;
            NewFile:=TRUE;
            IF IOResult=0 THEN
               BEGIN
                  Close(TempFile);
                  New(OverwriteWarning, Init(InputLn));
                  BoxResult:=ExecView(OverwriteWarning);
                  Dispose(OverwriteWarning, Done);
               END;
            IF BoxResult<>cmCancel THEN
               BEGIN
                  IF Length(OutputFileName)<=15 THEN OutputFileNameD:=OutputFileName+Copy(Spaces,1,16-Length(OutputFileName))
                     ELSE OutputFileNameD:=Copy(OutputFileName,Length(OutputFileName)-15,16);
                  OutputFileSelected:=TRUE;
                  EnableCommands(CloseOutputCommands);
                  IF CommandEnabled(cmZoom) THEN EnableCommands(OutputCommands);
               END;
         END;
   END;

PROCEDURE WordSearchObj.CloseOutputFile;
   BEGIN
      DisableCommands(CloseOutputCommands);
      DisableCommands(OutputCommands);
      OutputFileSelected:=FALSE;
      OutputFileNameD:='No file selected';
   END;

{****************************************************************************}

PROCEDURE WordSearchObj.WordSearch;
   VAR
      SearchString:String[InputLineLength];
      Box         :PGetSearchWordDialog;
      BoxResult   :Word;
      StrToPass   :HighlightArray;

   PROCEDURE OpenSearchWindow;
      VAR
         Ind2File:FILE OF Word;
         R       :TRect;
         X       :Word;
         OneRec  :FinalRec;
         Address :AddrRecordPtr;
         Window  :PTextFileWindow;

      BEGIN{OpenSearchWindow}
         IF NotEnoughMemory THEN Exit;
         IF NOT FindWordInIndex(Copy(SearchString,1,StringLength),OneRec) THEN
            BEGIN
               Say('Search Error', Concat('The word "',SearchString,'" is not in the file.'),OKButton);
               Exit;
            END;
         GetMem(Address,OneRec.Occur*SizeOf(Word));
         Assign(Ind2File,Ind2FileName);
         Reset(Ind2File);
         Seek(Ind2File,OneRec.FirstAddr);
         FOR X:=1 TO OneRec.Occur DO Read(Ind2File,Address^[X]);
         Close(Ind2File);
         R.Assign(0,0,80,22);
         FillChar(StrToPass,SizeOf(StrToPass),#0);
         StrToPass[1]:=SearchString;
         DeskTop^.Lock;
         Window:=New(PTextFileWindow, Init(R, Concat(SearchString, ': The Capital Source'),Address,OneRec.Occur,StrToPass, 1));
         DeskTop^.Insert(Window);
         IF MyOptions.AutoTiling AND NOT MyOptions.AutoSizing THEN Tile;
         DeskTop^.Unlock;
      END;{OpenSearchWindow}

   BEGIN{WordSearch}
      Box:=New(PGetSearchWordDialog, Init);
      SearchString:='';
      Box^.SetData(SearchString);
      BoxResult:=Desktop^.ExecView(Box);
      IF BoxResult <> cmCancel THEN
         BEGIN
            Box^.GetData(SearchString);
            IF SearchString='' THEN Exit;
            WHILE Pos(' ',SearchString)>0 DO System.Delete(SearchString,Pos(' ',SearchString),1);
            Dispose(Box, Done);
            OpenSearchWindow;
         END
      ELSE Dispose(Box, Done);
   END;

PROCEDURE WordSearchObj.LogicalAndSearch;
   VAR
      SearchString :ARRAY[1..MaxAndWords] OF String[InputLineLength];
      StrToPass    :HighLightArray;
      Box          :PGetSearchWordsDialog;
      BoxResult    :Word;

   PROCEDURE OpenAndSearchWindow;
      VAR
         Ind2File   :FILE OF Word;
         R          :TRect;
         X,Y,Z,
         NumOfAddr1,
         NumOfAddr2,
         OneAddr,
         NumOfWords :Word;
         Dist1,Dist2:LongInt;
         OneRec     :FinalRec;
         Address1,
         Address2   :AndRecPtr;
         AddrToPass :AddrRecordPtr;
         Window     :PTextFileWindow;
         AllWords   :String;
      BEGIN{OpenAndSearchWindow}
         IF NotEnoughMemory THEN Exit;
         NumOfWords:=MaxAndWords;
         FOR Y:=MaxAndWords-1 DOWNTO 1 DO IF SearchString[Y+1]='' THEN NumOfWords:=Y;
         Assign(Ind2File,Ind2FileName);
         Reset(Ind2File);
         FOR Z:=1 TO NumOfWords DO
            BEGIN
               IF NOT FindWordInIndex(Copy(SearchString[Z],1,StringLength),OneRec) THEN
                  BEGIN
                     Say('Search Error', Concat('The word "',SearchString[Z],'" is not in the file.'),OKButton);
                     Close(Ind2File);
                     Exit;
                  END;
               Seek(Ind2File,OneRec.FirstAddr);
               IF Z=1 THEN
                  BEGIN
                     GetMem(Address1,OneRec.Occur*SizeOf(AndRec));
                     FOR X:=1 TO OneRec.Occur DO
                        BEGIN
                           Read(Ind2File,Address1^[X].Lo);
                           Address1^[X].High:=Address1^[X].Lo;
                        END;
                     NumOfAddr1:=OneRec.Occur;
                  END
               ELSE
                  BEGIN
                     NumOfAddr2:=0;
                     GetMem(Address2,OneRec.Occur*NumOfAddr1*SizeOf(AndRec));
                     FOR X:=1 TO OneRec.Occur DO
                        BEGIN
                           Read(Ind2File,OneAddr);
                           FOR Y:=1 TO NumOfAddr1 DO
                              BEGIN
                                 Dist1:=Address1^[Y].High;
                                 Dist1:=Abs(OneAddr-Dist1);
                                 Dist2:=Address1^[Y].Lo;
                                 Dist2:=Abs(OneAddr-Dist2);
                                 IF (Dist1<=MyOptions.LogicalAndDistance) AND (Dist2<=MyOptions.LogicalAndDistance) THEN
                                    BEGIN
                                       Inc(NumOfAddr2);
                                       Address2^[NumOfAddr2]:=Address1^[Y];
                                       IF OneAddr<Address2^[NumOfAddr2].Lo THEN Address2^[NumOfAddr2].Lo:=OneAddr
                                       ELSE IF OneAddr>Address2^[NumOfAddr2].High THEN Address2^[NumOfAddr2].High:=OneAddr;
                                    END;
                              END;
                        END;
                        FreeMem(Address1,NumOfAddr1*SizeOf(AndRec));
                        GetMem(Address1,NumOfAddr2*SizeOf(AndRec));
                        FOR Y:=1 TO NumOfAddr2 DO Address1^[Y]:=Address2^[Y];
                        FreeMem(Address2,OneRec.Occur*NumOfAddr1*SizeOf(AndRec));
                        NumOfAddr1:=NumOfAddr2;
                        IF NumOfAddr1=0 THEN
                           BEGIN
                              Close(Ind2File);
                              Say('Search Error','Those words do not occur together in The Capital Source.',OKButton);
                              Exit;
                           END;
                     END;
            END;
         Close(Ind2File);
         FOR Z:=1 TO NumOfWords DO StrToPass[Z]:=SearchString[Z];
         GetMem(AddrToPass,NumOfAddr1*SizeOf(Word));
         FOR Z:=1 TO NumOfAddr1 DO AddrToPass^[Z]:=Address1^[Z].Lo;
         FreeMem(Address1,NumOfAddr1*SizeOf(AndRec));
         AllWords:=SearchString[1];
         FOR Z:=2 TO NumOfWords DO AllWords:=AllWords+' & '+SearchString[Z];
         AllWords:=AllWords+': The Capital Source';
         R.Assign(0,0,80,22);
         DeskTop^.Lock;
         Window:=New(PTextFileWindow, Init(R, AllWords, AddrToPass, NumOfAddr1, StrToPass, NumOfWords));
         DeskTop^.Insert(Window);
         IF MyOptions.AutoTiling THEN Tile;
         DeskTop^.Unlock;
      END;{OpenSearchWindow}

   BEGIN
      Box:=New(PGetSearchWordsDialog, Init);
      FillChar(SearchString,SizeOf(SearchString),#0);
      Box^.SetData(SearchString);
      BoxResult:=Desktop^.ExecView(Box);
      IF BoxResult <> cmCancel THEN
         BEGIN
            Box^.GetData(SearchString);
            IF SearchString[1]='' THEN Exit;
            FOR BoxResult:=1 TO MaxAndWords DO WHILE Pos(' ',SearchString[BoxResult])>0 DO
                System.Delete(SearchString[BoxResult],Pos(' ',SearchString[BoxResult]),1);
            Dispose(Box, Done);
            OpenAndSearchWindow;
         END
      ELSE Dispose(Box, Done);
   END;

PROCEDURE WordSearchObj.LogicalAndOptions;
   VAR
      Box       :PLogicalAndOptions;
      BoxResult :Byte;
      Error     :Integer;
      TempStr   :String[2];
   BEGIN
      Box:=New(PLogicalAndOptions, Init);
      Str(MyOptions.LogicalAndDistance,TempStr);
      Box^.SetData(TempStr);
      BoxResult:=DeskTop^.ExecView(Box);
      IF BoxResult <> cmCancel THEN
         BEGIN
            Box^.GetData(TempStr);
            Val(TempStr,BoxResult,Error);
            IF Error=0 THEN MyOptions.LogicalAndDistance:=BoxResult;
         END;
      Dispose(Box, Done);
   END;

PROCEDURE WordSearchObj.SaveConfirmationOptions;
   VAR
      Box       :PSaveConfirmationOptions;
      BoxResult :Byte;
      BoxData   :Word;
   BEGIN
      Box:=New(PSaveConfirmationOptions, Init);
      BoxData:=Ord(MyOptions.SaveConfirmation);
      Box^.SetData(BoxData);
      BoxResult:=DeskTop^.ExecView(Box);
      IF BoxResult <> cmCancel THEN Box^.GetData(BoxData);
      CASE BoxData OF
         0:MyOptions.SaveConfirmation:=None;
         1:MyOptions.SaveConfirmation:=AutoText;
         2:MyOptions.SaveConfirmation:=DialogBox;
      END;
      Dispose(Box, Done);
   END;

PROCEDURE WordSearchObj.AutoTilingOptions;
   VAR
      Box       :PAutoTilingOptions;
      BoxResult :Byte;
      BoxData   :Word;
   BEGIN
      Box:=New(PAutoTilingOptions, Init);
      BoxData:=Ord(MyOptions.AutoTiling);
      Box^.SetData(BoxData);
      BoxResult:=DeskTop^.ExecView(Box);
      IF BoxResult <> cmCancel THEN Box^.GetData(MyOptions.AutoTiling);
      Dispose(Box, Done);
   END;

PROCEDURE WordSearchObj.AutoSizingOptions;
   VAR
      Box       :PAutoSizingOptions;
      BoxResult :Byte;
      BoxData   :Word;
   BEGIN
      Box:=New(PAutoSizingOptions, Init);
      BoxData:=Ord(MyOptions.AutoSizing);
      Box^.SetData(BoxData);
      BoxResult:=DeskTop^.ExecView(Box);
      IF BoxResult <> cmCancel THEN Box^.GetData(MyOptions.AutoSizing);
      Dispose(Box, Done);
   END;

PROCEDURE WordSearchObj.SaveDivisionOptions;
   VAR
      Box       :PSaveDivisionOptions;
      BoxResult :Byte;
      BoxData   :Word;
   BEGIN
      Box:=New(PSaveDivisionOptions, Init);
      BoxData:=Ord(MyOptions.SaveDivision);
      Box^.SetData(BoxData);
      BoxResult:=DeskTop^.ExecView(Box);
      IF BoxResult <> cmCancel THEN Box^.GetData(BoxData);
      CASE BoxData OF
         0:MyOptions.SaveDivision:=Nothing;
         1:MyOptions.SaveDivision:=BlankLine;
         2:MyOptions.SaveDivision:=Stars;
      END;
      Dispose(Box, Done);
   END;

PROCEDURE WordSearchObj.ViewFile(ToCNum:Word);
   VAR
      R:TRect;
      Temp:HighlightArray;
      Address:AddrRecordPtr;
      Window:PTextFileWindow;
      TempOpts : OptionRec;
   BEGIN
      IF NotEnoughMemory THEN Exit;
      DeskTop^.Lock;
      R.Assign(0,0,80,22);
      GetMem(Address,2);
      Address^[1]:=ToC[ToCNum];
      FillChar(Temp,SizeOf(Temp),#0);
      TempOpts:=MyOptions;
      MyOptions.AutoSizing:=FALSE;
      Window:=New(PTextFileWindow, Init(R, 'The Capital Source', Address, 1, Temp, 0));
      DeskTop^.Insert(Window);
      IF MyOptions.AutoTiling THEN Tile;
      DeskTop^.Unlock;
      MyOptions:=TempOpts;
   END;

PROCEDURE WordSearchObj.SaveOptions;
   VAR
      OptionFile :FILE OF OptionRec;
   BEGIN
      Assign(OptionFile,'capsrch.cfg');
      Rewrite(OptionFile);
      Write(OptionFile,MyOptions);
      Close(OptionFile);
      Say('Save Confirmation', 'Options saved to disk.',OKButton);
   END;

PROCEDURE WordSearchObj.AboutBox;
   var
     D: PDialog;
     R: TRect;
   begin
     R.Assign(0, 0, 45, 13);
     D := New(PDialog, Init(R, 'About'));
     with D^ do
     begin
       Options := Options or ofCentered;
       HelpCtx:=hcInfoBox;
       DragMode:=dmLimitAll;

       R.Grow(-1, -1);
       Dec(R.B.Y, 3);
       Insert(New(PStaticText, Init(R,
         #13 +
         ^C'The Capital Search, Fall 1991'#13 +
         #13 +
         ^C'Copyright (c) 1991  The Whitman Group'#13 +
         #13+
         ^C'PROMOTIONAL COPY -- NOT FOR RESALE'#13+
         #13 +
         ^C'Ser. # 0100A197381591')));

       R.Assign(17, 10, 27, 12);
       Insert(New(PButton, Init(R, 'OK', cmOk, bfDefault)));
     end;
     if ValidView(D) <> nil then
     begin
       Desktop^.ExecView(D);
       Dispose(D, Done);
     end;
   end;

PROCEDURE WordSearchObj.PrintOutputFile;
   VAR
      Printer,
      OutputFile:Text;
      PrintBuffer:String;
   BEGIN
      Assign(OutputFile,OutputFileName);
      {$I-} Reset(OutputFile); {$I+}
      IF IOResult>0 THEN Exit;
      Assign(Printer,'PRN');
      Rewrite(Printer);
      WHILE NOT EOF(OutputFile) DO
         BEGIN
            Readln(OutputFile,PrintBuffer);
            Writeln(Printer,PrintBuffer);
         END;
      Writeln(Printer,#12);
      Close(OutputFile);
      Close(Printer);
   END;

PROCEDURE WordSearchObj.ViewOutputFile;
   BEGIN
      IF NotEnoughMemory THEN Exit;
      DeskTop^.Lock;
      DeskTop^.Insert(New(PFileWindow, Init(OutputFileName)));
      IF MyOptions.AutoTiling THEN Tile;
      DeskTop^.Unlock;
   END;

FUNCTION WordSearchObj.NotEnoughMemory:Boolean;
   BEGIN
     IF MaxAvail < (22*1024) THEN
        BEGIN
           Say('Low Memory','Not enough free memory to open another window.',OKButton);
           NotEnoughMemory:=TRUE;
        END
     ELSE NotEnoughMemory:=FALSE;
   END;

{****************************************************************************}
{****************************************************************************}

VAR
   WordSearchApp  : WordSearchObj;

BEGIN {Main Program}
   WordSearchApp.Init;
   IF FilesGone THEN
      BEGIN
         Writeln;
         Writeln('The Capital Source text and/or index files are missing.');
         Writeln;
         Writeln('The file names are CAPSOURC.TXT, CAPSOURC.IN1, CAPSOURC.IN2, and CAPSOURC.IN3.');
         Writeln('Make sure that all of these files are in the same directory as The Capital');
         Writeln('Search (CAPSRCH.EXE).  If any of these files are not on your hard drive,');
         Writeln('re-install the entire program from the distribution disks.');
         Halt;
      END;
   WordSearchApp.Run;
   WordSearchApp.Done;
END.