diff --git a/components/synedit/synedit.pp b/components/synedit/synedit.pp index caa0307020..1f10b135ee 100644 --- a/components/synedit/synedit.pp +++ b/components/synedit/synedit.pp @@ -59,6 +59,7 @@ interface { $DEFINE VerboseKeys} { $DEFINE VerboseSynEditInvalidate} +{ $DEFINE SYNDEBUGPRINT} uses {$IFDEF USE_UTF8BIDI_LCL} @@ -213,7 +214,7 @@ type eoScrollPastEof, // Allows the cursor to go past the end of file marker eoScrollPastEol, // Allows the cursor to go past the last character into the white space at the end of a line eoShowScrollHint, // Shows a hint of the visible line numbers when scrolling vertically - eoShowSpecialChars, //TODO Shows the special Characters + eoShowSpecialChars, // Shows the special Characters eoSmartTabDelete, //TODO similar to Smart Tabs, but when you delete characters eoSmartTabs, // When tabbing, the cursor will go to the next non-white space character of the previous line //eoSpecialLineDefaultFg, //TODO disables the foreground text color override when using the OnSpecialLineColor event @@ -1516,14 +1517,12 @@ begin FCaret.Lines := FTheLinesView; FInternalCaret.Lines := FTheLinesView; - TSynEditStringList(fLines).AddChangeHandler(senrLineCount, - {$IFDEF FPC}@{$ENDIF}LineCountChanged); - TSynEditStringList(fLines).AddChangeHandler(senrLineChange, - {$IFDEF FPC}@{$ENDIF}LineTextChanged); with TSynEditStringList(fLines) do begin - OnChange := {$IFDEF FPC}@{$ENDIF}LinesChanged; - OnChanging := {$IFDEF FPC}@{$ENDIF}LinesChanging; - OnCleared := {$IFDEF FPC}@{$ENDIF}ListCleared; + AddChangeHandler(senrLineCount, {$IFDEF FPC}@{$ENDIF}LineCountChanged); + AddChangeHandler(senrLineChange, {$IFDEF FPC}@{$ENDIF}LineTextChanged); + AddNotifyHandler(senrBeginUpdate, {$IFDEF FPC}@{$ENDIF}LinesChanging); + AddNotifyHandler(senrEndUpdate, {$IFDEF FPC}@{$ENDIF}LinesChanged); + AddNotifyHandler(senrCleared, {$IFDEF FPC}@{$ENDIF}ListCleared); end; fFontDummy := TFont.Create; @@ -2266,7 +2265,7 @@ begin // so we we fire the OnKeyPress here if (ord(key[1])< %11000000) and (key[1]<>#0) and Assigned(OnKeyPress) then OnKeyPress(Self, Key[1]); - {$IFDEF VerboseKeyboard} + {$IFDEF VerboseKeys} DebugLn('TCustomSynEdit.UTF8KeyPress ',DbgSName(Self),' Key="',DbgStr(Key),'" UseUTF8=',dbgs(UseUTF8)); {$ENDIF} CommandProcessor(ecChar, Key, nil); @@ -2287,7 +2286,7 @@ begin // don't fire the event if key is to be ignored if not (sfIgnoreNextChar in fStateFlags) then begin Include(FStateFlags, sfHideCursor); - {$IFDEF VerboseKeyboard} + {$IFDEF VerboseKeys} DebugLn('TCustomSynEdit.KeyPress ',DbgSName(Self),' Key="',DbgStr(Key),'" UseUTF8=',dbgs(UseUTF8)); {$ENDIF} if Assigned(OnKeyPress) then OnKeyPress(Self, Key); @@ -3483,6 +3482,16 @@ var end; end; + {$IFDEF SYNDEBUGPRINT} + procedure DebugPrint(Txt: String; MinCol: Integer = 0); + begin + if CurPhysPos < MinCol then Txt := StringOfChar(' ', MinCol - CurPhysPos) + txt; + Setlength(CharWidths, length(CharWidths) + length(Txt)); + FillChar(CharWidths[length(CharWidths)-length(Txt)], length(Txt), #1); + DrawHiLightMarkupToken(nil, PChar(Pointer(Txt)), Length(Txt)); + end; + {$ENDIF} + procedure PaintLines; var sLine: string; // the current line diff --git a/components/synedit/syneditmiscclasses.pp b/components/synedit/syneditmiscclasses.pp index 0cc8701c0c..7a650fea21 100644 --- a/components/synedit/syneditmiscclasses.pp +++ b/components/synedit/syneditmiscclasses.pp @@ -339,6 +339,21 @@ type property Size: LongInt read GetSize; end; + { TSynMethodList } + + TSynMethodList = Class(TMethodList) + private + function IndexToObjectIndex(const AnObject: TObject; AnIndex: Integer): integer; + function GetObjectItems(AnObject: TObject; Index: integer): TMethod; + procedure SetObjectItems(AnObject: TObject; Index: integer; const AValue: TMethod); + public + function CountByObject(const AnObject: TObject): integer; + procedure DeleteByObject(const AnObject: TObject; Index: integer); + public + property ItemsByObject[AnObject: TObject; Index: integer]: TMethod + read GetObjectItems write SetObjectItems; default; + end; + const synClipTagText = TSynClipboardStreamTag(1); synClipTagExtText = TSynClipboardStreamTag(2); @@ -1086,5 +1101,53 @@ begin Result := aX; end; +{ TSynMethodList } + +function TSynMethodList.IndexToObjectIndex(const AnObject: TObject; AnIndex: Integer): integer; +var + i, c: Integer; +begin + Result := -1; + if Self = nil then exit; + i := 0; + c := Count; + while i < c do begin + if TObject(Items[AnIndex].Data)=AnObject then begin + if AnIndex = 0 then exit(i); + dec(AnIndex); + end; + inc(i); + end; +end; + +function TSynMethodList.GetObjectItems(AnObject: TObject; Index: integer): TMethod; +begin + Result := Items[IndexToObjectIndex(AnObject, Index)]; +end; + +procedure TSynMethodList.SetObjectItems(AnObject: TObject; Index: integer; + const AValue: TMethod); +begin + Items[IndexToObjectIndex(AnObject, Index)] := AValue; +end; + +function TSynMethodList.CountByObject(const AnObject: TObject): integer; +var + i: Integer; +begin + Result := 0; + if Self=nil then exit; + i := Count-1; + while i>=0 do begin + if TObject(Items[i].Data)=AnObject then inc(Result); + dec(i); + end; +end; + +procedure TSynMethodList.DeleteByObject(const AnObject: TObject; Index: integer); +begin + Delete(IndexToObjectIndex(AnObject, Index)); +end; + end. diff --git a/components/synedit/synedittextbase.pas b/components/synedit/synedittextbase.pas index 5eed95e9f0..7af05d8d00 100644 --- a/components/synedit/synedittextbase.pas +++ b/components/synedit/synedittextbase.pas @@ -33,7 +33,9 @@ type TStringListLineCountEvent = procedure(Sender: TSynEditStrings; Index, Count: Integer) of object; - TSynEditNotifyReason = (senrLineCount, senrLineChange, senrEditAction); + TSynEditNotifyReason = (senrLineCount, senrLineChange, senrEditAction, + senrTextEdit, senrBeginUpdate, senrEndUpdate, + senrCleared); TStringListLineEditEvent = procedure(Sender: TSynEditStrings; LinePos, BytePos, Count, LineBrkCnt: Integer; @@ -105,12 +107,23 @@ type procedure RegisterAttribute(const Index: TClass; const Size: Word); virtual; abstract; property Attribute[Owner: TClass; Index: Integer]: Pointer read GetAttribute write SetAttribute; + + procedure AddGenericHandler(AReason: TSynEditNotifyReason; + AHandler: TMethod); virtual; abstract; procedure AddChangeHandler(AReason: TSynEditNotifyReason; - AHandler: TStringListLineCountEvent); virtual; abstract; + AHandler: TStringListLineCountEvent); + procedure AddNotifyHandler(AReason: TSynEditNotifyReason; + AHandler: TNotifyEvent); + + procedure RemoveGenericHandler(AReason: TSynEditNotifyReason; + AHandler: TMethod); virtual; abstract; procedure RemoveChangeHandler(AReason: TSynEditNotifyReason; - AHandler: TStringListLineCountEvent); virtual; abstract; - procedure AddEditHandler(AHandler: TStringListLineEditEvent); virtual; abstract; - procedure RemoveEditHandler(AHandler: TStringListLineEditEvent); virtual; abstract; + AHandler: TStringListLineCountEvent); + procedure RemoveNotifyHandler(AReason: TSynEditNotifyReason; + AHandler: TNotifyEvent); + + procedure AddEditHandler(AHandler: TStringListLineEditEvent); + procedure RemoveEditHandler(AHandler: TStringListLineEditEvent); public function GetPhysicalCharWidths(Index: Integer): TPhysicalCharWidths; function GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths; virtual; abstract; @@ -196,12 +209,10 @@ type // Size: 0 = Bit (TODO); 1..8 Size In Byte "SizeOf()" procedure RegisterAttribute(const Index: TClass; const Size: Word); override; - procedure AddChangeHandler(AReason: TSynEditNotifyReason; - AHandler: TStringListLineCountEvent); override; - procedure RemoveChangeHandler(AReason: TSynEditNotifyReason; - AHandler: TStringListLineCountEvent); override; - procedure AddEditHandler(AHandler: TStringListLineEditEvent); override; - procedure RemoveEditHandler(AHandler: TStringListLineEditEvent); override; + procedure AddGenericHandler(AReason: TSynEditNotifyReason; + AHandler: TMethod); override; + procedure RemoveGenericHandler(AReason: TSynEditNotifyReason; + AHandler: TMethod); override; function GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths; override; property NextLines: TSynEditStrings read fSynStrings; @@ -328,6 +339,40 @@ begin IsUtf8 := True; end; +procedure TSynEditStrings.AddChangeHandler(AReason: TSynEditNotifyReason; + AHandler: TStringListLineCountEvent); +begin + AddGenericHandler(AReason, TMethod(AHandler)); +end; + +procedure TSynEditStrings.AddNotifyHandler(AReason: TSynEditNotifyReason; + AHandler: TNotifyEvent); +begin + AddGenericHandler(AReason, TMethod(AHandler)); +end; + +procedure TSynEditStrings.RemoveChangeHandler(AReason: TSynEditNotifyReason; + AHandler: TStringListLineCountEvent); +begin + RemoveGenericHandler(AReason, TMethod(AHandler)); +end; + +procedure TSynEditStrings.RemoveNotifyHandler(AReason: TSynEditNotifyReason; + AHandler: TNotifyEvent); +begin + RemoveGenericHandler(AReason, TMethod(AHandler)); +end; + +procedure TSynEditStrings.AddEditHandler(AHandler: TStringListLineEditEvent); +begin + AddGenericHandler(senrTextEdit, TMethod(AHandler)); +end; + +procedure TSynEditStrings.RemoveEditHandler(AHandler: TStringListLineEditEvent); +begin + RemoveGenericHandler(senrTextEdit, TMethod(AHandler)); +end; + function TSynEditStrings.GetPhysicalCharWidths(Index: Integer): TPhysicalCharWidths; begin Result := GetPhysicalCharWidths(Strings[Index], Index); @@ -564,24 +609,14 @@ begin fSynStrings.RegisterAttribute(Index, Size); end; -procedure TSynEditStringsLinked.AddChangeHandler(AReason: TSynEditNotifyReason; AHandler: TStringListLineCountEvent); +procedure TSynEditStringsLinked.AddGenericHandler(AReason: TSynEditNotifyReason; AHandler: TMethod); begin - fSynStrings.AddChangeHandler(AReason, AHandler); + fSynStrings.AddGenericHandler(AReason, AHandler); end; -procedure TSynEditStringsLinked.RemoveChangeHandler(AReason: TSynEditNotifyReason; AHandler: TStringListLineCountEvent); +procedure TSynEditStringsLinked.RemoveGenericHandler(AReason: TSynEditNotifyReason; AHandler: TMethod); begin - fSynStrings.RemoveChangeHandler(AReason, AHandler); -end; - -procedure TSynEditStringsLinked.AddEditHandler(AHandler: TStringListLineEditEvent); -begin - fSynStrings.AddEditHandler(AHandler); -end; - -procedure TSynEditStringsLinked.RemoveEditHandler(AHandler: TStringListLineEditEvent); -begin - fSynStrings.RemoveEditHandler(AHandler); + fSynStrings.RemoveGenericHandler(AReason, AHandler); end; // Count diff --git a/components/synedit/synedittextbuffer.pp b/components/synedit/synedittextbuffer.pp index 6a6ee0c802..59dd55b6b8 100644 --- a/components/synedit/synedittextbuffer.pp +++ b/components/synedit/synedittextbuffer.pp @@ -44,10 +44,10 @@ interface uses Classes, SysUtils, SynEditTextBase, FileUtil, LCLProc, LCLIntf, LCLType, - SynEditTypes, SynEditMiscProcs; + SynEditTypes, SynEditMiscProcs, SynEditMiscClasses; const - NullRange = TSynEditRange(-1); + NullRange = TSynEditRange(nil); type TSynEditFlagsClass = class end; // For Register @@ -69,14 +69,14 @@ type { TLineRangeNotificationList } - TLineRangeNotificationList = Class(TMethodList) + TLineRangeNotificationList = Class(TSynMethodList) public Procedure CallRangeNotifyEvents(Sender: TSynEditStrings; aIndex, aCount: Integer); end; { TLineEditNotificationList } - TLineEditNotificationList = Class(TMethodList) + TLineEditNotificationList = Class(TSynMethodList) public Procedure CallRangeNotifyEvents(Sender: TSynEditStrings; aLinePos, aBytePos, aCount, aLineBrkCnt: Integer; aText: String); @@ -120,14 +120,17 @@ type private FList: TSynEditStringMemory; FAttributeList: Array of TSynEditStringAttribute; + FLineRangeNotificationList: TLineRangeNotificationList; // LineCount FLineChangeNotificationList: TLineRangeNotificationList; // ContentChange (not called on add...) FLineEditNotificationList: TLineEditNotificationList; + FOnChangeList: TSynMethodList; + FOnChangingList: TSynMethodList; + FOnClearedList: TSynMethodList; + FIgnoreSendNotification: array [TSynEditNotifyReason] of Integer; fDosFileFormat: boolean; fIndexOfLongestLine: integer; - fOnChange: TNotifyEvent; - fOnChanging: TNotifyEvent; fRedoList: TSynEditUndoList; fUndoList: TSynEditUndoList; FIsUndoing: Boolean; @@ -141,7 +144,6 @@ type Procedure SetAttributeSize(NewSize: Integer); procedure SetFlags(Index: Integer; const AValue: TSynEditStringFlags); protected - fOnCleared: TNotifyEvent; function GetExpandedString(Index: integer): string; override; function GetLengthOfLongestLine: integer; override; @@ -192,19 +194,14 @@ type procedure SetDebugMarks(AFirst, ALast: Integer); procedure ClearDebugMarks; {$ENDIF} - procedure AddChangeHandler(AReason: TSynEditNotifyReason; - AHandler: TStringListLineCountEvent); override; - procedure RemoveChangeHandler(AReason: TSynEditNotifyReason; - AHandler: TStringListLineCountEvent); override; - procedure AddEditHandler(AHandler: TStringListLineEditEvent); override; - procedure RemoveEditHandler(AHandler: TStringListLineEditEvent); override; + procedure AddGenericHandler(AReason: TSynEditNotifyReason; + AHandler: TMethod); override; + procedure RemoveGenericHandler(AReason: TSynEditNotifyReason; + AHandler: TMethod); override; function GetPhysicalCharWidths(const Line: String; Index: Integer): TPhysicalCharWidths; override; public property DosFileFormat: boolean read fDosFileFormat write fDosFileFormat; property LengthOfLongestLine: integer read GetLengthOfLongestLine; - property OnChange: TNotifyEvent read fOnChange write fOnChange; - property OnChanging: TNotifyEvent read fOnChanging write fOnChanging; - property OnCleared: TNotifyEvent read fOnCleared write fOnCleared; {$IFDEF SYN_LAZARUS} property Flags[Index: Integer]: TSynEditStringFlags read GetFlags write SetFlags; @@ -408,6 +405,10 @@ begin FLineRangeNotificationList := TLineRangeNotificationList.Create; FLineChangeNotificationList := TLineRangeNotificationList.Create; FLineEditNotificationList := TLineEditNotificationList.Create; + FOnChangeList := TSynMethodList.Create; + FOnChangingList := TSynMethodList.Create; + FOnClearedList := TSynMethodList.Create; + for r := low(TSynEditNotifyReason) to high(TSynEditNotifyReason) do FIgnoreSendNotification[r] := 0; inherited Create; @@ -421,8 +422,6 @@ end; destructor TSynEditStringList.Destroy; begin - fOnChange := nil; - fOnChanging := nil; fAttributeList := nil; inherited Destroy; SetCount(0); @@ -430,6 +429,10 @@ begin FreeAndNil(FLineRangeNotificationList); FreeAndNil(FLineChangeNotificationList); FreeAndNil(FLineEditNotificationList); + FreeAndNil(FOnChangeList); + FreeAndNil(FOnChangingList); + FreeAndNil(FOnClearedList); + FreeAndNil(fList); end; @@ -480,8 +483,7 @@ begin BeginUpdate; SetCount(0); SetCapacity(0); - if Assigned(fOnCleared) then - fOnCleared(Self); + FOnClearedList.CallNotifyEvents(Self); FLineRangeNotificationList.CallRangeNotifyEvents(self, 0, -c); EndUpdate; end; @@ -861,32 +863,30 @@ begin Flags[Index] := Flags[Index] - [sfDebugMark]; end; -procedure TSynEditStringList.AddChangeHandler(AReason: TSynEditNotifyReason; AHandler: TStringListLineCountEvent); +procedure TSynEditStringList.AddGenericHandler(AReason: TSynEditNotifyReason; AHandler: TMethod); begin case AReason of - senrLineChange : FLineChangeNotificationList.Add(TMethod(AHandler)); - senrLineCount : FLineRangeNotificationList.Add(TMethod(AHandler)); + senrLineChange : FLineChangeNotificationList.Add(AHandler); + senrLineCount : FLineRangeNotificationList.Add(AHandler); + senrTextEdit: FLineEditNotificationList.Add(TMethod(AHandler)); + senrBeginUpdate : FOnChangingList.Add(AHandler); + senrEndUpdate : FOnChangeList.Add(AHandler); + senrCleared : FOnClearedList.Add(AHandler); end; end; -procedure TSynEditStringList.RemoveChangeHandler(AReason: TSynEditNotifyReason; AHandler: TStringListLineCountEvent); +procedure TSynEditStringList.RemoveGenericHandler(AReason: TSynEditNotifyReason; AHandler: TMethod); begin case AReason of - senrLineChange : FLineChangeNotificationList.Remove(TMethod(AHandler)); - senrLineCount : FLineRangeNotificationList.Remove(TMethod(AHandler)); + senrLineChange : FLineChangeNotificationList.Remove(AHandler); + senrLineCount : FLineRangeNotificationList.Remove(AHandler); + senrTextEdit: FLineEditNotificationList.Remove(TMethod(AHandler)); + senrBeginUpdate : FOnChangingList.Remove(AHandler); + senrEndUpdate : FOnChangeList.Remove(AHandler); + senrCleared : FOnClearedList.Remove(AHandler); end; end; -procedure TSynEditStringList.AddEditHandler(AHandler: TStringListLineEditEvent); -begin - FLineEditNotificationList.Add(TMethod(AHandler)); -end; - -procedure TSynEditStringList.RemoveEditHandler(AHandler: TStringListLineEditEvent); -begin - FLineEditNotificationList.Remove(TMethod(AHandler)); -end; - {$ENDIF} procedure TSynEditStringList.SetCapacity(NewCapacity: integer); @@ -897,11 +897,9 @@ end; procedure TSynEditStringList.SetUpdateState(Updating: Boolean); begin if Updating then begin - if Assigned(fOnChanging) then - fOnChanging(Self); + FOnChangingList.CallNotifyEvents(Self); end else begin - if Assigned(fOnChange) then - fOnChange(Self); + FOnChangeList.CallNotifyEvents(Self); end; end;