home *** CD-ROM | disk | FTP | other *** search
- {=================================================
- Program: SysFile.Exe
- Version: 1.0
- Module: SysFile1.pas
- Author: Wayne Niddery
- CopyRight ⌐ 1995 Wayne Niddery and WinWright
- =================================================}
- unit Sysfile1;
-
- {SysFile1 implements the mainform of the program. All events taking
- place on the main form are handled here. This includes all actions
- on the different pages of the TabbedNoteBook component.}
-
- interface
-
- uses
- SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
- Forms, Dialogs, StdCtrls, TabNotBk, Buttons, ExtCtrls, Menus,
- SysOpts, SysGlb;
-
- type
- {In the visual designer, The TabbedNotebook component was given a
- single page called 'Set Up'. All controls defined below (by Delphi)
- are on this first page of the Notebook with the exception of the
- menu components and Find/Replace dialog components (which are always
- directly on the form)}
- TForm1 = class(TForm)
- Notebook: TTabbedNotebook;
- BottomPanel: TPanel; {Various panel components for both}
- Panel2: TPanel; {appearance and an aid to placing}
- BtnPanel: TPanel; {the other controls when the form}
- FilePanel: TPanel; {needs to change its size}
- AutoPanel: TPanel;
- FileList: TListBox; {FileList displays available files}
- AutoList: TListBox; {AutoList displays opened files}
- FileLabel: TLabel;
- AutoLabel: TLabel;
- bTake: TBitBtn; {Copies file names to AutoList}
- bDrop: TBitBtn; {Removes file names from AutoList}
- bOptions: TBitBtn; {Executes the Options Dialog}
- bHelp: TBitBtn; {Executes the help system}
- EditPopup: TPopupMenu; {Popup menu for TMemo controls}
- mFind: TMenuItem; {Executes Find dialog}
- mReplace: TMenuItem; {Executes Replace dialog}
- N1: TMenuItem;
- mEditRemove: TMenuItem; {Close file & remove from auto list}
- mEditProtect: TMenuItem; {Add file to protection list}
- N3: TMenuItem;
- mEditDelete: TMenuItem; {Delete this file}
- N5: TMenuItem;
- mExit: TMenuItem; {Exit the application}
- AutoPopup: TPopupMenu; {Popup for the Auto Listbox}
- mAutoEdit: TMenuItem;
- mAutoRemove: TMenuItem;
- mAutoProtect: TMenuItem;
- N2: TMenuItem;
- mAutoDelete: TMenuItem;
- FilePopup: TPopupMenu; {Popup for the File Listbox}
- mFileEdit: TMenuItem;
- mFileAdd: TMenuItem;
- mFileProtect: TMenuItem;
- N4: TMenuItem;
- mFileDelete: TMenuItem;
- FindDialog1: TFindDialog;
- ReplaceDialog1: TReplaceDialog;
- procedure FormCreate(Sender: TObject);
- procedure bTakeClick(Sender: TObject);
- procedure bDropClick(Sender: TObject);
- procedure NotebookClick(Sender: TObject);
- procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
- procedure FormResize(Sender: TObject);
- procedure FormKeyUp(Sender: TObject; var Key: Word;
- Shift: TShiftState);
- procedure ListDragOver(Sender, Source: TObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean);
- procedure ListMouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure FileListDragDrop(Sender, Source: TObject; X, Y: Integer);
- procedure AutoListDragDrop(Sender, Source: TObject; X, Y: Integer);
- procedure mDeleteClick(Sender: TObject);
- procedure mEditRemoveClick(Sender: TObject);
- procedure mEditClick(Sender: TObject);
- procedure mExitClick(Sender: TObject);
- procedure mFindClick(Sender: TObject);
- procedure mReplaceClick(Sender: TObject);
- procedure ReplaceDialog1Replace(Sender: TObject);
- procedure bOptionsClick(Sender: TObject);
- procedure ProtectClick(Sender: TObject);
- procedure FindDialog1Find(Sender: TObject);
- procedure bHelpClick(Sender: TObject);
- private
- { Private declarations }
- BtnPanelWidth: integer; {used to help resize form}
- FormHeight: integer; {use design-time height as minimum}
- procedure LoadIniFiles;
- procedure LoadAutoFiles;
- procedure MakePage(pg: integer);
- procedure AdjustSizes;
- function CheckSave(pg: integer; ask: Boolean): integer;
- function DoFind(Sender: TFindDialog): Boolean;
- procedure WMGetMinMaxInfo(var msg: TWMGetMinMaxInfo); message wm_GetMinMaxInfo;
- procedure WMDelOptChanged(var msg: TMessage); message wm_user + DelOptChanged;
- public
- { Public declarations }
- end;
-
- var
- Form1: TForm1;
-
- implementation
-
- {$R *.DFM}
-
- uses
- {SysProt implements the protection list.
- IniFiles is a Delphi unit that makes .INI management easier
- SysGlb stores the global constants and vars needed}
- SysProt, IniFiles;
-
- {FormCreate responds to the OnCreate event}
- procedure TForm1.FormCreate(Sender: TObject);
- begin
- {The OnRestore event is owned by the Application component.
- This event fires when the application is restored from a
- minimized or maximized state. It is being directed to the
- form's OnResize event handler.}
- Application.OnRestore := FormResize;
- {Save width of button panel to help in controlling appearance}
- BtnPanelWidth := BtnPanel.Width;
- {Call private methods to load the FileList and AutoList listboxes
- and open the files in AutoList}
- LoadIniFiles;
- LoadAutoFiles;
- {Read size and position info from INI file and set the main
- form accordingly}
- with SysIni do begin
- SetBounds(
- ReadInteger(iniPosition, iniLeft, Left),
- ReadInteger(iniPosition, iniTop, Top),
- ReadInteger(iniPosition, iniWidth, Width),
- ReadInteger(iniPosition, iniHeight, Height));
- {Read page last displayed so it displays first}
- with NoteBook do
- PageIndex := ReadInteger(iniPosition, iniPage, PageIndex);
- end;
- { AdjustSizes;}
- end;
-
- {Load the names of all .INI files found in the Windows directory
- plus AUTOEXEC.BAT and CONFIG.SYS}
- procedure TForm1.LoadIniFiles;
- var
- ret: integer;
- SRec: TSearchRec;
- begin
- {The FileList listbox is first set to sorted state so .INI files
- will display in alphabetical order}
- FileList.Sorted := True;
- {FindFirst will locate the first INI file. 'faAnyFile' tells Windows
- we want all INI files even if hidden or system attributes are on}
- ret := FindFirst(WinDir + IniFilter, faAnyFile, SRec);
- {Both FindFirst and FindNext return 0 when no more files are found}
- while ret=0 do begin
- FileList.Items.Add(Srec.Name); {Add file name to listbox}
- ret := FindNext(SRec); {get the next file name}
- end;
- {The sorted state is now turned off so we can force AUTOEXEC.BAT
- and CONFIG.SYS to the top of the list}
- FileList.Sorted := False;
- FileList.Items.Insert(0, AutoExec);
- FileList.Items.Insert(1, Config);
- end;
-
- {LoadAutoFiles reads the list of files to be opened from the .INI
- file. If this file hasn't been created yet then it gets a default
- list of files to open from the Protection list in SysProt. This
- default list was defined in the TMemo component of the SysProt
- form at design time. For each file opened, a page is added to the
- notebook component, a TMemo component is added to the page and the
- file is then loaded into the TMemo ready for viewing / editing}
- procedure TForm1.LoadAutoFiles;
- var
- i, pos: integer;
- s: string;
- begin
- {Initialize AutoList}
- if not FileExists(SysIni.FileName) then
- {copy from default list, but don't include SYSFILE.INI}
- for i := 0 to High(DefProt)-1 do
- AutoList.Items.Add(Defprot[i])
- else begin
- {read file names from INI file}
- i := 0;
- repeat
- {the variable i is used as a key to get each file name from
- the .INI file. When there are no more strings, a string of
- zero length is returned}
- s := SysIni.ReadString(iniAutoOpen, IntToStr(i), '');
- if Length(s) > 0 then AutoList.Items.Add(s); {add to listbox}
- inc(i); {next INI key}
- until Length(s) = 0;
- end;
- with NoteBook do begin
- {create a page for each selected file name}
- for i := 0 to AutoList.Items.Count - 1 do begin
- Pages.Insert(i, AutoList.Items[i]); {add new page for file name}
- MakePage(i); {add a memo and load selected file into it}
- end;
- PageIndex := 0; {Focus first selected file. This may be changed
- after returning to the FormCreate method}
- end;
- end;
-
- {MakePage does the work of creating and initializing a TMemo
- component to be placed on a notebook page. The ofs parameter
- is the page number to place the TMemo on. It has been coded in
- a separate procedure because it needs to be used by a few other
- methods in the application}
- procedure TForm1.MakePage(pg: integer);
- var
- Memo: TMemo;
- begin
- {create a new TMemo with Form1 as the owner}
- Memo := TMemo.Create(Form1);
- with Memo do begin
- {the Page component of the notebook will be parent of the TMemo}
- Parent := TTabPage(NoteBook.Pages.Objects[pg]);
- Align := alClient; {fill entire page}
- ScrollBars := ssBoth; {display both scroll bars}
- TabStop := True; {let it receive focus}
- WordWrap := False; {don't wrap lines of these files}
- PopupMenu := EditPopup; {assign a popup menu}
- HideSelection := False; {always allow selected text to show}
- HelpContext := Editing_a_File; {context help on F1}
- {save file name in Hint property for easy access}
- Hint := NoteBook.Pages.Strings[pg];
- {construct a complete file path in the Hint property}
- if (Hint = AutoExec) or (Hint = Config) then Hint := Root + Hint
- else Hint := WinDir + Hint;
- Lines.LoadFromFile(Hint); {open and read in the file}
- end;
- end;
-
- {The form is resizeable by the user and, whenever a page is added
- or removed from the notebook component, the notebook component may
- grow or shrink in size. The AdjustSizes method, called by other
- methods such as FormResize, adjusts the width of the Panel components
- containing the list boxes so they stay proportional within the form}
- procedure TForm1.AdjustSizes;
- var
- space: integer;
- pt: TPoint;
- begin
- with NoteBook do begin
- {try to keep tabs from gettng to short for the file names}
- TabsPerRow := Form1.Width div 100;
- {Get current width of notebook page. The Objects property contains
- a set of TTabPage components which represent each of the pages.
- The Objects property itself is of type TObject, so in order to
- access the properties of TTabPage, Objects[x] must be typecasted
- as a TTabPage}
- space := TTabPage(Pages.Objects[Pages.Count-1]).Width;
- {subtract width of panel containing buttons and divide in half}
- space := (space - BtnPanelWidth) div 2;
- {allocate equal space to both list box panels}
- FilePanel.Width := space;
- AutoPanel.Width := space;
- {adjust label to line up with AutoList listbox}
- AutoLabel.Left := AutoPanel.Left;
- end;
- {Adjust form height so all buttons remain visible}
- pt := bHelp.ClientToScreen(Point(0, bHelp.Height));
- space := pt.y - Top + BottomPanel.Height + 16;
- {allow height to be larger than needed}
- if space > Height then Height := space;
- end;
-
- {CheckSave is call by other routines to check whether a file has been
- modified. If it has, the user is prompted if necessary and the
- file is saved if so indicated}
- function TForm1.CheckSave(pg: integer; ask: Boolean): integer;
- begin
- Result := mrNo; {assume no modifications yet}
- {address the specified TMemo}
- with TMemo(TTabPage(NoteBook.Pages.Objects[pg]).Controls[0]) do begin
- if Modified then begin {changes made}
- if ask then begin {let user decide if prompt option set}
- if (OptionsDlg.SaveGroup.ItemIndex = opPromptEach) then
- Result := MessageDlg(Hint + ' has changed. Save?',
- mtConfirmation, mbYesNoCancel, 0)
- else if (OptionsDlg.SaveGroup.ItemIndex = opPromptOnce) then
- Result := MessageDlg('One or more files have changed. Save?',
- mtConfirmation, mbYesNoCancel, 0)
- else Result := mrYes; {auto save the file}
- end;
- if Result = mrCancel then Exit {cancel request}
- else if Result = mrYes then Lines.SaveToFile(Hint); {save file}
- end;
- end;
- end;
-
- {This procedure handles the OnClick event of the NoteBook component.
- When the notebook tabs are clicked, the notebook flips to the selected
- page but it then remains the focused control. We want one of the controls
- on the notebook page to get focus. For most, this is always just the
- single TMemo component. For the Setup page, it can be any component
- except the TLabels. TLabels can't get focus (and so don't have a SetFocus
- method). What TLabels do have though is a FocusControl property that can
- be set to associate the TLabel with some other component. This was done
- at design time for the two labels that name the listboxes}
- procedure TForm1.NoteBookClick(Sender: TObject);
- begin
- with NoteBook, NoteBook.Pages do begin
- if TTabPage(Objects[PageIndex]).Controls[0] is TLabel then
- TLabel(TTabPage(Objects[PageIndex]).Controls[0]).FocusControl.SetFocus
- else {whether 1st control is TMemo, TListBox, or TButton...}
- TWinControl(TTabPage(Objects[PageIndex]).Controls[0]).SetFocus;
- end;
- AdjustSizes; {In case Set Up selected and form previously resized}
- end;
-
- {This handles clicks on the Take button and the Add menu item. It loops
- through each file name selected (highlighted) in the FileList listbox,
- adds it to the AutoList listbox, adds a page for it to the notebook and
- calls MakePage to create a TMemo and load in the selected file. When a
- new page is added to a TabbedNoteBook component, focus is given to the
- new page. Once all pages have been added, we want focus to return to the
- Setup page. To do this, the name of the setup page is first saved (because
- its page index value will change while adding other pages) so it can be
- assigned as the active page at the end. Also, if more than one page is
- being added, the notebook is hidden during the process. This makes the
- process much faster and the appearance cleaner and more professional
- looking}
- procedure TForm1.bTakeClick(Sender: TObject);
- var
- i, idx: integer;
- ap: string[12];
- begin
- if FileList.SelCount > 0 then begin {see if any selected}
- for i := 0 to FileList.Items.Count-1 do {loop through items}
- if FileList.Selected[i] then begin {see if selected}
- if FileList.SelCount > 1 then NoteBook.Hide; {hide process}
- {skip if already in auto list}
- if AutoList.Items.IndexOf(FileList.Items[i]) < 0 then begin
- idx := AutoList.Items.Add(FileList.Items[i]); {add to auto list}
- with NoteBook do begin {add new page}
- {insert at last position - pushes SetUp down}
- Pages.Insert(idx, FileList.Items[i]);
- MakePage(idx);
- end;
- end;
- end;
- AdjustSizes; {adjust setup page properly}
- NoteBook.PageIndex := NoteBook.Pages.Count - 1; {back to Setup page}
- if not NoteBook.Showing then NoteBook.Show; {display again}
- {Send Windows message to FileList listbox to clear selected items}
- SendMessage(FileList.Handle, lb_SelItemRange, 0, FileList.Items.Count);
- end;
- end;
-
- {This handles the clicks on the Drop button and the Remove menu item in
- the popup menus. The logic is basically the same as above for the
- Take button, but is simpler}
- procedure TForm1.bDropClick(Sender: TObject);
- var
- i, idx: integer;
- NotAsked: Boolean;
- begin
- NotAsked := True;
- if AutoList.SelCount > 0 then begin {see if any selected}
- if AutoList.SelCount > 1 then NoteBook.Hide; {hide process}
- for i := AutoList.Items.Count-1 downto 0 do begin {loop through items}
- if AutoList.Selected[i] then begin {see if selected}
- {find page index in notebook}
- idx := NoteBook.GetIndexForPage(AutoList.Items[i]);
- {check if file modified and save if necessary}
- if CheckSave(idx, NotAsked) = mrCancel then break;
- if OptionsDlg.SaveGroup.ItemIndex = opPromptOnce then
- NotAsked := False; {so CheckSave won't prompt again}
- {Because the Parent property of the TMemo component on this page
- was assigned to the page (TTabSet component), it will be
- destroyed for us by the TTabset component when we destroy the
- TTabset in the next statement}
- NoteBook.Pages.Delete(idx); {delete notebook page}
- AutoList.Items.Delete(i); {delete from Autolist}
- end;
- end;
- AdjustSizes;
- if not NoteBook.Showing then NoteBook.Show;
- end;
- end;
-
- {FormCloseQuery checks each open file to see if it has been modified.
- If so, it is saved. If one of the two prompt options is checked then
- a message is displayed accordingly (either for each modified file or
- once for the first modified file. If prompting for each, user has the
- option to skip saving any particular file. For both prompt options,
- user can cancel the Exit request and return to the application. If
- user does not cancel, then after modified files are saved, the INI
- file is updated. User is then given option to reboot system (if
- AUTOEXEC.BAT or CONFIG.SYS is modified) or restarting windows (if one
- or more INI files have been changed but not AUTOEXEC OR CONFIG)}
- procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
- var
- i, idx, mods, ret: integer;
- NotAsked, Boot: boolean;
- rw: longint; {simply a place holder for ExitWindows API call}
- strz: array [0..145] of char; {temp asciiz string to close help}
-
- begin
- mods := 0;
- CanClose := False;
- Boot := False;
- NotAsked := True;
- {memos are owned by the form, so look for them}
- for i := 0 to AutoList.Items.Count - 1 do begin
- idx := NoteBook.GetIndexForPage(AutoList.Items[i]);
- ret := CheckSave(idx, NotAsked);
- if OptionsDlg.SaveGroup.Itemindex = opPromptOnce then
- NotAsked := False;
- if ret = mrCancel then exit
- else if ret = mrNo then continue;
- Inc(mods); {count number saved}
- {see if a boot is called for}
- if (Pos(AutoExec, AutoList.Items[i]) > 0)
- or (Pos(Config, AutoList.Items[i]) > 0) then Boot := True
- else
- end;
-
- {Erase AutoSave section in INI file, then save names of open files}
- SysIni.EraseSection(iniAutoOpen);
- for i := 0 to AutoList.Items.Count -1 do
- SysIni.WriteString(iniAutoOpen, IntToStr(i), AutoList.Items[i]);
- {save the position and size of the form and the current page}
- with SysIni do begin
- WriteInteger(iniPosition, iniLeft, Left);
- WriteInteger(iniPosition, iniTop, Top);
- WriteInteger(iniPosition, iniWidth, Width);
- WriteInteger(iniPosition, iniHeight, Height);
- WriteInteger(iniPosition, iniPage, NoteBook.PageIndex);
- end;
-
- {make sure the help file gets closed}
- StrPCopy(strz, Application.HelpFile);
- WinHelp(Application.Handle, strz, help_Quit, 0);
-
- CanClose := True; {proceed with program termination}
- if Boot then begin {boot is called for}
- if MessageDlg(RebootMsg, mtConfirmation, [mbYes, mbNo], 0) = mrYes
- then ExitWindows(ew_RebootSystem, rw);
- end
- else if mods>0 then begin {Windows restart is called for}
- if MessageDlg(RestartMsg, mtConfirmation, [mbYes, mbNo], 0) = mrYes
- then ExitWindows(ew_RestartWindows, rw);
- end;
- end;
-
- {This handles the OnResize event. All that's required is to adjust
- the components on the Setup page}
- procedure TForm1.FormResize(Sender: TObject);
- begin
- AdjustSizes;
- end;
-
- {This handles the OnKeyUp event. Here we allow the Delete and Insert
- keys to be used to add or remove selected files to/from AutoList.
- NOTE: The KeyPreview property must be set True for the form in order
- to receive OnClick events for control keys such as these}
- procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
- Shift: TShiftState);
- begin
- if key = vk_Delete then bDrop.Click {fake click on Drop button}
- else if key = vk_Insert then bTake.Click; {fake click on Take button}
- end;
-
- {OnMouseDown handler for FileList and AutoList list boxes. If option
- for Drag 'n Drop is on, then start the drag. DragMode for the
- list boxes must be set to dmManual so we can decide here. The reason
- drag and drop is an option is because without it, user can drag mouse
- to highlight multiple entries in the listbox.}
- procedure TForm1.ListMouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- begin
- if OptionsDlg.ckUseDrag.Checked then
- (Sender as TListBox).BeginDrag(True);
- end;
-
- {This handles the OnDragOver event. The Take and Drop buttons and both
- listboxes have their OnDragOver events assigned to this method.
- Sender is the component the mouse is currently over.
- Source is the component where dragging originated.
- We need to determine whether the component being dragged is allowed
- to be dropped on the component currently under the mouse.
- The combinations are:
- 1. Since only the two list boxes can be dragged, it's always valid to
- drop on a listbox (you must allow a component to "drop" on itself
- in order for the proper cursor to appear when dragging starts).
- 2. The FileList can drop on the Take button
- 3. The AutoList can drop on the Drop button}
- procedure TForm1.ListDragOver(Sender, Source: TObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean);
- begin
- if (Sender is TListBox) {itself or other list box is OK}
- or ((Source = FileList) and (Sender = bTake))
- or ((Source = AutoList) and (Sender = bDrop))
- then begin
- Accept :=True; {allow the drop if mouse is released over Sender}
- {Just a nice touch here; see if single or multiple file names
- are selected and display the appropriate cursor}
- if (Source as TListBox).SelCount > 1 then
- (Source as TListBox).DragCursor := crMultiDrag
- else
- (Source as TListBox).DragCursor := crDrag;
- end
- else Accept := False; {combination not valid for drop}
- end;
-
- {Handles OnDragDrop event for FileList. The only check that needs to
- be made here is that user is not attempting to drop on the same
- listbox s/he dragged from. All other valid combinations are checked
- in the OnDragDrop handler}
- procedure TForm1.FileListDragDrop(Sender, Source: TObject; X, Y: Integer);
- begin
- if OptionsDlg.ckUseDrag.Checked then {fake click on Drop button}
- if Sender <> Source then bDrop.Click;
- end;
-
- {Handles OnDragDrop for AutoList. Same check as for FileList}
- procedure TForm1.AutoListDragDrop(Sender, Source: TObject; X, Y: Integer);
- begin
- if OptionsDlg.ckUseDrag.Checked then {fake click on Take button}
- if Sender <> Source then bTake.Click;
- end;
-
- {This method is called when the Delete menu item is selected from any
- of the three popup menus. They must be handled differently depending
- on which popup it was selected from}
- procedure TForm1.mDeleteClick(Sender: TObject);
- var
- sel, idx, ret: integer;
- path: string;
- List: TListBox;
-
- {Because only the actual file name is stored in the list boxes and
- on the Tabs of the Notebook pages, GetName is needed to construct
- the complete path name}
- procedure GetName;
- begin
- if Sender = mEditDelete then begin {one of the TMemos}
- path := TTabPage(NoteBook.Pages.Objects[NoteBook.PageIndex])
- .Controls[0].Hint; {get full path name}
- end
- else begin {one of the list boxes}
- path := List.Items[sel]; {List was set before calling GetName}
- if (path = AutoExec) or (path = Config) then {build path}
- path := Root + path
- else
- path := WinDir + path;
- end;
- end;
-
- {CanDelete checks the protection list to determine whether ot not
- the currently selected file name can be deleted. If currently
- protected, user is informed that deletion will not occur}
- function CanDelete(const name: string): boolean;
- begin
- with ProtectDlg.ProtList.Lines do
- Result := IndexOf(ExtractFileName(name)) < 0; {look for file name}
- if not Result then {yes, it's in protect list}
- Messagebeep(mb_IconInformation);
- MessageDlg(name + ' is in the protection list and will not be deleted',
- mtInformation, [mbOK], 0);
- end;
-
- begin
- {if No Delete option selected then just ignore request. Note that
- this check should be redundant as we are disabling the the Delete
- menu items when the No Delete radio button is set}
- if OptionsDlg.DeleteGroup.ItemIndex = opNoDelete then exit;
-
- if Sender = mEditDelete then begin {from a TMemo}
- GetName; {construct full path name}
- if CanDelete(path) then begin {make sure file not protected}
- {get confirmation if Confirm option set}
- if OptionsDlg.DeleteGroup.ItemIndex = opConfirm then begin
- MessageBeep(mb_IconQuestion);
- ret := MessageDlg('Are you sure you want to delete ' + path,
- mtWarning, [mbYes, mbNo], 0);
- if ret = mrNo then Exit; {user had second thoughts}
- end;
- DeleteFile(path); {physically delete the file from disk}
- {remove file name from Autolist and FileList}
- AutoList.Items.Delete(AutoList.Items.IndexOf(NoteBook.ActivePage));
- FileList.Items.Delete(FileList.Items.IndexOf(NoteBook.ActivePage));
- {remove page from notebook}
- NoteBook.Pages.Delete(NoteBook.PageIndex);
- end;
- end else begin {from a list box}
- {setting a local variable to the list box responsible for the
- delete request simplifies the code}
- if (Sender = mFileDelete) then List := FileList
- else List := AutoList;
- {loop through file names in whichever list sent request}
- for sel := List.Items.Count - 1 downto 0 do
- if List.Selected[sel] then begin {a highlighted file name}
- GetName; {construct full path from this file name}
- if not CanDelete(path) then continue; {check if protected}
- if OptionsDlg.DeleteGroup.ItemIndex = opConfirm then begin
- MessageBeep(mb_IconQuestion);
- ret := MessageDlg('Are you sure you want to delete ' +
- path, mtWarning, mbYesNoCancel, 0);
- if ret = mrNo then continue {try next file name}
- else if ret = mrCancel then break; {skip remaining selects}
- end else
- if List.SelCount > 1 then NoteBook.Hide; {faster, looks better}
- DeleteFile(path); {physically delete from disk}
- if Sender = mAutoDelete then begin
- {find corresponding file name in notebook pages and in
- FileList and remove}
- FileList.Items.Delete(FileList.Items.IndexOf(AutoList.Items[sel]));
- NoteBook.Pages.Delete(Notebook.GetIndexForPage(AutoList.Items[sel]));
- AutoList.Items.Delete(sel); {remove from AutoList}
- end
- else begin {called from FileList}
- {see if file name exists in AutoList}
- idx := AutoList.Items.IndexOf(FileList.Items[sel]);
- if idx >=0 then begin {in Auto List}
- AutoList.Items.Delete(idx); {so remove it}
- {now find which page contains this file...}
- idx := NoteBook.GetIndexForPage(FileList.Items[sel]);
- NoteBook.Pages.Delete(idx); {...and remove the page}
- end;
- FileList.Items.Delete(sel); {remove from FileList}
- end;
- end;
- AdjustSizes; {adjust setup components}
- if not NoteBook.Showing then NoteBook.Show; {make visible again}
- end;
- end;
-
- {Handles click on Remove menu item in Popup for TMemos}
- procedure TForm1.mEditRemoveClick(Sender: TObject);
- begin
- {see if file modified and save if necessary}
- if CheckSave(NoteBook.PageIndex, True) = mrCancel then Exit;
- {delete currently active file from Autolist}
- AutoList.Items.Delete(AutoList.Items.IndexOf(NoteBook.ActivePage));
- {remove page from notebook}
- NoteBook.Pages.Delete(NoteBook.PageIndex);
- AdjustSizes;
- end;
-
- {handles Edit menu item from either list box}
- procedure TForm1.mEditClick(Sender: TObject);
- var
- List: TListBox;
- idx: integer;
- begin
- {set List to calling listbox. Simplifies checking}
- if Sender = mAutoEdit then List := AutoList
- else List := FileList;
- if List.SelCount <> 1 then begin {can only edit one file at a time}
- MessageBeep(mb_IconInformation);
- MessageDlg('Please select a single item to Edit',
- mtInformation, [mbok], 0);
- end
- else begin {make this page current}
- idx := AutoList.Items.IndexOf(List.Items[List.ItemIndex]);
- if idx<0 then begin {need to add file to AutoList and NoteBook}
- bTakeClick(Sender); {fake click on Take button}
- idx := NoteBook.Pages.Count - 2; {set focus to new page}
- end;
- NoteBook.PageIndex := idx; {set as current page}
- NoteBookClick(Sender); {focus to the TMemo}
- end;
- end;
-
- {For the Exit menu item, simply close the application}
- procedure TForm1.mExitClick(Sender: TObject);
- begin
- Close;
- end;
-
- {Handles clicks on the Find menu item}
- procedure TForm1.mFindClick(Sender: TObject);
- begin
- with TMemo(TTabPage(NoteBook.Pages.Objects[NoteBook.PageIndex])
- .Controls[0]) do
- if SelLength > 0 then {highlighted text...}
- FindDialog1.FindText := SelText; {... so use as default find text}
- FindDialog1.Execute; {display find dialog}
- end;
-
- {Handles clicks on the Replace menu item}
- procedure TForm1.mReplaceClick(Sender: TObject);
- begin
- with TMemo(TTabPage(NoteBook.Pages.Objects[NoteBook.PageIndex])
- .Controls[0]) do
- if SelLength > 0 then
- ReplaceDialog1.FindText := SelText;
- ReplaceDialog1.Execute;
- end;
-
- {This is the search engine. It's used by both the Find and Replace
- Dialogs}
- function TForm1.DoFind(Sender: TFindDialog): Boolean;
- var
- TLen: Integer;
- Tx, TxPos, FStr: PChar;
- begin
- with TMemo(TTabPage(NoteBook.Pages.Objects[NoteBook.PageIndex])
- .Controls[0]) do begin
- TLen := GetTextLen + 1; {length of TMemo's text + 1 for #0}
- Tx := StrAlloc(TLen); {get memory from Windows}
- GetTextBuf(Tx, TLen); {get the entire text from the TMemo}
- FStr := StrAlloc(Length(Sender.FindText) + 1); {memory for find text}
- StrPCopy(FStr, Sender.FindText); {convert pascal find text to ASCIIZ}
- if not (frMatchCase in Sender.Options) then begin
- StrUpper(Tx); StrUpper(FStr); {so case doesn't matter}
- end;
- TxPos := Tx + SelStart + SelLength; {start search at caret position}
- TxPos := StrPos(TxPos, Fstr); {look for the string}
- if TxPos <> nil then begin {Found it!}
- SelStart := TxPos - Tx; {Set caret to found string}
- SelLength := Length(Sender.FindText); {highlight it!}
- Result := True; {let caller know it was found}
- end else
- Result :=False; {string not found}
- end;
- end;
-
- {Handle click on FindNext button (on either Find or Replace dialogs)}
- procedure TForm1.FindDialog1Find(Sender: TObject);
- begin
- if not DoFind(TFindDialog(Sender)) then {string not found}
- ShowMessage(''''+ TFindDialog(Sender).FindText +''' not found');
- end;
-
- {Handle click on Replace or Replace All buttons}
- procedure TForm1.ReplaceDialog1Replace(Sender: TObject);
- var
- reps: Integer;
- begin
- reps := 0;
- with TMemo(TTabPage(NoteBook.Pages.Objects[NoteBook.PageIndex])
- .Controls[0]) do begin
- {if highlighted text doesn't match search string do initial search}
- if SelText <> ReplaceDialog1.FindText then
- DoFind(TFindDialog(Sender));
- {if highlighted text DOES = search string, do initial replace}
- if SelText = ReplaceDialog1.FindText then begin
- Seltext := ReplaceDialog1.ReplaceText;
- Inc(reps);
- end;
- {see if Replace All button clicked}
- if frReplaceAll in ReplaceDialog1.Options then begin
- {search for all matches from current caret position}
- while DoFind(TFindDialog(Sender)) do begin
- {replace each one}
- Seltext := ReplaceDialog1.ReplaceText;
- Inc(reps);
- end;
- if reps > 1 then {show how many were done}
- ShowMessage('Performed ' + IntToStr(reps) + ' replacements');
- end;
- if reps = 0 then
- ShowMessage(''''+ TFindDialog(Sender).FindText +''' not found');
- end;
- end;
-
- {executes the Options dialog}
- procedure TForm1.bOptionsClick(Sender: TObject);
- begin
- OptionsDlg.ShowModal;
- end;
-
- {handles clicks on the protect menu items}
- procedure TForm1.ProtectClick(Sender: TObject);
- var
- List: TListBox;
- i: integer;
- begin
- if Sender = mEditProtect then {from a TMemo}
- ProtectDlg.ProtList.Lines.Add(NoteBook.ActivePage)
- else begin {from a list box}
- if Sender = mAutoProtect then List := AutoList
- else List := FileList;
- for i := 0 to List.Items.Count - 1 do begin
- if List.Selected[i] then {add all selected items}
- ProtectDlg.ProtList.Lines.Add(List.Items[i]);
- end;
- end;
- end;
-
- {this handles a Windows message that lets us tell Windows the
- minimum size it should allow our app to be sized by the user}
- procedure TForm1.WMGetMinMaxInfo(var msg: TWMGetMinMaxInfo);
- var
- pt1, pt2: TPoint;
- ht: integer;
- begin
- {first time we get this message, form1 controls aren't yet created}
- if BtnPanel <> nil then begin
- {map bottom of help button to screen coordinate}
- pt1 := bHelp.ClientToScreen(Point(0, bHelp.Height));
- {calc distance from top of Form1, add height of lower panel + extra}
- ht := pt1.y - Top + BottomPanel.Height + 16;
- {that's minimum needed to keep help button in view}
- msg.MinMaxInfo^.ptMinTrackSize.y := ht;
- {keep reasonable width for 3 tab columns in notebook}
- msg.MinMaxInfo^.ptMinTrackSize.x := 301;
- msg.result := 0;
- end else
- msg.result := 1;
- end;
-
- {if the Delete option on the Options Dialog changes, OptionDlg
- sends a message to Form1 so the Delete menu items on the pop-up
- menus can be disabled or enabled as appropriate}
- procedure TForm1.WMDelOptChanged(var msg: TMessage);
- begin
- {set Delete menu item on Edit popup to enabled if deletes allowed}
- mEditDelete.Enabled := (OptionsDlg.DeleteGroup.ItemIndex <> opNoDelete);
- {set Delete menu item on listbox popups to same value}
- mFileDelete.Enabled := mEditDelete.Enabled;
- mAutoDelete.Enabled := mEditDelete.Enabled;
- end;
-
- var
- {a temporary variable. Only used in initialization code below}
- strz: pchar;
-
- {All units can optionally have an initialization section at the end.
- This section (in each unit, and in the order the units are referenced
- in the DPR's Uses clause) executes before the main code of the program
- (in project's DPR). This allows an opportunity to set certain things up
- such as global resources.}
- procedure TForm1.bHelpClick(Sender: TObject);
- begin
- Application.HelpCommand(Help_Contents, 0);
- end;
-
- initialization
- {allocate enough memory to hold longest possible path name}
- strz := StrAlloc(145);
- {get the system's Windows directory path}
- GetWindowsDirectory(strz, 145);
- {Append a '\' to it so file names can be appended}
- WinDir := StrPas(strz) + Slash;
- {dispose the temporary memory}
- StrDispose(strz);
- {create a TIniFile object to handle our own INI file}
- SysIni := TIniFile.Create(WinDir +
- ChangeFileExt(ExtractFileName(Application.ExeName),'.INI'));
- end.
-