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;