Browse Source

Add search. Uses new PathStrFind which uses Win32 FindStringOrdinal.

Martijn Laan 1 ngày trước cách đây
mục cha
commit
b09f623d08

+ 34 - 0
Components/PathFunc.pas

@@ -54,6 +54,9 @@ function PathStartsWith(const S, AStartsWith: String;
 function PathStrCompare(const S1: PChar; const S1Length: Integer;
 function PathStrCompare(const S1: PChar; const S1Length: Integer;
   const S2: PChar; const S2Length: Integer;
   const S2: PChar; const S2Length: Integer;
   const IgnoreCase: Boolean = True): Integer;
   const IgnoreCase: Boolean = True): Integer;
+function PathStrFind(const SSource: PChar; const SSourceLength: Integer;
+  const SValue: PChar; const SValueLength: Integer;
+  const IgnoreCase: Boolean = True): Integer;
 function PathStrNextChar(const S: PChar): PChar;
 function PathStrNextChar(const S: PChar): PChar;
 function PathStrPrevChar(const Start, Current: PChar): PChar;
 function PathStrPrevChar(const Start, Current: PChar): PChar;
 function PathStrScan(const S: PChar; const C: Char): PChar;
 function PathStrScan(const S: PChar; const C: Char): PChar;
@@ -619,6 +622,37 @@ begin
   Result := CompareResult - 2;
   Result := CompareResult - 2;
 end;
 end;
 
 
+{ Use our own FindStringOrdinal declaration. The one in the Windows unit is
+  "delayload" (yuck). }
+function FindStringOrdinal_static(dwFindStringOrdinalFlags: DWORD;
+  lpStringSource: LPCWSTR; cchSource: Integer;
+  lpStringValue: LPCWSTR; cchValue: Integer; bIgnoreCase: BOOL): Integer; stdcall;
+  external kernel32 name 'FindStringOrdinal';
+
+function PathStrFind(const SSource: PChar; const SSourceLength: Integer;
+  const SValue: PChar; const SValueLength: Integer;
+  const IgnoreCase: Boolean = True): Integer;
+{ Locates a value in a string, starting with the first character of the string.
+  Returns a 0-based index if found, and -1 otherwise.
+  An ordinal comparison is used, ignoring case by default.
+  A length of -1 may be passed if a string is null-terminated; in that case,
+  the length is determined automatically. }
+begin
+  { This not documented for FindStringOrdinal, but like CompareStringOrdinal it
+    only allows 1 for TRUE in the bIgnoreCase parameter. See above. }
+  const CompareResult = FindStringOrdinal_static(FIND_FROMSTART, SSource, SSourceLength,
+    SValue, SValueLength, BOOL(Byte(IgnoreCase)));
+  if CompareResult = -1 then begin
+    const LastError = GetLastError;
+    if LastError <> ERROR_SUCCESS then
+      raise Exception.CreateFmt('PathStrFind: FindStringOrdinal failed (%u)',
+        [LastError]);
+  end else if not (CompareResult >= 0) and (CompareResult < SSourceLength) then
+    raise Exception.CreateFmt('PathStrFind: FindStringOrdinal result invalid (%d)',
+      [CompareResult]);
+  Result := CompareResult;
+end;
+
 function PathStrNextChar(const S: PChar): PChar;
 function PathStrNextChar(const S: PChar): PChar;
 { Returns pointer to the character after S, unless S points to a null (#0). }
 { Returns pointer to the character after S, unless S points to a null (#0). }
 begin
 begin

+ 1 - 0
Projects/Src/IDE.GotoFileForm.dfm

@@ -57,6 +57,7 @@ object GotoFileForm: TGotoFileForm
     Height = 21
     Height = 21
     Anchors = [akLeft, akTop, akRight]
     Anchors = [akLeft, akTop, akRight]
     TabOrder = 0
     TabOrder = 0
+    OnChange = GotoFileEditChange
     OnKeyDown = GotoFileEditOrListBoxKeyDown
     OnKeyDown = GotoFileEditOrListBoxKeyDown
   end
   end
 end
 end

+ 43 - 0
Projects/Src/IDE.GotoFileForm.pas

@@ -23,19 +23,57 @@ type
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure GotoFileListBoxDblClick(Sender: TObject);
     procedure GotoFileListBoxDblClick(Sender: TObject);
     procedure GotoFileEditOrListBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
     procedure GotoFileEditOrListBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
+    procedure GotoFileEditChange(Sender: TObject);
+  private
+    FFiles: TStrings;
+    procedure SetFiles(Value: TStrings);
+    procedure UpdateGotoFileListBox;
   protected
   protected
     procedure CreateWnd; override;
     procedure CreateWnd; override;
     procedure CreateParams(var Params: TCreateParams); override;
     procedure CreateParams(var Params: TCreateParams); override;
+  public
+    property Files: TStrings write SetFiles;
   end;
   end;
 
 
 implementation
 implementation
 
 
 uses
 uses
   Windows, Messages,
   Windows, Messages,
+  PathFunc,
   IDE.HelperFunc;
   IDE.HelperFunc;
 
 
 {$R *.DFM}
 {$R *.DFM}
 
 
+procedure TGotoFileForm.SetFiles(Value: TStrings);
+begin
+  FFiles := Value;
+  UpdateGotoFileListBox;
+end;
+
+procedure TGotoFileForm.UpdateGotoFileListBox;
+
+  function Match(const &File, Value: String): Boolean;
+  begin
+    Result := (Value = '') or (PathStrFind(PChar(&File), Length(&File), PChar(Value), Length(Value)) >= 0);
+  end;
+
+begin
+  GotoFileListBox.Items.BeginUpdate;
+  try
+    GotoFileListBox.Items.Clear;
+    for var I := 0 to FFiles.Count-1 do
+      if Match(FFiles[I], GotoFileEdit.Text) then
+        GotoFileListBox.Items.AddObject(FFiles[I], TObject(I));
+  finally
+    GotoFileListBox.Items.EndUpdate;
+  end;
+
+  if GotoFileListBox.Items.Count > 0 then
+    GotoFileListBox.ItemIndex := 0;
+
+  OKButton.Enabled := GotoFileListBox.ItemIndex >= 0;
+end;
+
 procedure TGotoFileForm.FormCreate(Sender: TObject);
 procedure TGotoFileForm.FormCreate(Sender: TObject);
 begin
 begin
   InitFormFont(Self);
   InitFormFont(Self);
@@ -56,6 +94,11 @@ begin
   Params.ExStyle := Params.ExStyle or WS_EX_DLGMODALFRAME or WS_EX_WINDOWEDGE;
   Params.ExStyle := Params.ExStyle or WS_EX_DLGMODALFRAME or WS_EX_WINDOWEDGE;
 end;
 end;
 
 
+procedure TGotoFileForm.GotoFileEditChange(Sender: TObject);
+begin
+  UpdateGotoFileListBox;
+end;
+
 procedure TGotoFileForm.GotoFileEditOrListBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
 procedure TGotoFileForm.GotoFileEditOrListBoxKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
 begin
 begin
   if Shift = [] then begin
   if Shift = [] then begin

+ 12 - 1
Projects/Src/IDE.MainForm.pas

@@ -5884,7 +5884,18 @@ procedure TMainForm.EGotoFileClick(Sender: TObject);
 begin
 begin
   const GotoFileForm = TGotoFileForm.Create(Application);
   const GotoFileForm = TGotoFileForm.Create(Application);
   try
   try
-    if GotoFileForm.ShowModal = mrOK then begin
+    const Files = TStringList.Create;
+    try
+      Files.Add(PathExtractName(FMainMemo.Filename));
+      for var IncludedFile in FIncludedFiles do
+        Files.Add(PathExtractName(IncludedFile.Filename));
+      if FPreprocessorOutputMemo.Used then
+        Files.Add(MemosTabSet.Tabs[MemoToTabIndex(FPreprocessorOutputMemo)]);
+      GotoFileForm.Files := Files;
+      if GotoFileForm.ShowModal = mrOK then begin
+      end;
+    finally
+      Files.Free;
     end;
     end;
   finally
   finally
     GotoFileForm.Free;
     GotoFileForm.Free;