SynEdit, Refactor: Move more range scanning code to highlighter

git-svn-id: trunk@24477 -
This commit is contained in:
martin 2010-04-06 22:13:33 +00:00
parent 02c12b2e82
commit 9a3a4acd60
5 changed files with 324 additions and 141 deletions

View File

@ -364,8 +364,8 @@ type
fInserting: Boolean;
fLastMouseCaret: TPoint; // Char; physical (screen)
FLastMousePoint: TPoint; // Pixel
fHighlighterNeedsUpdateStartLine: integer; // 1 based, 0 means invalid
fHighlighterNeedsUpdateEndLine: integer; // 1 based, 0 means invalid
FChangedLinesStart: integer; // 1 based, 0 means invalid
FChangedLinesEnd: integer; // 1 based, 0 means invalid
FBeautifier: TSynCustomBeautifier;
FBeautifyStartLineIdx, FBeautifyEndLineIdx: Integer;
@ -524,7 +524,7 @@ type
procedure MoveCaretVert(DY: integer);
procedure PrimarySelectionRequest(const RequestedFormatID: TClipboardFormat;
Data: TStream);
function ScanFrom(var Index: integer; AtLeastTilIndex: integer = -1): integer; // Todo: move to line, currently scans twice or more, if SharedView is active
procedure ScanRanges;
procedure DoBlockSelectionChanged(Sender: TObject);
procedure SetBlockBegin(Value: TPoint);
procedure SetBlockEnd(Value: TPoint);
@ -610,7 +610,6 @@ type
procedure SetLines(Value: TStrings); override;
function GetMarkupMgr: TObject; override;
function GetCaretObj: TSynEditCaret; override;
procedure ScanFromAfterLock;
procedure DecPaintLock;
procedure DestroyWnd; override;
procedure DragOver(Source: TObject; X, Y: Integer;
@ -632,6 +631,7 @@ type
{$ENDIF}
Procedure LineCountChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
Procedure LineTextChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
procedure DoHighlightChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
procedure LinesChanging(Sender: TObject);
procedure LinesChanged(Sender: TObject);
procedure ListCleared(Sender: TObject);
@ -1540,6 +1540,7 @@ begin
with TSynEditStringList(fLines) do begin
AddChangeHandler(senrLineCount, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
AddChangeHandler(senrLineChange, {$IFDEF FPC}@{$ENDIF}LineTextChanged);
AddChangeHandler(senrHighlightChanged, {$IFDEF FPC}@{$ENDIF}DoHighlightChanged);
AddNotifyHandler(senrBeginUpdate, {$IFDEF FPC}@{$ENDIF}LinesChanging);
AddNotifyHandler(senrEndUpdate, {$IFDEF FPC}@{$ENDIF}LinesChanged);
AddNotifyHandler(senrCleared, {$IFDEF FPC}@{$ENDIF}ListCleared);
@ -1709,35 +1710,12 @@ begin
end;
end;
procedure TCustomSynEdit.ScanFromAfterLock;
var
LastLineChanged: LongInt;
begin
{$IFDEF SYNFOLDDEBUG}debugln(['FOLD-- ScanFromAfterLock; fPaintLock:=', fPaintLock, ' fHighlighterNeedsUpdateStartLine=', fHighlighterNeedsUpdateStartLine,' fHighlighterNeedsUpdateEndLine=',fHighlighterNeedsUpdateEndLine]);{$ENDIF}
if fHighlighterNeedsUpdateStartLine>0 then begin
//DebugLn('TCustomSynEdit.DecPaintLock ',dbgs(fHighlighterNeedsUpdateStartLine),'-',dbgs(fHighlighterNeedsUpdateEndLine));
if fHighlighterNeedsUpdateStartLine<=FTheLinesView.Count then begin
if fHighlighterNeedsUpdateEndLine>FTheLinesView.Count then
fHighlighterNeedsUpdateEndLine:=FTheLinesView.Count;
// rescan all lines in range
// Note: The highlighter range of the line can be invalid as well,
// so start scan one line earlier
dec(fHighlighterNeedsUpdateStartLine, 2);
LastLineChanged:=ScanFrom(fHighlighterNeedsUpdateStartLine,
fHighlighterNeedsUpdateEndLine-1);
//DebugLn('TCustomSynEdit.DecPaintLock ',dbgs(fHighlighterNeedsUpdateStartLine),'-',dbgs(fHighlighterNeedsUpdateEndLine),' LastLineChanged=',dbgs(LastLineChanged));
InvalidateLines(fHighlighterNeedsUpdateStartLine,LastLineChanged+1);
InvalidateGutterLines(fHighlighterNeedsUpdateStartLine,LastLineChanged+1);
end;
fHighlighterNeedsUpdateStartLine:=0;
fHighlighterNeedsUpdateEndLine:=0;
end;
end;
procedure TCustomSynEdit.DecPaintLock;
begin
if (fPaintLock=1) and HandleAllocated then begin
ScanFromAfterLock;
ScanRanges;
FChangedLinesStart:=0;
FChangedLinesEnd:=0;
end;
FCaret.Unlock; // Maybe after FFoldedLinesView
FTrimmedLinesView.UnLock; // Must be unlocked after caret
@ -3814,7 +3792,7 @@ begin
if eoFoldedCopyPaste in fOptions2 then begin
PTxt := ClipHelper.GetTagPointer(synClipTagFold);
if PTxt <> nil then begin
ScanFromAfterLock;
ScanRanges;
FFoldedLinesView.ApplyFoldDescription(InsStart.Y -1, InsStart.X,
FInternalBlockSelection.StartLinePos-1, FInternalBlockSelection.StartBytePos,
PTxt, ClipHelper.GetTagLen(synClipTagFold));
@ -4541,28 +4519,18 @@ begin
end;
end;
function TCustomSynEdit.ScanFrom(var Index: integer; AtLeastTilIndex: integer): integer;
// Index and AtLeastTilIndex are 0 based
procedure TCustomSynEdit.ScanRanges;
begin
{$IFDEF SYNFOLDDEBUG}debugln(['FOLD-- ScanFrom Index=', Index, ' AtLeats=', AtLeastTilIndex]);{$ENDIF}
if Index < 0 then Index := 0;
Result := Max(Index, AtLeastTilIndex);
if not assigned(fHighlighter) or (Index > FTheLinesView.Count - 1) then begin
FFoldedLinesView.FixFoldingAtTextIndex(Index);
fMarkupManager.TextChangedScreen(Max(RowToScreenRow(Index+1), 0), LinesInWindow+1);
if not assigned(FHighlighter) then begin
fMarkupManager.TextChanged(FChangedLinesStart, FChangedLinesEnd);
Topline := TopLine;
exit;
end;
fHighlighter.CurrentLines := FTheLinesView;
Result := fHighlighter.ScanFrom(Index, AtLeastTilIndex);
FHighlighter.CurrentLines := FTheLinesView;
FHighlighter.ScanRanges;
FFoldedLinesView.FixFoldingAtTextIndex(Index, Result);
fMarkupManager.TextChangedScreen(Max(RowToScreenRow(Index+1), 0),
Min(RowToScreenRow(Result), LinesInWindow+1));
fMarkupManager.TextChanged(FChangedLinesStart, FChangedLinesEnd);
Topline := TopLine;
if Index > 0 then dec(Index);
Dec(Result);
{$IFDEF SYNFOLDDEBUG}debugln(['FOLD-- ScanFrom Result=', Result]);{$ENDIF}
end;
procedure TCustomSynEdit.LineCountChanged(Sender: TSynEditStrings;
@ -4582,27 +4550,25 @@ begin
if (FBeautifyEndLineIdx < AIndex) then
FBeautifyEndLineIdx := AIndex;
end;
if PaintLock>0 then begin
if (fHighlighterNeedsUpdateStartLine<1)
or (fHighlighterNeedsUpdateStartLine>AIndex+1) then
fHighlighterNeedsUpdateStartLine:=AIndex+1;
if (fHighlighterNeedsUpdateEndLine<1)
or (fHighlighterNeedsUpdateEndLine<AIndex+1) then
fHighlighterNeedsUpdateEndLine:=AIndex + 1 + MaX(ACount, 0)
if (FChangedLinesStart<1)
or (FChangedLinesStart>AIndex+1) then
FChangedLinesStart:=AIndex+1;
if (FChangedLinesEnd<1)
or (FChangedLinesEnd<AIndex+1) then
FChangedLinesEnd:=AIndex + 1 + MaX(ACount, 0)
else
fHighlighterNeedsUpdateEndLine := fHighlighterNeedsUpdateEndLine
+ MaX(ACount, 0)
end
else
ScanFrom(AIndex, Max(AIndex, AIndex + ACount));
InvalidateLines(AIndex + 1, -1);
InvalidateGutterLines(AIndex + 1, -1);
FChangedLinesEnd := FChangedLinesEnd + MaX(ACount, 0);
end else begin
ScanRanges;
InvalidateLines(AIndex + 1, -1);
InvalidateGutterLines(AIndex + 1, -1);
end;
end;
procedure TCustomSynEdit.LineTextChanged(Sender: TSynEditStrings;
AIndex, ACount: Integer);
var
EndIndex: Integer;
begin
{$IFDEF SYNFOLDDEBUG}debugln(['FOLD-- LineTextChanged Aindex', AIndex, ' ACount=', ACount]);{$ENDIF}
IncreaseChangeStamp;
@ -4610,18 +4576,27 @@ begin
FBeautifyStartLineIdx := AIndex;
if (AIndex + ACount - 1 > FBeautifyEndLineIdx) then
FBeautifyEndLineIdx := AIndex + ACount - 1;
if PaintLock>0 then begin
if (fHighlighterNeedsUpdateStartLine<1)
or (fHighlighterNeedsUpdateStartLine>AIndex+1) then
fHighlighterNeedsUpdateStartLine:=AIndex+1;
if (fHighlighterNeedsUpdateEndLine<1)
or (fHighlighterNeedsUpdateEndLine<AIndex+1) then
fHighlighterNeedsUpdateEndLine:=AIndex + 1 + MaX(ACount, 0);
exit;
if (FChangedLinesStart<1)
or (FChangedLinesStart>AIndex+1) then
FChangedLinesStart:=AIndex+1;
if (FChangedLinesEnd<1)
or (FChangedLinesEnd<AIndex+1) then
FChangedLinesEnd:=AIndex + 1 + MaX(ACount, 0);
end else begin
ScanRanges;
InvalidateLines(AIndex + 1, AIndex + ACount);
InvalidateGutterLines(AIndex + 1, AIndex + ACount);
end;
EndIndex := ScanFrom(AIndex, Max(AIndex, AIndex + ACount)) + 1;
InvalidateLines(AIndex + 1, EndIndex);
InvalidateGutterLines(AIndex + 1, EndIndex);
end;
procedure TCustomSynEdit.DoHighlightChanged(Sender: TSynEditStrings; AIndex,
ACount: Integer);
begin
InvalidateLines(AIndex + 1, AIndex + 1 + ACount);
InvalidateGutterLines(AIndex + 1, AIndex + 1 + ACount);
FFoldedLinesView.FixFoldingAtTextIndex(AIndex, AIndex + ACount);
end;
procedure TCustomSynEdit.ListCleared(Sender: TObject);
@ -5007,6 +4982,7 @@ begin
if FHighlighter <> nil then
FHighlighter.DetachFromLines(FLines);
// TextBuffer
OldLines := TSynEditStringList(FLines);
if AValue = nil then begin
FLines := TSynEditStringList.Create;
@ -5323,7 +5299,7 @@ begin
BlockBegin := NewCaret;
SetSelTextPrimitive(smNormal, PChar(DragDropText), true);
if FoldInfo <> '' then begin
ScanFromAfterLock;
ScanRanges;
FFoldedLinesView.ApplyFoldDescription(NewCaret.Y -1, NewCaret.X,
FBlockSelection.StartLinePos-1, FBlockSelection.StartBytePos,
PChar(FoldInfo), length(FoldInfo));
@ -5424,8 +5400,6 @@ begin
end;
procedure TCustomSynEdit.SetHighlighter(const Value: TSynCustomHighlighter);
var
tmp: Integer;
begin
if Value <> fHighlighter then begin
RemoveHooksFromHighlighter;
@ -5451,8 +5425,7 @@ begin
RecalcCharExtent;
FTheLinesView.BeginUpdate;
try
tmp := 0;
ScanFrom(tmp,FTheLinesView.Count-1);
ScanRanges;
finally
FTheLinesView.EndUpdate;
end;
@ -6379,7 +6352,7 @@ procedure TCustomSynEdit.AfterLoadFromFile;
begin
if assigned(FFoldedLinesView) then begin
// TODO: Maybe defer until after paintlock?
ScanFromAfterLock;
ScanRanges;
FFoldedLinesView.UnfoldAll;
FFoldedLinesView.CollapseDefaultFolds;
TopLine := TopLine;
@ -7207,15 +7180,16 @@ begin
end;
procedure TCustomSynEdit.HighlighterAttrChanged(Sender: TObject);
var
t: integer;
begin
RecalcCharExtent;
SizeOrFontChanged(TRUE); //jr 2000-10-01
Invalidate;
t := 0;
if fHighlighter.AttributeChangeNeedScan then
ScanFrom(t, FLines.Count - 1);
if fHighlighter.AttributeChangeNeedScan then begin
FHighlighter.CurrentLines := FTheLinesView;
FHighlighter.ScanAllRanges;
fMarkupManager.TextChanged(0, FTheLinesView.Count - 1);
TopLine := TopLine;
end;
end;
procedure TCustomSynEdit.StatusChanged(AChanges: TSynStatusChanges);

View File

@ -44,7 +44,7 @@ uses
{$ENDIF}
Registry, IniFiles,
{$ENDIF}
SynEditTypes, SynEditMiscClasses, SynEditTextBase;
SynEditTypes, SynEditMiscClasses, SynEditTextBase, SynEditTextBuffer;
{$DEFINE _Gp_MustEnhanceRegistry}
{$IFDEF SYN_COMPILER_4_UP}
@ -59,19 +59,29 @@ type
{ TSynHighlighterRangeList }
TSynHighlighterRangeList = class(TSynEditStorageMem)
TSynHighlighterRangeList = class(TSynManagedStorageMem)
private
FRefCount: Integer;
FNeedsReScanStartIndex: Integer;
FNeedsReScanEndIndex: Integer;
function GetRange(Index: Integer): Pointer;
procedure SetRange(Index: Integer; const AValue: Pointer);
protected
function ItemSize: Integer; override;
protected
procedure LineTextChanged(AIndex: Integer); override;
procedure InsertedLines(AIndex, ACount: Integer); override;
procedure DeletedLines(AIndex, ACount: Integer); override;
public
constructor Create;
procedure ClearReScanNeeded;
procedure InvalidateAll;
procedure IncRefCount;
procedure DecRefCount;
property Range[Index: Integer]: Pointer read GetRange write SetRange; default;
property RefCount: Integer read FRefCount;
property NeedsReScanStartIndex: Integer read FNeedsReScanStartIndex;
property NeedsReScanEndIndex: Integer read FNeedsReScanEndIndex;
end;
{ TSynHighlighterAttributes }
@ -287,7 +297,9 @@ type
procedure StartAtLineIndex(LineNumber:Integer); virtual; // 0 based
procedure ContinueNextLine; // To be called at EOL; does not read the range
function ScanFrom(Index: integer; AtLeastTilIndex: integer = -1): integer;
function ScanFrom(Index: integer; AtLeastTilIndex: integer = -1): integer; deprecated;
procedure ScanRanges;
procedure ScanAllRanges;
procedure SetRange(Value: Pointer); virtual;
procedure ResetRange; virtual;
procedure SetLine({$IFDEF FPC}const {$ENDIF}NewValue: String;
@ -1248,6 +1260,40 @@ begin
end;
end;
procedure TSynCustomHighlighter.ScanRanges;
var
StartIndex, EndIndex, CurrentIndex, c: Integer;
begin
StartIndex := CurrentRanges.NeedsReScanStartIndex;
if (StartIndex < 0) or (StartIndex >= CurrentRanges.Count) then exit;
EndIndex := CurrentRanges.NeedsReScanEndIndex + 1;
CurrentIndex := StartIndex;
c := CurrentLines.Count;
FIsScanning := True;
try
StartAtLineIndex(CurrentIndex);
NextToEol;
while UpdateRangeInfoAtLine(CurrentIndex) or
(CurrentIndex <= EndIndex)
do begin
inc(CurrentIndex);
if CurrentIndex = c then
break;
ContinueNextLine;
NextToEol;
end;
finally
FIsScanning := False;
end;
CurrentLines.SendHighlightChanged(StartIndex, CurrentIndex);
end;
procedure TSynCustomHighlighter.ScanAllRanges;
begin
CurrentRanges.InvalidateAll;
ScanRanges;
end;
procedure TSynCustomHighlighter.SetEnabled(const Value: boolean);
begin
if fEnabled <> Value then
@ -1275,8 +1321,11 @@ begin
r := TSynHighlighterRangeList(Lines.Ranges[ClassType]);
if assigned(r) then
r.IncRefCount
else
Lines.Ranges[ClassType] := CreateRangeList;
else begin
r := CreateRangeList;
Lines.Ranges[ClassType] := r;
r.InvalidateAll;
end;
FCurrentLines := nil;
end;
@ -1288,8 +1337,8 @@ begin
if not assigned(r) then exit;
r.DecRefCount;
if r.RefCount = 0 then begin
r.Free;
Lines.Ranges[ClassType] := nil;
r.Free;
end;
end;
@ -1332,10 +1381,55 @@ begin
Result := SizeOf(Pointer);
end;
procedure TSynHighlighterRangeList.LineTextChanged(AIndex: Integer);
begin
if FNeedsReScanStartIndex < 0 then begin
FNeedsReScanStartIndex := AIndex;
FNeedsReScanEndIndex := AIndex;
end
else if AIndex < FNeedsReScanStartIndex then
FNeedsReScanStartIndex := AIndex
else if AIndex > FNeedsReScanEndIndex then
FNeedsReScanEndIndex := AIndex;
end;
procedure TSynHighlighterRangeList.InsertedLines(AIndex, ACount: Integer);
begin
if (FNeedsReScanStartIndex < 0) or (AIndex < FNeedsReScanStartIndex) then
FNeedsReScanStartIndex := AIndex;
if (FNeedsReScanEndIndex < 0) or (FNeedsReScanEndIndex < AIndex) then
FNeedsReScanEndIndex := AIndex + ACount
else
FNeedsReScanEndIndex := FNeedsReScanEndIndex + ACount
end;
procedure TSynHighlighterRangeList.DeletedLines(AIndex, ACount: Integer);
begin
if AIndex >= Count then exit;
if (FNeedsReScanStartIndex < 0) or (AIndex < FNeedsReScanStartIndex) then
FNeedsReScanStartIndex := AIndex;
if (FNeedsReScanEndIndex < 0) or (FNeedsReScanEndIndex < AIndex) then
FNeedsReScanEndIndex := AIndex;
end;
procedure TSynHighlighterRangeList.ClearReScanNeeded;
begin
FNeedsReScanStartIndex := -1;
FNeedsReScanEndIndex := -1;
end;
procedure TSynHighlighterRangeList.InvalidateAll;
begin
FNeedsReScanStartIndex := 0;
FNeedsReScanEndIndex := Count - 1;
end;
constructor TSynHighlighterRangeList.Create;
begin
Inherited;
FRefCount := 1;
ClearReScanNeeded;
end;
procedure TSynHighlighterRangeList.IncRefCount;

View File

@ -145,7 +145,6 @@ type
Function GetNextMarkupColAfterRowCol(const aRow, aCol : Integer) : Integer; override;
// Notifications about Changes to the text
Procedure TextChangedScreen(aFirstCodeLine, aLastCodeLine: Integer);
Procedure TextChanged(aFirstCodeLine, aLastCodeLine: Integer); override;
end;
@ -485,11 +484,6 @@ begin
end;
end;
procedure TSynEditMarkupManager.TextChangedScreen(aFirstCodeLine, aLastCodeLine: Integer);
begin
TextChanged(ScreenRowToRow(aFirstCodeLine), ScreenRowToRow(aLastCodeLine));
end;
procedure TSynEditMarkupManager.TextChanged(aFirstCodeLine, aLastCodeLine: Integer);
var
i : integer;

View File

@ -39,6 +39,7 @@ type
TSynEditNotifyReason = ( // TStringListLineCountEvent
senrLineCount, senrLineChange, senrEditAction,
senrHighlightChanged, // used by Highlighter
// TStringListLineEditEvent
senrTextEdit,
// TNotifyEvent
@ -65,13 +66,15 @@ type
procedure SetCapacity(const AValue: Integer); virtual;
procedure SetCount(const AValue: Integer); virtual;
function ItemSize: Integer; virtual; abstract;
procedure Move(AFrom, ATo, ALen: Integer); virtual;
property Mem: PByte read FMem;
property ItemPointer[Index: Integer]: Pointer read GetItemPointer;
public
constructor Create;
destructor Destroy; override;
procedure Move(AFrom, ATo, ALen: Integer); virtual;
procedure InsertRows(AIndex, ACount: Integer); virtual;
procedure DeleteRows(AIndex, ACount: Integer); virtual;
property Capacity: Integer read FCapacity write SetCapacity;
// Count must be maintained by owner
property Count: Integer read FCount write SetCount;
@ -159,6 +162,7 @@ type
property IsUndoing: Boolean read GetIsUndoing write SetIsUndoing;
property IsRedoing: Boolean read GetIsRedoing write SetIsRedoing;
procedure IncreaseTextChangeStamp;
procedure SendHighlightChanged(aIndex, aCount: Integer);
public
property ExpandedStrings[Index: integer]: string read GetExpandedString;
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
@ -343,8 +347,25 @@ type
write SetCurrentReason;
end;
ESynEditStorageMem = class(Exception);
implementation
{$IFNDEF FPC}
{$IFDEF SYN_COMPILER_3_UP}
resourcestring
{$ELSE}
const
{$ENDIF}
{$ELSE}
const
{$ENDIF}
SListIndexOutOfBounds = 'Invalid stringlist index %d';
procedure ListIndexOutOfBounds(Index: integer);
begin
raise ESynEditStorageMem.CreateFmt(SListIndexOutOfBounds, [Index]);
end;
{ TSynEditStrings }
@ -514,6 +535,11 @@ begin
inc(fTextChangeStamp);
end;
procedure TSynEditStrings.SendHighlightChanged(aIndex, aCount: Integer);
begin
SendNotification(senrHighlightChanged, Self, aIndex, aCount);
end;
{ TSynEditStringsLinked }
constructor TSynEditStringsLinked.Create(ASynStringSource: TSynEditStrings);
@ -1186,6 +1212,29 @@ begin
inherited Destroy;
end;
procedure TSynEditStorageMem.InsertRows(AIndex, ACount: Integer);
begin
if (AIndex < 0) or (AIndex > Count) then
ListIndexOutOfBounds(AIndex);
if Capacity < Count + ACount then
SetCapacity(Count + ACount);
if AIndex < Count then
Move(AIndex, AIndex + ACount, Count - AIndex);
Count := Count + ACount;
end;
procedure TSynEditStorageMem.DeleteRows(AIndex, ACount: Integer);
var
LinesAfter: Integer;
begin
if (AIndex < 0) or (AIndex + ACount > Count) then
ListIndexOutOfBounds(AIndex);
LinesAfter := Count - (AIndex + ACount);
if LinesAfter > 0 then
Move(AIndex + ACount, AIndex, LinesAfter);
Count := Count - ACount;
end;
procedure TSynEditStorageMem.Move(AFrom, ATo, ALen: Integer);
var
len: Integer;

View File

@ -82,42 +82,53 @@ type
aLinePos, aBytePos, aCount, aLineBrkCnt: Integer; aText: String);
end;
{ TSynEditStringMemory }
{ TSynManagedStorageMem }
TSynManagedStorageMem = class(TSynEditStorageMem)
protected
procedure LineTextChanged(AIndex: Integer); virtual;
procedure InsertedLines(AIndex, ACount: Integer); virtual;
procedure DeletedLines(AIndex, ACount: Integer); virtual;
end;
{ TSynEditStringMemory }
TSynEditStringRangeEntry = record
Index: TClass;
Data: TSynEditStorageMem;
Data: TSynManagedStorageMem;
end;
TSynEditStringMemory = class(TSynEditStorageMem)
private
FAttributeSize: Integer;
FRangeList: Array of TSynEditStringRangeEntry;
FRangeListLock: Integer;
function GetAttribute(Index: Integer; Pos: Integer; Size: Word): Pointer;
function GetAttributeSize: Integer;
function GetObject(Index: Integer): TObject;
function GetRange(Index: TClass): TSynEditStorageMem;
function GetRange(Index: TClass): TSynManagedStorageMem;
function GetString(Index: Integer): String;
procedure SetAttribute(Index: Integer; Pos: Integer; Size: Word; const AValue: Pointer);
procedure SetAttributeSize(const AValue: Integer);
procedure SetObject(Index: Integer; const AValue: TObject);
procedure SetRange(Index: TClass; const AValue: TSynEditStorageMem);
procedure SetRange(Index: TClass; const AValue: TSynManagedStorageMem);
procedure SetString(Index: Integer; const AValue: String);
protected
procedure Move(AFrom, ATo, ALen: Integer); override;
procedure SetCount(const AValue: Integer); override;
function ItemSize: Integer; override;
procedure SetCapacity(const AValue: Integer); override;
public
constructor Create;
procedure Move(AFrom, ATo, ALen: Integer); override;
procedure InsertRows(AIndex, ACount: Integer); override;
procedure DeleteRows(AIndex, ACount: Integer); override;
property Strings[Index: Integer]: String read GetString write SetString; default;
property Objects[Index: Integer]: TObject read GetObject write SetObject;
property Attribute[Index: Integer; Pos: Integer; Size: Word]: Pointer
read GetAttribute write SetAttribute;
property AttributeSize: Integer read GetAttributeSize write SetAttributeSize;
property RangeList[Index: TClass]: TSynEditStorageMem read GetRange write SetRange;
property RangeList[Index: TClass]: TSynManagedStorageMem read GetRange write SetRange;
end;
{ TSynEditStringList }
@ -129,6 +140,7 @@ type
FLineRangeNotificationList: TLineRangeNotificationList; // LineCount
FLineChangeNotificationList: TLineRangeNotificationList; // ContentChange (not called on add...)
FLineInvalidateNotificationList: TLineRangeNotificationList; // senrHighlightChanged
FLineEditNotificationList: TLineEditNotificationList;
FRefCount: integer;
FUndoRedoAddedNotificationList: TSynMethodList;
@ -424,6 +436,7 @@ begin
FLineRangeNotificationList := TLineRangeNotificationList.Create;
FLineChangeNotificationList := TLineRangeNotificationList.Create;
FLineInvalidateNotificationList := TLineRangeNotificationList.Create;
FLineEditNotificationList := TLineEditNotificationList.Create;
FUndoRedoAddedNotificationList := TLineEditNotificationList.Create;
FOnChangeList := TSynMethodList.Create;
@ -449,6 +462,7 @@ begin
SetCapacity(0);
FreeAndNil(FLineRangeNotificationList);
FreeAndNil(FLineChangeNotificationList);
FreeAndNil(FLineInvalidateNotificationList);
FreeAndNil(FLineEditNotificationList);
FreeAndNil(FUndoRedoAddedNotificationList);
FreeAndNil(FOnChangeList);
@ -516,37 +530,26 @@ end;
procedure TSynEditStringList.Delete(Index: integer);
begin
if (Index < 0) or (Index > Count) then
// Ensure correct index, so DeleteLines will not throw exception
if (Index < 0) or (Index >= Count) then
ListIndexOutOfBounds(Index);
BeginUpdate;
if Index < Count-1 then
fList.Move(Index + 1, Index, Count-Index-1);
SetCount(Count - 1);
FList.DeleteRows(Index, 1);
fIndexOfLongestLine := -1;
FLineRangeNotificationList.CallRangeNotifyEvents(self, Index, -1);
EndUpdate;
end;
procedure TSynEditStringList.DeleteLines(Index, NumLines: Integer);
var
LinesAfter: integer;
begin
if NumLines > 0 then begin
if (Index < 0) or (Index >= Count) then
// Ensure correct index, so DeleteLines will not throw exception
if (Index < 0) or (Index + NumLines > Count) then
ListIndexOutOfBounds(Index);
LinesAfter := Count - (Index + NumLines);
if LinesAfter < 0 then
NumLines := Count - Index;
if LinesAfter > 0 then begin
BeginUpdate;
try
fList.Move(Index + NumLines, Index, LinesAfter);
finally
EndUpdate;
end;
end;
SetCount(Count - NumLines);
BeginUpdate;
FList.DeleteRows(Index, NumLines);
FLineRangeNotificationList.CallRangeNotifyEvents(self, Index, -NumLines);
EndUpdate;
end;
end;
@ -717,13 +720,14 @@ end;
procedure TSynEditStringList.InsertItem(Index: integer; const S: string);
begin
// Ensure correct index, so DeleteLines will not throw exception
if (Index < 0) or (Index > Count) then
ListIndexOutOfBounds(Index);
BeginUpdate;
if Count = Capacity then
Grow;
if Index < Count then
FList.Move(Index, Index+1, Count - Index);
FList.InsertRows(Index, 1);
fIndexOfLongestLine := -1; //mh 2000-10-19
SetCount(Count + 1);
fList[Index] := S;
FList.Objects[Index] := nil;
Flags[Index] := [];
@ -734,13 +738,14 @@ end;
procedure TSynEditStringList.InsertLines(Index, NumLines: integer);
begin
if NumLines > 0 then begin
// Ensure correct index, so DeleteLines will not throw exception
if (Index < 0) or (Index > Count) then
ListIndexOutOfBounds(Index);
BeginUpdate;
try
if Capacity<Count + NumLines then
SetCapacity(Count + NumLines);
if Index < Count then
FList.Move(Index, Index + NumLines, Count-Index);
SetCount(Count + NumLines);
FList.InsertRows(Index, NumLines);
FLineRangeNotificationList.CallRangeNotifyEvents(self, Index, NumLines);
finally
EndUpdate;
@ -795,7 +800,7 @@ end;
procedure TSynEditStringList.PutRange(Index: TClass; const ARange: TSynEditStorageMem);
begin
FList.RangeList[Index] := ARange;
FList.RangeList[Index] := ARange as TSynManagedStorageMem;
end;
function TSynEditStringList.GetAttribute(const Owner: TClass; const Index: Integer): Pointer;
@ -907,6 +912,7 @@ begin
senrLineChange : FLineChangeNotificationList.Add(AHandler);
senrLineCount : FLineRangeNotificationList.Add(AHandler);
senrTextEdit: FLineEditNotificationList.Add(TMethod(AHandler));
senrHighlightChanged: FLineInvalidateNotificationList.Add(TMethod(AHandler));
senrBeginUpdate : FOnChangingList.Add(AHandler);
senrEndUpdate : FOnChangeList.Add(AHandler);
senrCleared : FOnClearedList.Add(AHandler);
@ -920,6 +926,7 @@ begin
senrLineChange : FLineChangeNotificationList.Remove(AHandler);
senrLineCount : FLineRangeNotificationList.Remove(AHandler);
senrTextEdit: FLineEditNotificationList.Remove(TMethod(AHandler));
senrHighlightChanged: FLineInvalidateNotificationList.Remove(TMethod(AHandler));
senrBeginUpdate : FOnChangingList.Remove(AHandler);
senrEndUpdate : FOnChangeList.Remove(AHandler);
senrCleared : FOnClearedList.Remove(AHandler);
@ -933,6 +940,7 @@ begin
FLineRangeNotificationList.AddCopyFrom(OtherLines.FLineRangeNotificationList, AOwner);
FLineChangeNotificationList.AddCopyFrom(OtherLines.FLineChangeNotificationList, AOwner);
FLineEditNotificationList.AddCopyFrom(OtherLines.FLineEditNotificationList, AOwner);
FLineInvalidateNotificationList.AddCopyFrom(OtherLines.FLineInvalidateNotificationList, AOwner);
FUndoRedoAddedNotificationList.AddCopyFrom(OtherLines.FUndoRedoAddedNotificationList, AOwner);
FOnChangeList.AddCopyFrom(OtherLines.FOnChangeList, AOwner);
FOnChangingList.AddCopyFrom(OtherLines.FOnChangingList, AOwner);
@ -944,6 +952,7 @@ begin
FLineRangeNotificationList.RemoveAllMethodsOfObject(AOwner);
FLineChangeNotificationList.RemoveAllMethodsOfObject(AOwner);
FLineEditNotificationList.RemoveAllMethodsOfObject(AOwner);
FLineInvalidateNotificationList.RemoveAllMethodsOfObject(AOwner);
FUndoRedoAddedNotificationList.RemoveAllMethodsOfObject(AOwner);
FOnChangeList.RemoveAllMethodsOfObject(AOwner);
FOnChangingList.RemoveAllMethodsOfObject(AOwner);
@ -1085,6 +1094,8 @@ begin
senrEditAction:
FLineEditNotificationList.CallRangeNotifyEvents(ASender, aIndex, // aindex is mis-named (linepos) for edit action
aBytePos, aLen, aCount, aTxt);
senrHighlightChanged:
FLineInvalidateNotificationList.CallRangeNotifyEvents(ASender, aIndex, aCount);
end;
end;
@ -1108,10 +1119,35 @@ const
constructor TSynEditStringMemory.Create;
begin
inherited Create;
FRangeListLock := 0;
AttributeSize := 0;
FRangeList := nil;
end;
procedure TSynEditStringMemory.InsertRows(AIndex, ACount: Integer);
var
i: Integer;
begin
// Managed lists to get Mave, Count, instead of InsertRows
inc(FRangeListLock);
inherited InsertRows(AIndex, ACount);
dec(FRangeListLock);
for i := 0 to length(FRangeList) - 1 do
FRangeList[i].Data.InsertedLines(AIndex, ACount);
end;
procedure TSynEditStringMemory.DeleteRows(AIndex, ACount: Integer);
var
i: Integer;
begin
// Managed lists to get Mave, Count, instead of InsertRows
inc(FRangeListLock);
inherited DeleteRows(AIndex, ACount);
dec(FRangeListLock);
for i := 0 to length(FRangeList) - 1 do
FRangeList[i].Data.DeletedLines(AIndex, ACount);
end;
procedure TSynEditStringMemory.Move(AFrom, ATo, ALen: Integer);
var
Len, i: Integer;
@ -1130,13 +1166,24 @@ end;
procedure TSynEditStringMemory.SetCount(const AValue: Integer);
var
i : Integer;
OldCount, i : Integer;
begin
If Count = AValue then exit;
for i:= AValue to Count-1 do Strings[i]:='';
for i:= AValue to Count-1 do
Strings[i]:='';
OldCount := Count;
inherited SetCount(AValue);
for i := 0 to length(FRangeList) - 1 do
FRangeList[i].Data.Count := AValue;
if FRangeListLock = 0 then begin
if OldCount > Count then begin
for i := 0 to length(FRangeList) - 1 do
FRangeList[i].Data.DeletedLines(Count, OldCount - Count);
end else begin
for i := 0 to length(FRangeList) - 1 do
FRangeList[i].Data.InsertedLines(OldCount, Count - OldCount);
end;
end;
end;
function TSynEditStringMemory.GetAttributeSize: Integer;
@ -1161,8 +1208,12 @@ begin
end;
procedure TSynEditStringMemory.SetString(Index: Integer; const AValue: String);
var
i: Integer;
begin
(PString(Mem + Index * FAttributeSize))^ := AValue;
for i := 0 to length(FRangeList) - 1 do
FRangeList[i].Data.LineTextChanged(Index);
end;
function TSynEditStringMemory.ItemSize: Integer;
@ -1184,7 +1235,7 @@ begin
Result := (PObject(Mem + Index * FAttributeSize + SizeOf(String)))^;
end;
function TSynEditStringMemory.GetRange(Index: TClass): TSynEditStorageMem;
function TSynEditStringMemory.GetRange(Index: TClass): TSynManagedStorageMem;
var
i: Integer;
begin
@ -1199,7 +1250,7 @@ begin
(PObject(Mem + Index * FAttributeSize + SizeOf(String)))^ := AValue;
end;
procedure TSynEditStringMemory.SetRange(Index: TClass; const AValue: TSynEditStorageMem);
procedure TSynEditStringMemory.SetRange(Index: TClass; const AValue: TSynManagedStorageMem);
var
i, j: Integer;
begin
@ -1208,23 +1259,30 @@ begin
dec(i);
if i < 0 then begin
i := length(FRangeList);
SetLength(FRangeList, i + 1);
FRangeList[i].Index := Index;
if AValue = nil then begin
debugln('Removing none existent range');
exit;
end;
j := length(FRangeList);
SetLength(FRangeList, j + 1);
FRangeList[j].Data := AValue;
FRangeList[j].Index := Index;
end
else
begin
if AValue <> nil then
DebugLn(['TSynEditStringMemory.SetRange - Overwriting old range at index=', i, ' index=', dbgs(Index)]);
FRangeList[i].Data := AValue;
FRangeList[i].Data := AValue;
if AValue = nil then begin
for j := i to length(FRangeList) - 2 do
FRangeList[j] := FRangeList[j+1];
SetLength(FRangeList, length(FRangeList) - 1);
end;
end;
if AValue <> nil then begin
AValue.Capacity := Capacity;
AValue.Count := Count;
end else begin
for j := i to length(FRangeList) - 2 do
FRangeList[j] := FRangeList[j+1];
SetLength(FRangeList, length(FRangeList) - 1);
end;
end;
@ -1272,5 +1330,19 @@ begin
aLineBrkCnt, aText);
end;
{ TSynManagedStorageMem }
procedure TSynManagedStorageMem.LineTextChanged(AIndex: Integer);
begin // empty base class
end;
procedure TSynManagedStorageMem.InsertedLines(AIndex, ACount: Integer);
begin // empty base class
end;
procedure TSynManagedStorageMem.DeletedLines(AIndex, ACount: Integer);
begin // empty base class
end;
end.