diff --git a/components/synedit/synedit.pp b/components/synedit/synedit.pp index 72c29e8f68..af0f646a74 100644 --- a/components/synedit/synedit.pp +++ b/components/synedit/synedit.pp @@ -128,7 +128,8 @@ const type TSynSearchOption = (ssoMatchCase, ssoWholeWord, ssoBackwards, - ssoEntireScope, ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoPrompt); + ssoEntireScope, ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoPrompt + {$IFDEF SYN_LAZARUS}, ssoRegExpr, ssoRegExprMultiLine{$ENDIF}); TSynSearchOptions = set of TSynSearchOption; TSynReplaceAction = (raCancel, raSkip, raReplace, raReplaceAll); @@ -5777,8 +5778,12 @@ begin fTSearch.Sensitive := ssoMatchCase in AOptions; fTSearch.Whole := ssoWholeWord in AOptions; fTSearch.Pattern := ASearch; + fTSearch.RegularExpressions := ssoRegExpr in AOptions; + fTSearch.RegExprSingleLine := not (ssoRegExprMultiLine in AOptions); // search while the current search position is inside of the search range + {$IFNDEF SYN_LAZARUS} nSearchLen := Length(ASearch); + {$ENDIF} nReplaceLen := Length(AReplace); if bReplaceAll then IncPaintLock; try @@ -5788,6 +5793,9 @@ begin // Operate on all results in this line. while nInLine > 0 do begin nFound := fTSearch.Results[n]; + {$IFDEF SYN_LAZARUS} + nSearchLen := fTSearch.ResultLengths[n]; + {$ENDIF} if bBackward then Dec(n) else Inc(n); Dec(nInLine); // Is the search result entirely in the search range? diff --git a/components/synedit/syneditsearch.pp b/components/synedit/syneditsearch.pp index aefbd27026..8d6425677e 100644 --- a/components/synedit/syneditsearch.pp +++ b/components/synedit/syneditsearch.pp @@ -42,7 +42,8 @@ unit SynEditSearch; interface uses - Classes; + Classes + {$IFDEF SYN_LAZARUS}, RegExpr{$ENDIF}; procedure MakeCompTable(Sensitive: boolean); procedure MakeDelimiterTable; @@ -63,6 +64,16 @@ type fWhole: Boolean; fResults: TList; fShiftInitialized: boolean; + {$IFDEF SYN_LAZARUS} + FoundLen: integer; + RegExprEngine : TRegExprEngine; + fRegExpr: Boolean; + fRegExprFlags: TRegExprFlags; + fResultLens: TList; + fRegExprSingleLine: boolean; + function GetResultLen(Index: integer): integer; + procedure SetRegExpr(const NewValue: boolean); + {$ENDIF} function GetFinished: Boolean; function GetResult(Index: integer): integer; function GetResultCount: integer; @@ -85,6 +96,12 @@ type property ResultCount: integer read GetResultCount; property Sensitive: Boolean read fSensitive write SetSensitive; property Whole: Boolean read fWhole write fWhole; + {$IFDEF SYN_LAZARUS} + property RegularExpressions: Boolean read fRegExpr write SetRegExpr; + property ResultLengths[Index: integer]: integer read GetResultLen; + property RegExprSingleLine: Boolean + read fRegExprSingleLine write fRegExprSingleLine; + {$ENDIF} end; implementation @@ -102,12 +119,6 @@ var CompTable: array[#0..#255] of Byte; DelimTable: array[#0..#255] of boolean; -constructor TSynEditSearch.Create; -begin - inherited Create; - fResults := TList.Create; -end; - procedure MakeCompTable(Sensitive: Boolean); var I: Char; @@ -134,6 +145,18 @@ begin for c := #0 to #255 do DelimTable[c] := not IsCharAlphaNumeric(c); end; +constructor TSynEditSearch.Create; +begin + inherited Create; + fResults := TList.Create; + {$IFDEF SYN_LAZARUS} + fRegExpr:=false; + fResultLens := TList.Create; + fRegExprSingleLine:=true; + FoundLen:=0; + {$ENDIF} +end; + { TSynEditSearch } function TSynEditSearch.GetFinished: Boolean; @@ -200,43 +223,64 @@ var J: PChar; begin Result := 0; - inc(Run, PatLen); - while Run < TheEnd do - begin - if CompTable[Pat[Patlen]] <> CompTable[Run^] then - inc(Run, Shift[CompTable[(Run + 1)^]]) - else + {$IFDEF SYN_LAZARUS} + if not fRegExpr then begin + {$ENDIF} + inc(Run, PatLen); + FoundLen:=PatLen; + while Run < TheEnd do begin - J := Run - PatLen + 1; - I := 1; - while CompTable[Pat[I]] = CompTable[J^] do + if CompTable[Pat[Patlen]] <> CompTable[Run^] then + inc(Run, Shift[CompTable[(Run + 1)^]]) + else begin - if I = PatLen then + J := Run - PatLen + 1; + I := 1; + while CompTable[Pat[I]] = CompTable[J^] do begin - Case fWhole of - True: if not TestWholeWord then break; + if I = PatLen then + begin + Case fWhole of + True: if not TestWholeWord then break; + end; + inc(fCount); + Result := Run - Origin - Patlen + 2; + exit; end; - inc(fCount); - Result := Run - Origin - Patlen + 2; - exit; + inc(I); + inc(J); end; - inc(I); - inc(J); - end; {begin} //mh 2000-08-29 -// inc(Run, Look_At + Shift[CompTable[(Run + Look_at)^]] - 1); - Inc(Run, Look_At); - if Run >= TheEnd then - break; - Inc(Run, Shift[CompTable[Run^]] - 1); +// inc(Run, Look_At + Shift[CompTable[(Run + Look_at)^]] - 1); + Inc(Run, Look_At); + if Run >= TheEnd then + break; + Inc(Run, Shift[CompTable[Run^]] - 1); {end} //mh 2000-08-29 + end; end; + {$IFDEF SYN_LAZARUS} + end else begin + // regular expressions + inc(Run); + if not RegExprPos(RegExprEngine,Run,Result,FoundLen) then begin + Run:=TheEnd; + Result:=0; + end else begin + inc(Run,Result); + Result:=Run-Origin+1; + end; + {$ENDIF} end; end; destructor TSynEditSearch.Destroy; begin fResults.Free; + {$IFDEF SYN_LAZARUS} + DestroyRegExprEngine(RegExprEngine); + fResultLens.Free; + {$ENDIF} inherited Destroy; end; @@ -252,10 +296,15 @@ end; procedure TSynEditSearch.SetSensitive(const Value: Boolean); begin if fSensitive <> Value then begin -writeln('A'); fSensitive := Value; MakeCompTable(Value); fShiftInitialized := FALSE; + {$IFDEF SYN_LAZARUS} + if fSensitive then + Exclude(fRegExprFlags,REF_CaseInsensitive) + else + Include(fRegExprFlags,REF_CaseInsensitive); + {$ENDIF} end; end; @@ -267,10 +316,16 @@ begin InitShiftTable; // never shrink Capacity fResults.Count := 0; + {$IFDEF SYN_LAZARUS} + if fRegExpr then fResultLens.Count := 0; + {$ENDIF} Found := FindFirst(NewText); while Found > 0 do begin fResults.Add(pointer(Found)); + {$IFDEF SYN_LAZARUS} + if fRegExpr then fResultLens.Add(pointer(FoundLen)); + {$ENDIF} Found := Next; end; Result := fResults.Count; @@ -280,6 +335,24 @@ function TSynEditSearch.FindFirst(const NewText: string): Integer; begin Result := 0; fTextLen := Length(NewText); + {$IFDEF SYN_LAZARUS} + if fRegExpr then begin + DestroyRegExprEngine(RegExprEngine); + if fSensitive then + Exclude(fRegExprFlags,REF_CaseInsensitive) + else + Include(fRegExprFlags,REF_CaseInsensitive); + if fRegExprSingleLine then begin + Include(fRegExprFlags,REF_SingleLine); + Exclude(fRegExprFlags,REF_MultiLine); + end else begin + Exclude(fRegExprFlags,REF_SingleLine); + Include(fRegExprFlags,REF_MultiLine); + end; + RegExprEngine:=GenerateRegExprEngine(PChar(Pat+#0),fRegExprFlags); + PatLen:=length(Pat); + end; + {$ENDIF} if fTextLen >= PatLen then begin Origin := PChar(NewText); @@ -289,9 +362,27 @@ begin end; end; +{$IFDEF SYN_LAZARUS} +function TSynEditSearch.GetResultLen(Index: integer): integer; +begin + if (Index>=0) and (Index