diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi
index 5e24ff97..0e50dd57 100644
--- a/lazproj/coedit.lpi
+++ b/lazproj/coedit.lpi
@@ -126,7 +126,7 @@
-
+
@@ -218,6 +218,14 @@
+
+
+
+
+
+
+
+
diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr
index a2265302..4098f904 100644
--- a/lazproj/coedit.lpr
+++ b/lazproj/coedit.lpr
@@ -9,7 +9,7 @@ uses
Interfaces, Forms, lazcontrols, runtimetypeinfocontrols, ce_widget,
ce_dmdwrap, ce_common, ce_synmemo, ce_main, ce_messages, ce_editor,
ce_projinspect, ce_projconf, jsonparser, ce_project,
- ce_widgettypes, ce_staticexplorer;
+ ce_widgettypes, ce_staticexplorer, ce_search;
{$R *.res}
diff --git a/src/ce_common.pas b/src/ce_common.pas
index 94740ac0..bda20ffa 100644
--- a/src/ce_common.pas
+++ b/src/ce_common.pas
@@ -7,6 +7,33 @@ interface
uses
Classes, SysUtils, ActnList, dialogs, forms;
+type
+
+ (**
+ * MRU list for strings
+ *)
+ TMRUList = class(TStringList)
+ private
+ fMaxCount: Integer;
+ protected
+ procedure setMaxCount(aValue: Integer);
+ function checkItem(const S: string): boolean; virtual;
+ procedure Put(Index: Integer; const S: string); override;
+ published
+ property maxCount: Integer read fMaxCount write setMaxCount;
+ public
+ constructor Create;
+ procedure Insert(Index: Integer; const S: string); override;
+ end;
+
+ (**
+ * MRU list for filenames
+ *)
+ TMRUFileList = class(TMRUList)
+ protected
+ function checkItem(const S: string): boolean; override;
+ end;
+
(**
* Save a component with a readable aspect.
*)
@@ -45,9 +72,45 @@ uses
*)
function uniqueObjStr(const aObject: Tobject): string;
-
implementation
+constructor TMRUList.Create;
+begin
+ fMaxCount := 10;
+end;
+
+procedure TMRUList.setMaxCount(aValue: Integer);
+begin
+ if aValue < 0 then aValue := 0;
+ if fMaxCount = aValue then exit;
+ while Count > fMaxCount do delete(Count-1);
+end;
+
+function TMRUList.checkItem(const S: string): boolean;
+begin
+ exit( indexOf(S) = -1 );
+end;
+
+procedure TMRUList.Put(Index: Integer; const S: string);
+begin
+ if not (checkItem(S)) then exit;
+ inherited;
+ while Count > fMaxCount do delete(Count-1);
+end;
+
+procedure TMRUList.Insert(Index: Integer; const S: string);
+begin
+ if not (checkItem(S)) then exit;
+ inherited;
+ while Count > fMaxCount do delete(Count-1);
+end;
+
+function TMRUFileList.checkItem(const S: string): boolean;
+begin
+ exit( inherited checkItem(S) and fileExists(S));
+end;
+
+
procedure saveCompToTxtFile(const aComp: TComponent; const aFilename: string);
var
str1, str2: TMemoryStream;
@@ -102,71 +165,34 @@ begin
end;
function patchPlateformPath(const aPath: string): string;
+function patchProc(const src: string; const invalid: char): string;
var
i: Integer;
+begin
+ result := src;
+ i := pos(invalid, result);
+ if i <> 0 then
+ begin
+ repeat
+ result[i] := directorySeparator;
+ i := pos(invalid,result);
+ until
+ i = 0;
+ end;
+end;
begin
result := aPath;
{$IFDEF MSWINDOWS}
- i := pos('/',result);
- if i <> 0 then
- begin
- repeat
- result[i] := directorySeparator;
- i := pos('/',result);
- until
- i = 0;
- end;
- i := pos(':',result);
- if i <> 0 then
- begin
- repeat
- result[i] := directorySeparator;
- i := pos(':',result);
- until
- i = 0;
- end;
+ result := patchProc(result,'/');
+ result := patchProc(result,':');
{$ENDIF}
-
{$IFDEF LINUX}
- i := pos('\',result);
- if i <> 0 then
- begin
- repeat
- result[i] := directorySeparator;
- i := pos('\',result);
- until
- i = 0;
- end;
- i := pos(':',result);
- if i <> 0 then
- begin
- repeat
- result[i] := directorySeparator;
- i := pos(':',result);
- until
- i = 0;
- end;
+ result := patchProc(result,'\');
+ result := patchProc(result,':');
{$ENDIF}
-
{$IFDEF MACOS}
- i := pos('\',result);
- if i <> 0 then
- begin
- repeat
- result[i] := directorySeparator;
- i := pos('\',result);
- until
- i = 0;
- end;
- i := pos('/',result);
- if i <> 0 then
- begin
- repeat
- result[i] := directorySeparator;
- i := pos('/',result);
- until
- i = 0;
- end;
+ result := patchProc(result,'\');
+ result := patchProc(result,'/');
{$ENDIF}
end;
@@ -249,4 +275,9 @@ begin
{$HINTS ON}{$WARNINGS ON}
end;
+operator =(lhs,rhs: TPoint): boolean;
+begin
+ exit( (lhs.x = rhs.x) and (lhs.y = rhs.y) );
+end;
+
end.
diff --git a/src/ce_d2syn.pas b/src/ce_d2syn.pas
index 14631ef0..c83ce6ff 100644
--- a/src/ce_d2syn.pas
+++ b/src/ce_d2syn.pas
@@ -44,11 +44,12 @@ type
values: array of string;
end;
+ // TODO: rather gperf ?
TD2Dictionary = object
private
fLongest: NativeInt;
- fEntries: array[0..1023] of TD2DictionaryEntry;
- function toHash(const aValue: string): word;
+ fEntries: array[0..255] of TD2DictionaryEntry;
+ function toHash(const aValue: string): Byte;
procedure addEntry(const aValue: string);
public
constructor create;
@@ -227,20 +228,14 @@ begin
end;
{$IFDEF DEBUG}{$R-}{$ENDIF}
-function TD2Dictionary.toHash(const aValue: string): word;
+function TD2Dictionary.toHash(const aValue: string): Byte;
var
i, len: Integer;
- prev: word;
begin
result := 0;
- prev := 0;
len := length(aValue);
for i := 1 to len do
- begin
- result += ((Byte(aValue[i]) + 64) shl i) xor prev;
- prev := Byte(aValue[i]);
- end;
- result := result and 1023;
+ result += (Byte(aValue[i]) shl i) xor 63;
end;
{$IFDEF DEBUG}{$R+}{$ENDIF}
@@ -458,6 +453,8 @@ TODO:
- comments: correct nested comments handling.
}
procedure TSynD2Syn.next;
+label
+ _postString1;
begin
fTokStart := fTokStop;
@@ -613,8 +610,8 @@ begin
begin
if not (readNext = '"') then
begin
- fTokKind := tkIdent;
- exit; // warning: a goto is avoided but any other r/x is not detectable since it's truncated as tkIdent
+ Dec(fTokStop);
+ goto _postString1;
end;
end;
// go to end of string/eol
@@ -631,6 +628,7 @@ begin
exit;
end;
end;
+ _postString1:
// string 2
if fRange = rkString2 then
diff --git a/src/ce_main.pas b/src/ce_main.pas
index 19fa510e..0c9003fe 100644
--- a/src/ce_main.pas
+++ b/src/ce_main.pas
@@ -7,9 +7,9 @@ interface
uses
Classes, SysUtils, FileUtil, SynEditKeyCmds, SynHighlighterLFM, Forms,
AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg, Controls, Graphics,
- Dialogs, Menus, ActnList, ExtCtrls, ComCtrls, process,
+ Dialogs, Menus, ActnList, ExtCtrls, process,
ce_common, ce_dmdwrap, ce_project, ce_synmemo, ce_widget, ce_messages,
- ce_editor, ce_projinspect, ce_projconf, ce_staticexplorer;
+ ce_editor, ce_projinspect, ce_projconf, ce_staticexplorer, ce_search;
type
@@ -142,6 +142,7 @@ type
fProjWidg: TCEProjectInspectWidget;
fPrjCfWidg: TCEProjectConfigurationWidget;
fStExpWidg: TCEStaticExplorerWidget;
+ fFindWidg: TCESearchWidget;
// widget interfaces subroutines
procedure checkWidgetActions(const aWidget: TCEWidget);
@@ -207,12 +208,14 @@ begin
fProjWidg := TCEProjectInspectWidget.create(nil);
fPrjCfWidg:= TCEProjectConfigurationWidget.create(nil);
fStExpWidg:= TCEStaticExplorerWidget.create(nil);
+ fFindWidg := TCESearchWidget.create(nil);
fWidgList.addWidget(@fMesgWidg);
fWidgList.addWidget(@fEditWidg);
fWidgList.addWidget(@fProjWidg);
fWidgList.addWidget(@fPrjCfWidg);
fWidgList.addWidget(@fStExpWidg);
+ fWidgList.addWidget(@fFindWidg);
for widg in fWidgList do widg.Show;
@@ -252,6 +255,7 @@ begin
fProjWidg.Free;
fPrjCfWidg.Free;
fStExpWidg.Free;
+ fFindWidg.Free;
fProject.Free;
//
inherited;
@@ -698,23 +702,28 @@ begin
{$IFDEF RELEASE}
dmdProc.ShowWindow := swoHIDE;
{$ENDIF}
- dmdproc.Options:= [poWaitOnExit, poStdErrToOutput, poUsePipes];
+ dmdproc.Options:= [poStdErrToOutput, poUsePipes];
dmdproc.Executable:= 'dmd';
dmdproc.Parameters.Add(fname + '.d');
try
dmdproc.Execute;
+ while dmdproc.Running do if dmdproc.ExitStatus <> 0 then break;
ProcessOutputToMsg(dmdproc);
finally
DeleteFile(fname + '.d');
end;
+ {$IFDEF MSWINDOWS}
+ if (dmdProc.ExitStatus = 0) or (dmdProc.ExitStatus = 259) then
+ {$ELSE}
if dmdProc.ExitStatus = 0 then
+ {$ENDIF}
begin
fMesgWidg.addCeInf( fEditWidg.editor[edIndex].fileName
+ ' successfully compiled' );
- runproc.Options:= [poWaitOnExit, poStderrToOutPut, poUsePipes];
+ runproc.Options:= [poStderrToOutPut, poUsePipes];
{$IFDEF MSWINDOWS}
runproc.Executable := fname + '.exe';
runproc.Parameters.Text := runArgs;
@@ -722,10 +731,8 @@ begin
runproc.Executable := fname;
{$ENDIF}
runproc.Execute;
- repeat
- ProcessOutputToMsg(runproc);
- until
- not runproc.Active;
+ while runproc.Running do if runproc.ExitStatus <> 0 then break;
+ ProcessOutputToMsg(runproc);
{$IFDEF MSWINDOWS}
DeleteFile(fname + '.exe');
DeleteFile(fname + '.obj');
@@ -749,12 +756,6 @@ procedure TCEMainForm.compileProject(const aProject: TCEProject);
var
dmdproc: TProcess;
olddir, prjpath: string;
-const
- // option -v causes a hang if poWaitOnExit is included
- procopts: array[boolean] of TProcessOptions = (
- [poWaitOnExit, poStdErrToOutput, poUsePipes],
- [poStdErrToOutput, poUsePipes]
- );
begin
if aProject.Sources.Count = 0 then
@@ -776,16 +777,20 @@ begin
{$IFDEF RELEASE}
dmdProc.ShowWindow := swoHIDE;
{$ENDIF}
- dmdproc.Options :=
- procopts[aProject.currentConfiguration.messagesOptions.verbose];
+ dmdproc.Options := [poStdErrToOutput, poUsePipes];
dmdproc.Executable := 'dmd';
aProject.getOpts(dmdproc.Parameters);
try
dmdproc.Execute;
+ while dmdproc.Running do if dmdproc.ExitStatus <> 0 then break;
ProcessOutputToMsg(dmdproc);
finally
+ {$IFDEF MSWINDOWS} // STILL_ACTIVE ambiguity
+ if (dmdProc.ExitStatus = 0) or (dmdProc.ExitStatus = 259) then
+ {$ELSE}
if dmdProc.ExitStatus = 0 then
+ {$ENDIF}
fMesgWidg.addCeInf( aProject.fileName
+ ' successfully compiled' )
else
@@ -833,6 +838,7 @@ begin
runproc.Executable := procname;
runproc.Parameters.Text := runArgs;
runproc.Execute;
+ while runproc.Running do if runproc.ExitStatus <> 0 then break;
finally
runproc.Free;
@@ -856,8 +862,8 @@ begin
if fEditWidg.editorIndex < 0 then exit;
//
runargs := '';
- if InputQuery('Execution arguments', 'enter switches and arguments',
- runargs) then compileAndRunFile(fEditWidg.editorIndex, runargs);
+ if InputQuery('Execution arguments', '', runargs) then
+ compileAndRunFile(fEditWidg.editorIndex, runargs);
end;
procedure TCEMainForm.actProjCompileExecute(Sender: TObject);
@@ -878,8 +884,8 @@ begin
compileProject(fProject);
//
runargs := '';
- if InputQuery('Execution arguments', 'enter switches and arguments',
- runargs) then runProject(fProject, runargs);
+ if InputQuery('Execution arguments', '', runargs) then
+ runProject(fProject, runargs);
end;
procedure TCEMainForm.actProjRunExecute(Sender: TObject);
@@ -892,8 +898,8 @@ var
runargs: string;
begin
runargs := '';
- if InputQuery('Execution arguments', 'enter switches and arguments',
- runargs) then runProject(fProject, runargs);
+ if InputQuery('Execution arguments', '', runargs) then
+ runProject(fProject, runargs);
end;
{$ENDREGION}
diff --git a/src/ce_search.lfm b/src/ce_search.lfm
new file mode 100644
index 00000000..6730f897
--- /dev/null
+++ b/src/ce_search.lfm
@@ -0,0 +1,305 @@
+inherited CESearchWidget: TCESearchWidget
+ Left = 1338
+ Height = 276
+ Top = 697
+ Width = 405
+ Caption = 'Search & replace'
+ ClientHeight = 276
+ ClientWidth = 405
+ inherited Back: TPanel
+ Height = 276
+ Width = 405
+ ClientHeight = 276
+ ClientWidth = 405
+ inherited Content: TPanel
+ Height = 276
+ Width = 405
+ ClientHeight = 276
+ ClientWidth = 405
+ object cbToFind: TComboBox[0]
+ Left = 4
+ Height = 23
+ Top = 4
+ Width = 397
+ Align = alTop
+ BorderSpacing.Around = 4
+ ItemHeight = 15
+ OnChange = cbToFindChange
+ TabOrder = 0
+ end
+ object cbReplaceWth: TComboBox[1]
+ Left = 4
+ Height = 23
+ Top = 31
+ Width = 397
+ Align = alTop
+ BorderSpacing.Around = 4
+ ItemHeight = 15
+ OnChange = cbReplaceWthChange
+ TabOrder = 1
+ end
+ object btnFind: TBitBtn[2]
+ Left = 4
+ Height = 24
+ Top = 192
+ Width = 397
+ Align = alBottom
+ BorderSpacing.Around = 4
+ Caption = 'btnFind'
+ Glyph.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF003E39
+ 34FF393430FF332F2BFF2C2925FF272421FF201D1BFF1716141A110F0EDB0B0A
+ 09FF070706FF040403FF000000FF000000FFFFFFFF00FFFFFF00FFFFFF004641
+ 3BFF857A70FFC3B8AEFF7C7268FF7F756BFF36322DFF1E1C190F282522D49589
+ 7DFFBAAEA2FF7C7268FF7F756BFF010101FFFFFFFF00FFFFFF00FFFFFF004D47
+ 41FF83786FFFCCC3BAFF786F65FF7B7167FF2F2B28F9272421011D1B18EE9589
+ 7DFFC2B8ADFF786F65FF7C7268FF060505FFFFFFFF00FFFFFF00FFFFFF00534C
+ 46FC83786FFFCCC3BAFF797066FF71685FFF37332ED5FFFFFF00252220D5857A
+ 70FFC2B8ADFF786F65FF7B7167FF0A0908FCFFFFFF00FFFFFF00FFFFFF005A52
+ 4CC39F9286FFCCC3BAFFC0B4AAFFA6988BFF3E3934A8FFFFFF002C2925A89084
+ 79FFC2B8ADFFC0B4AAFFA89B8EFF110F0EC3FFFFFF00FFFFFF00797066055C55
+ 4EF9423D38FF58514AFF3D3833FF332F2BFF23201DE5171614301E1C19B51A18
+ 16FF252220FF191715FF0F0E0DFF010101EE00000002FFFFFF009F9286059D91
+ 85FFB1A396FF7F756BFF7C7268FF776D64FF6C635BFF2E2A26FF564F48FF8076
+ 6CFF7C7268FF776D64FF70675EFF000000FE00000005FFFFFF00AB9D9004AFA1
+ 94E1BAAEA2FF82776DFF82776DFFAA917BFFBAA794FFB7A48EFAB09781FF9F8D
+ 7DFF836D5BFF716357FF95897DFF040403E000000003FFFFFF00B9ACA008877D
+ 72489B8E82FF9D9185FF867B71FF564F48FF504A44FF80766CFF6E665DFF826C
+ 58FFA6917DFF948474FF564F48FF0C0B0B7A07070601FFFFFF00FFFFFF00FFFF
+ FF00746B62FFA4978AFF95897DFF9F9286FF3E3934FFFFFFFF004C4640FF7E74
+ 6AFF857A70FF3E3934FF453F3AA72522200C15131102FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF008E8378E2C3B8AEFF655D55FFFFFFFF007C7268FFA89B
+ 8EFF9C8F83E4FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF009C8F83E2BCB0A4FF9D9185FFFFFFFF00AEA093FF9D91
+ 85FF655D55DAFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ TabOrder = 2
+ end
+ object btnReplace: TBitBtn[3]
+ Left = 4
+ Height = 24
+ Top = 220
+ Width = 397
+ Align = alBottom
+ BorderSpacing.Around = 4
+ Caption = 'btnReplace'
+ Glyph.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00DB772511DB742199D9701FFFD96E1CFFD86C
+ 1BCCD8691A77D8671A77D6651AEED6621AEED4621999D4601911FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00DD7B2A66E18F4CFFEBB183FFE3914EFFDA73
+ 23FFDA7428FFE08848FFE7A270FFE3935CFFDB7533FFD6621A44FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00DF823044E28D44FFECB588FFDC7A2CFFDB74
+ 2311DB721F22D9701EDDE6A471FFDC7A34FFD8671A44FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00DF8231CCE69959FFE49755FFDB7B
+ 2877FFFFFF00DB742177E18C4CFFE18B49FFD86C1B77FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E1873711DF8435BBE59856FFE595
+ 53FFDD7B2ACCDB7727AAE69D63FFE8A46DFFD9701ECCFFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00419149E539853FFF317A37FF7F7A32FF9579
+ 2EFCDF8230BBDF7E2CFFE39250FFEBB386FFDC7728FFDB721F11FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00419149F9BCB272FFE8A05EFFBD82
+ 37FEDF853511FFFFFF00DF7E2E99E69E61FFE1924EFFDB772566FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF0051A75A8A71B67AFFB6C590FFE69B55FFE8A4
+ 65FFE2893988FFFFFF00DF843588E69F61FFE59858FFDD7B2A77DB721F99D96E
+ 1CDDD86C1BDDD8691AFF919749F080C588FFB0DCB6FF75B87CFF8E9146FAE496
+ 4AFFE8A361FFE28B3CFFE69E5CFFE9A96FFFE49956FFDF823066DB772755E087
+ 42FFDB721F88FFFFFF0083AA59D988CB90FF83C68BFF51A75AA8499C52035991
+ 48E5E2924377E29040BBE28D3CBBE28B3AAAE1873966FFFFFF00DF7E2E11DE7E
+ 2FFFDB7727AAFFFFFF00DB721F1190A352FF85A251F958B16203FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00DF82
+ 31BBDF7E2EFFFFFFFF00FFFFFF00DB7423CCDE833AFFD96E1C44FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E189
+ 3977E59B59FFDF8231BBDF7E2E88E39250FFDD7F32FFDB742322FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E28E
+ 4033E5944CFFE18939BBDF8535AADF8231BBDF7E2E55FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00E29041FFE28E40DDFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E697
+ 4766E69547FFE69A4EFFE2904122FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ TabOrder = 3
+ end
+ object grpOpts: TGroupBox[4]
+ Left = 4
+ Height = 130
+ Top = 58
+ Width = 397
+ Align = alClient
+ BorderSpacing.Around = 4
+ Caption = 'Options'
+ ClientHeight = 112
+ ClientWidth = 393
+ TabOrder = 4
+ object chkWWord: TCheckBox
+ Left = 8
+ Height = 19
+ Top = 0
+ Width = 82
+ Caption = 'whole word'
+ TabOrder = 0
+ end
+ object chkBack: TCheckBox
+ Left = 8
+ Height = 19
+ Top = 24
+ Width = 71
+ Caption = 'backward'
+ TabOrder = 1
+ end
+ object chkFromCur: TCheckBox
+ Left = 8
+ Height = 19
+ Top = 48
+ Width = 82
+ Caption = 'from cursor'
+ Checked = True
+ State = cbChecked
+ TabOrder = 2
+ end
+ object chkCaseSens: TCheckBox
+ Left = 128
+ Height = 19
+ Top = 0
+ Width = 91
+ Caption = 'case sensitive'
+ TabOrder = 3
+ end
+ object chkPrompt: TCheckBox
+ Left = 128
+ Height = 19
+ Top = 24
+ Width = 60
+ Caption = 'Prompt'
+ TabOrder = 4
+ end
+ end
+ object btnReplaceAll: TBitBtn[5]
+ Left = 4
+ Height = 24
+ Top = 248
+ Width = 397
+ Align = alBottom
+ BorderSpacing.Around = 4
+ Caption = 'btnReplaceAll'
+ Glyph.Data = {
+ 36040000424D3604000000000000360000002800000010000000100000000100
+ 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00DB772511DB742199D9701FFFD96E1CFFD86C
+ 1BCCD8691A77D8671A77D6651AEED6621AEED4621999D4601911FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00DD7B2A66E18F4CFFEBB183FFE3914EFFDA73
+ 23FFDA7428FFE08848FFE7A270FFE3935CFFDB7533FFD6621A44FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00DF823044E28D44FFECB588FFDC7A2CFFDB74
+ 2311DB721F22D9701EDDE6A471FFDC7A34FFD8671A44FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00DF8231CCE69959FFE49755FFDB7B
+ 2877FFFFFF00DB742177E18C4CFFE18B49FFD86C1B77FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E1873711DF8435BBE59856FFE595
+ 53FFDD7B2ACCDB7727AAE69D63FFE8A46DFFD9701ECCFFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00419149E539853FFF317A37FF7F7A32FF9579
+ 2EFCDF8230BBDF7E2CFFE39250FFEBB386FFDC7728FFDB721F11FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00419149F9BCB272FFE8A05EFFBD82
+ 37FEDF853511FFFFFF00DF7E2E99E69E61FFE1924EFFDB772566FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF0051A75A8A71B67AFFB6C590FFE69B55FFE8A4
+ 65FFE2893988FFFFFF00DF843588E69F61FFE59858FFDD7B2A77DB721F99D96E
+ 1CDDD86C1BDDD8691AFF919749F080C588FFB0DCB6FF75B87CFF8E9146FAE496
+ 4AFFE8A361FFE28B3CFFE69E5CFFE9A96FFFE49956FFDF823066DB772755E087
+ 42FFDB721F88FFFFFF0083AA59D988CB90FF83C68BFF51A75AA8499C52035991
+ 48E5E2924377E29040BBE28D3CBBE28B3AAAE1873966FFFFFF00DF7E2E11DE7E
+ 2FFFDB7727AAFFFFFF00DB721F1190A352FF85A251F958B16203FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00DF82
+ 31BBDF7E2EFFFFFFFF00FFFFFF00DB7423CCDE833AFFD96E1C44FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E189
+ 3977E59B59FFDF8231BBDF7E2E88E39250FFDD7F32FFDB742322FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E28E
+ 4033E5944CFFE18939BBDF8535AADF8231BBDF7E2E55FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00E29041FFE28E40DDFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E697
+ 4766E69547FFE69A4EFFE2904122FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
+ }
+ TabOrder = 5
+ end
+ end
+ end
+ object imgList: TImageList[2]
+ left = 32
+ Bitmap = {
+ 4C690200000010000000100000007B7977007B7977007B7977FF73716FFF6D6B
+ 69FF696665FF625F5EFF615E5D007E7C7A007B7977FF73716FFF6D6B69FF6966
+ 65FF63605FFF64616000646160007B7977007B7977007A7976FF908D8CFF908E
+ 8CFF656461FF615E5DFF615E5D007D7B7900797775FF8E8B8AFF918F8DFF6866
+ 64FF63605FFF64616000646160007B7977007B79770000000033787574FFCBCA
+ C7FF9B9A99FF625E5DFF625F5E007D7A7900787574FFCAC8C6FF989796FF605D
+ 5CFF0000003364616000646160007B797700797875AE716E6DFF696665FF6460
+ 5FFF625E5DFF545251AA7B7A7700656361006A6967AA6F6C6BFF696665FF6764
+ 63FF656261FF63605FAE646160007C797800787574FFBDBBB9FFCECCCBFFA5A3
+ A2FF7E7C7BFF5E5B5AFF7B7977FF646260FF797675FFBCBBB8FFCECCCBFFA6A4
+ A3FF807E7DFF605D5CFF63605F007B787700777473FFB9B7B5FFC9C7C6FFA2A0
+ 9FFF7D7B7AFF5C5858FF777472FF615F5DFF777473FFB9B8B5FFC9C7C6FFA2A0
+ 9FFF7E7C7BFF605D5CFF63605F007B797700777473FFBCBAB8FFCDCBCAFFA5A3
+ A2FF7E7C7BFF595655FFD6D5D3FF8C8C89FF767372FFBCBAB7FFCCCAC9FFA4A2
+ A1FF7E7C7BFF5F5C5BFF625F5E007A7876FF6F6D6BFF666261FF605D5CFF5E5C
+ 5AFF5E5A5AFF4946469BD3D2D0FF8A8987FF62615F9B6C6A68FF646160FF625F
+ 5EFF615F5DFF615E5DFF615E5DA8777472FFDEDDDDFFEBEBE9FFDBDAD9FFCAC9
+ C8FFBBBAB9FF575453FFD6D5D3FF8C8B89FF757371FFDEDDDCFFEBEBE9FFDBDA
+ D9FFCAC9C8FFBCBCBBFF5E5B5AFF767472FFB3B0AEFFCAC9C7FFB0ADADFF9190
+ 8EFF757472FF5B5857FF767472FF615F5DFF767472FFB3B1AFFFCAC9C7FFB0AD
+ ADFF91908EFF757573FF5F5C5BFF767472FFB3B1AFFFCAC9C7FFB1AEAEFF9392
+ 90FF777674FF5E5A59FF7A7876FF646260FF777573FFB3B1AFFFCAC9C7FFB1AE
+ AEFF939290FF777674FF605D5CFF767472FFB3B1AFFFCAC9C7FFB0AEADFF9190
+ 8EFF757472FF5E5A59FF0000003300000033777573FFB3B1AFFFCAC9C7FFB0AE
+ ADFF91908EFF757572FF5F5C5BFF777573FFCFCFCFFFD9D7D6FFD0CFCEFFC8C8
+ C7FFC3C1C1FF5E5A59FF5F5C5B007E7C7A00777573FFD0CFCFFFD9D7D6FFD0CF
+ CEFFC8C8C7FFC3C1C1FF5E5B5AFF7A7876FF817E7DFF9C9996FF898583FF716F
+ 6CFF595756FF605D5CFF605D5C007F7D7B007A7876FF817E7DFF9C9996FF8985
+ 83FF716F6CFF595756FF615E5DFF716F6DC0767472FF706D6CFF6D6A69FF6967
+ 65FF666362FF5A5756C0605D5C007E7C7A00716F6DC0767472FF706D6CFF6D6A
+ 69FF696765FF666362FF5A5756C0000000230000003300000033000000330000
+ 0033000000330000002300000000000000000000002300000033000000330000
+ 0033000000330000003300000023FFFFFF00E6974766E69547FFE69A4EFFE290
+ 4122FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E29041FFE28E40DDFFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E28E4033E5944CFFE18939BBDF85
+ 35AADF8231BBDF7E2E55FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00E1893977E59B59FFDF8231BBDF7E
+ 2E88E39250FFDD7F32FFDB742322FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00DF8231BBDF7E2EFFFFFFFF00FFFF
+ FF00DB7423CCDE833AFFD96E1C44FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00DF7E2E11DE7E2FFFDB7727AAFFFFFF00DB72
+ 1F1190A352FF85A251F958B16203FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00FFFFFF00FFFFFF00DB772755E08742FFDB721F88FFFFFF0083AA
+ 59D988CB90FF83C68BFF51A75AA8499C5203599148E5E2924377E29040BBE28D
+ 3CBBE28B3AAAE1873966FFFFFF00DB721F99D96E1CDDD86C1BDDD8691AFF9197
+ 49F080C588FFB0DCB6FF75B87CFF8E9146FAE4964AFFE8A361FFE28B3CFFE69E
+ 5CFFE9A96FFFE49956FFDF823066FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF0051A75A8A71B67AFFB6C590FFE69B55FFE8A465FFE2893988FFFFFF00DF84
+ 3588E69F61FFE59858FFDD7B2A77FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00419149F9BCB272FFE8A05EFFBD8237FEDF853511FFFFFF00DF7E
+ 2E99E69E61FFE1924EFFDB772566FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00419149E539853FFF317A37FF7F7A32FF95792EFCDF8230BBDF7E2CFFE392
+ 50FFEBB386FFDC7728FFDB721F11FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00E1873711DF8435BBE59856FFE59553FFDD7B2ACCDB7727AAE69D
+ 63FFE8A46DFFD9701ECCFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00FFFFFF00DF8231CCE69959FFE49755FFDB7B2877FFFFFF00DB742177E18C
+ 4CFFE18B49FFD86C1B77FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00DF823044E28D44FFECB588FFDC7A2CFFDB742311DB721F22D9701EDDE6A4
+ 71FFDC7A34FFD8671A44FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00DD7B2A66E18F4CFFEBB183FFE3914EFFDA7323FFDA7428FFE08848FFE7A2
+ 70FFE3935CFFDB7533FFD6621A44FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
+ FF00DB772511DB742199D9701FFFD96E1CFFD86C1BCCD8691A77D8671A77D665
+ 1AEED6621AEED4621999D4601911
+ }
+ end
+end
diff --git a/src/ce_search.pas b/src/ce_search.pas
new file mode 100644
index 00000000..3ffa2ef7
--- /dev/null
+++ b/src/ce_search.pas
@@ -0,0 +1,186 @@
+unit ce_search;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
+ Menus, StdCtrls, actnList, Buttons, SynEdit, SynEditSearch, SynEditTypes, ce_common,
+ ce_widget, ce_synmemo;
+
+type
+
+ { TCESearchWidget }
+
+ TCESearchWidget = class(TCEWidget)
+ btnFind: TBitBtn;
+ btnReplace: TBitBtn;
+ btnReplaceAll: TBitBtn;
+ cbToFind: TComboBox;
+ cbReplaceWth: TComboBox;
+ chkPrompt: TCheckBox;
+ chkWWord: TCheckBox;
+ chkBack: TCheckBox;
+ chkFromCur: TCheckBox;
+ chkCaseSens: TCheckBox;
+ grpOpts: TGroupBox;
+ imgList: TImageList;
+ procedure cbReplaceWthChange(Sender: TObject);
+ procedure cbToFindChange(Sender: TObject);
+ private
+ fEditor: TCESynMemo;
+ fToFind: string;
+ fReplaceWth: string;
+ fActFindNext, fActReplaceNext: TAction;
+ fActReplaceAll: TAction;
+ fSearchMru, fReplaceMru: TMruList;
+ function getOptions: TSynSearchOptions;
+ procedure actFindNextExecute(sender: TObject);
+ procedure actReplaceAllExecute(sender: TObject);
+ procedure actReplaceNextExecute(sender: TObject);
+ procedure replaceEvent(Sender: TObject; const ASearch, AReplace:
+ string; Line, Column: integer; var ReplaceAction: TSynReplaceAction);
+ protected
+ procedure UpdateByEvent; override;
+ public
+ constructor Create(aOwner: TComponent); override;
+ destructor Destroy; override;
+ //
+ procedure docFocused(const aDoc: TCESynMemo); override;
+ procedure docClose(const aDoc: TCESynMemo); override;
+ end;
+
+implementation
+{$R *.lfm}
+
+constructor TCESearchWidget.Create(aOwner: TComponent);
+begin
+ inherited;
+ fID := 'ID_FIND';
+ //
+ fSearchMru := TMruList.Create;
+ fReplaceMru:= TMruList.Create;
+ //
+ fActFindNext := TAction.Create(self);
+ fActFindNext.Caption := 'Find';
+ fActFindNext.OnExecute := @actFindNextExecute;
+ btnFind.Action := fActFindNext;
+ fActReplaceNext := TAction.Create(self);
+ fActReplaceNext.Caption := 'Replace';
+ fActReplaceNext.OnExecute := @actReplaceNextExecute;
+ btnReplace.Action := fActReplaceNext;
+ fActReplaceAll := TAction.Create(self);
+ fActReplaceAll.Caption := 'Replace all';
+ fActReplaceAll.OnExecute := @actReplaceAllExecute;
+ btnReplaceAll.Action := fActReplaceAll;
+end;
+
+destructor TCESearchWidget.Destroy;
+begin
+ fSearchMru.Free;
+ fReplaceMru.Free;
+ inherited;
+end;
+
+procedure TCESearchWidget.docFocused(const aDoc: TCESynMemo);
+begin
+ fEditor := aDoc;
+ UpdateByEvent;
+end;
+
+procedure TCESearchWidget.docClose(const aDoc: TCESynMemo);
+begin
+ if fEditor = aDoc then fEditor := nil;
+ UpdateByEvent;
+end;
+
+procedure TCESearchWidget.cbToFindChange(Sender: TObject);
+begin
+ if Updating then exit;
+ fToFind := cbToFind.Text;
+end;
+
+procedure TCESearchWidget.cbReplaceWthChange(Sender: TObject);
+begin
+ if Updating then exit;
+ fReplaceWth := cbReplaceWth.Text;
+end;
+
+function TCESearchWidget.getOptions: TSynSearchOptions;
+begin
+ result := [];
+ if chkWWord.Checked then result += [ssoWholeWord];
+ if chkBack.Checked then result += [ssoBackwards];
+ if chkCaseSens.Checked then result += [ssoMatchCase];
+ if chkPrompt.Checked then result += [ssoPrompt];
+end;
+
+procedure TCESearchWidget.actFindNextExecute(sender: TObject);
+begin
+ if fEditor = nil then exit;
+ //
+ fSearchMru.Insert(0,fToFind);
+ if not chkFromCur.Checked then if chkBack.Checked then
+ fEditor.CaretXY := Point(high(Integer), high(Integer)) else
+ fEditor.CaretXY := Point(0,0);
+ fEditor.SearchReplace(fToFind, '', getOptions);
+ UpdateByEvent;
+end;
+
+procedure TCESearchWidget.actReplaceNextExecute(sender: TObject);
+begin
+ if fEditor = nil then exit;
+ //
+ fSearchMru.Insert(0, fToFind);
+ fReplaceMru.Insert(0, fReplaceWth);
+ if chkPrompt.Checked then
+ fEditor.OnReplaceText := @replaceEvent;
+ if not chkFromCur.Checked then if chkBack.Checked then
+ fEditor.CaretXY := Point(high(Integer), high(Integer)) else
+ fEditor.CaretXY := Point(0,0);
+ fEditor.SearchReplace(fToFind, fReplaceWth, getOptions + [ssoReplace]);
+ fEditor.OnReplaceText := nil;
+ UpdateByEvent;
+end;
+
+procedure TCESearchWidget.actReplaceAllExecute(sender: TObject);
+var
+ opts: TSynSearchOptions;
+begin
+ if fEditor = nil then exit;
+ opts := getOptions + [ssoReplace];
+ opts -= [ssoBackwards];
+ //
+ fSearchMru.Insert(0, fToFind);
+ fReplaceMru.Insert(0, fReplaceWth);
+ if chkPrompt.Checked then fEditor.OnReplaceText := @replaceEvent;
+ fEditor.CaretXY := Point(0,0);
+ while(true) do
+ begin
+ if fEditor.SearchReplace(fToFind, fReplaceWth, opts) = 0
+ then break;
+ end;
+ fEditor.OnReplaceText := nil;
+ UpdateByEvent;
+end;
+
+procedure TCESearchWidget.replaceEvent(Sender: TObject; const ASearch, AReplace:
+ string; Line, Column: integer; var ReplaceAction: TSynReplaceAction);
+begin
+ ReplaceAction := raSkip;
+ if dlgOkCancel('Replace this match ?') = mrOK then
+ ReplaceAction := raReplace;
+end;
+
+procedure TCESearchWidget.UpdateByEvent;
+begin
+ fActFindNext.Enabled := fEditor <> nil;
+ fActReplaceNext.Enabled := fEditor <> nil;
+ //
+ cbToFind.Items.Assign(fSearchMru);
+ cbReplaceWth.Items.Assign(fReplaceMru);
+end;
+
+end.
+
diff --git a/src/ce_staticexplorer.lfm b/src/ce_staticexplorer.lfm
index 51492770..6dd5d9c2 100644
--- a/src/ce_staticexplorer.lfm
+++ b/src/ce_staticexplorer.lfm
@@ -34,6 +34,7 @@ inherited CEStaticExplorerWidget: TCEStaticExplorerWidget
SelectionColor = clActiveBorder
TabOrder = 0
OnDeletion = TreeDeletion
+ OnKeyPress = TreeKeyPress
Options = [tvoAutoItemHeight, tvoKeepCollapsedNodes, tvoReadOnly, tvoRowSelect, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
Items.Data = {
F9FFFFFF020009000000000000000000000000000000FFFFFFFF000000000000
diff --git a/src/ce_staticexplorer.pas b/src/ce_staticexplorer.pas
index cabb1d30..b59718ee 100644
--- a/src/ce_staticexplorer.pas
+++ b/src/ce_staticexplorer.pas
@@ -18,6 +18,7 @@ type
Tree: TTreeView;
TreeFilterEdit1: TTreeFilterEdit;
procedure TreeDeletion(Sender: TObject; Node: TTreeNode);
+ procedure TreeKeyPress(Sender: TObject; var Key: char);
private
fActRefresh: TAction;
fActAutoRefresh: TAction;
@@ -168,6 +169,11 @@ begin
FreeMem(node.Data)
end;
+procedure TCEStaticExplorerWidget.TreeKeyPress(Sender: TObject; var Key: char);
+begin
+ if Key = #13 then TreeDblClick(nil);
+end;
+
procedure TCEStaticExplorerWidget.TreeDblClick(Sender: TObject);
var
line: Int64;
@@ -178,7 +184,7 @@ begin
//
line := PInt64(Tree.Selected.Data)^;
fDoc.CaretY := line;
- fDoc.SelectLine();
+ fDoc.SelectLine;
end;
procedure TCEStaticExplorerWidget.Rescan;