SynEdit: refactor painting

git-svn-id: trunk@34165 -
This commit is contained in:
martin 2011-12-14 02:53:19 +00:00
parent 21848dbdaa
commit 400f05dee0
24 changed files with 1346 additions and 947 deletions

1
.gitattributes vendored
View File

@ -2322,6 +2322,7 @@ components/synedit/languages/synmacrorecorder.pt_BR.po svneol=native#text/plain
components/synedit/languages/synmacrorecorder.ru.po svneol=native#text/plain
components/synedit/languages/synmacrorecorder.uk.po svneol=native#text/plain
components/synedit/languages/synmacrorecorder.zh_CN.po svneol=native#text/utf8
components/synedit/lazsynedittext.pas svneol=native#text/pascal
components/synedit/synbeautifier.pas svneol=native#text/plain
components/synedit/syncompletion.pas svneol=native#text/pascal
components/synedit/syndesignstringconstants.pas svneol=native#text/plain

View File

@ -25,7 +25,7 @@ uses
SynMacroRecorder, SynMemo, SynPluginSyncroEdit, SynPluginSyncronizedEditBase,
SynPluginTemplateEdit, SynPropertyEditObjectList, SynRegExpr, SynTextDrawer,
SynEditMarkupGutterMark, SynHighlighterBat, SynHighlighterIni, SynEditMarkupSpecialChar,
LazarusPackageIntf;
LazSynEditText, LazarusPackageIntf;
implementation

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ unit SynBeautifier;
interface
uses
Classes, SysUtils, LCLProc, SynEditMiscClasses, SynEditTextBase, SynEditPointClasses,
Classes, SysUtils, LCLProc, SynEditMiscClasses, LazSynEditText, SynEditPointClasses,
SynEditKeyCmds;
type

View File

@ -72,15 +72,18 @@ uses
{$ENDIF}
SynEditTypes, SynEditSearch, SynEditKeyCmds, SynEditMouseCmds, SynEditMiscProcs,
SynEditPointClasses, SynBeautifier, SynEditMarks,
// Markup
SynEditMarkup, SynEditMarkupHighAll, SynEditMarkupBracket, SynEditMarkupWordGroup,
SynEditMarkupCtrlMouseLink, SynEditMarkupSpecialLine, SynEditMarkupSelection,
SynEditMarkupSpecialChar,
SynEditTextBase, SynEditTextTrimmer, SynEditFoldedView, SynEditTextTabExpander,
SynEditTextDoubleWidthChars,
// Lines
SynEditTextBase, LazSynEditText, SynEditTextBuffer, SynEditLines,
SynEditTextTrimmer, SynEditTextTabExpander, SynEditTextDoubleWidthChars,
SynEditFoldedView,
// Gutter
SynGutterBase, SynGutter, SynGutterCodeFolding, SynGutterChanges,
SynGutterLineNumber, SynGutterMarks, SynGutterLineOverview,
SynEditMiscClasses, SynEditTextBuffer, SynEditHighlighter, SynTextDrawer,
SynEditLines,
SynEditMiscClasses, SynEditHighlighter, SynTextDrawer,
LResources, Clipbrd
{$IFDEF SYN_COMPILER_4_UP}
, StdActns
@ -413,6 +416,7 @@ type
FLines: TSynEditStrings; // The real (un-mapped) line-buffer
FStrings: TStrings; // External TStrings based interface to the Textbuffer
FTopLinesView: TSynEditStrings; // The linesview that holds the real line-buffer/FLines
FDisplayView: TLazSynDisplayView;
fExtraCharSpacing: integer;
fLinesInWindow: Integer;// MG: fully visible lines in window
@ -1720,14 +1724,18 @@ begin
// ftab, currently has LengthOfLongestLine, therefore must be after DoubleWidthChar
FTabbedLinesView := TSynEditStringTabExpander.Create(FDoubleWidthChrLinesView);
FFoldedLinesView := TSynEditFoldedView.Create(FTabbedLinesView, fCaret);
FFoldedLinesView.OnFoldChanged := {$IFDEF FPC}@{$ENDIF}FoldChanged;
FFoldedLinesView.OnLineInvalidate := {$IFDEF FPC}@{$ENDIF}InvalidateGutterLines;
// Pointer to the First/Lowest View
// TODO: this should be Folded...
FTheLinesView := FTabbedLinesView;
FTopLinesView := FTrimmedLinesView;
FFoldedLinesView := TSynEditFoldedView.Create(FTheLinesView, fCaret);
FFoldedLinesView.OnFoldChanged := {$IFDEF FPC}@{$ENDIF}FoldChanged;
FFoldedLinesView.OnLineInvalidate := {$IFDEF FPC}@{$ENDIF}InvalidateGutterLines;
FFoldedLinesView.DisplayView.NextView := FTheLinesView.DisplayView;
FDisplayView := FFoldedLinesView.DisplayView;
// External Accessor
FStrings := TSynEditLines.Create(TSynEditStringList(FLines), {$IFDEF FPC}@{$ENDIF}MarkTextAsSaved);
@ -3370,7 +3378,7 @@ end;
procedure TCustomSynEdit.PaintTextLines(AClip: TRect; FirstLine, LastLine,
FirstCol, LastCol: integer);
// FirstLine, LastLine are based 1
// FirstLine, LastLine are based 0
// FirstCol, LastCol are screen based 1 without scrolling (physical position).
// i.e. the real screen position is fTextOffset+Pred(FirstCol)*CharWidth
var
@ -3863,6 +3871,7 @@ var
function CharToByteLen(aCharLen: Integer) : Integer;
begin
if not UseUTF8 then exit(aCharLen);
// tabs and double-width chars are padded with spaces
Result := UTF8CharToByteIndex(sToken, nTokenByteLen, aCharLen);
if Result < 0 then begin
debugln('ERROR: Could not convert CharLen (',dbgs(aCharLen),') to byteLen (maybe invalid UTF8?)',' len ',dbgs(nTokenByteLen),' Line ',dbgs(CurLine),' PhysPos ',dbgs(CurPhysPos));
@ -4000,27 +4009,22 @@ var
attr: TSynHighlighterAttributes;
ypos: Integer;
DividerInfo: TSynDividerDrawConfigSetting;
cl: Integer;
TV, cl: Integer;
begin
// Initialize rcLine for drawing. Note that Top and Bottom are updated
// inside the loop. Get only the starting point for this.
rcLine := AClip;
rcLine.Bottom := FirstLine * fTextHeight;
// Make sure the token accumulator string doesn't get reassigned to often.
if Assigned(fHighlighter) then begin
TokenAccu.MaxLen := Max(128, fCharsInWindow * 4);
SetTokenAccuLength;
end;
TV := TopView - 1;
// Now loop through all the lines. The indices are valid for Lines.
CurLine := FirstLine-1;
while CurLine<LastLine do begin
inc(CurLine);
CurTextIndex := FFoldedLinesView.TextIndex[CurLine];
// CurTextIndex := FFoldedLinesView.TextIndex[CurLine];
//CharWidths := FFoldedLinesView.GetPhysicalCharWidths(CurLine);
CharWidths := FTheLinesView.GetPhysicalCharWidths(CurTextIndex);
fMarkupManager.PrepareMarkupForRow(CurTextIndex+1);
// Get the line.
// Update the rcLine rect to this line.
rcLine.Top := rcLine.Bottom;
@ -4039,41 +4043,25 @@ var
rcLine.Left := DrawLeft;
ForceEto := False;
if not Assigned(fHighlighter) then begin
sLine := FFoldedLinesView[CurLine];
DrawHiLightMarkupToken(nil, PChar(Pointer(sLine)), Length(sLine));
end else begin
// draw splitter line
DividerInfo := fHighlighter.DrawDivider[CurTextIndex];
if (DividerInfo.Color <> clNone) and (nRightEdge > TextLeftPixelOffset(False) - 1) then
begin
ypos := rcToken.Bottom - 1;
cl := DividerInfo.Color;
if cl = clDefault then
cl := fRightEdgeColor;
fTextDrawer.DrawLine(nRightEdge, ypos, TextLeftPixelOffset(False) - 1, ypos, cl);
dec(rcToken.Bottom);
end;
// Initialize highlighter with line text and range info. It is
// necessary because we probably did not scan to the end of the last
// line - the internal highlighter range might be wrong.
fHighlighter.StartAtLineIndex(CurTextIndex);
// Try to concatenate as many tokens as possible to minimize the count
// of ExtTextOut calls necessary. This depends on the selection state
// or the line having special colors. For spaces the foreground color
// is ignored as well.
//debugln('>>>> PaintLines Line=',dbgs(CurLine),' rect=',dbgs(rcToken));
while not fHighlighter.GetEol do begin
fHighlighter.GetTokenEx(sToken,nTokenLen);
attr := fHighlighter.GetTokenAttribute;
// Add Markup to the token and append it to the TokenAccu
// record. This will paint any chars already stored if there is
// a (visible) change in the attributes.
DrawHiLightMarkupToken(attr,sToken,nTokenLen);
// Let the highlighter scan the next token.
fHighlighter.Next;
end;
FDisplayView.SetHighlighterTokensLine(TV + CurLine, CurTextIndex);
CharWidths := FTheLinesView.GetPhysicalCharWidths(CurTextIndex);
fMarkupManager.PrepareMarkupForRow(CurTextIndex+1);
DividerInfo := FDisplayView.GetDrawDividerInfo;
if (DividerInfo.Color <> clNone) and (nRightEdge > TextLeftPixelOffset(False) - 1) then
begin
ypos := rcToken.Bottom - 1;
cl := DividerInfo.Color;
if cl = clDefault then
cl := fRightEdgeColor;
fTextDrawer.DrawLine(nRightEdge, ypos, TextLeftPixelOffset(False) - 1, ypos, cl);
dec(rcToken.Bottom);
end;
while FDisplayView.GetNextHighlighterToken(sToken, nTokenLen, attr) do begin
DrawHiLightMarkupToken(attr,sToken,nTokenLen);
end;
// Draw anything that's left in the TokenAccu record. Fill to the end
// of the invalid area with the correct colors.
PaintHighlightToken(TRUE);
@ -4091,11 +4079,8 @@ begin
//DebugLn(['TCustomSynEdit.PaintTextLines ',dbgs(AClip)]);
CurLine:=-1;
FillChar(TokenAccu,SizeOf(TokenAccu),0);
//DebugLn('TCustomSynEdit.PaintTextLines ',DbgSName(Self),' TopLine=',dbgs(TopLine),' AClip=',dbgs(AClip));
colEditorBG := Color;
if Assigned(fHighlighter) then
fHighlighter.CurrentLines := FTheLinesView;
// If the right edge is visible and in the invalid area, prepare to paint it.
// Do this first to realize the pen when getting the dc variable.
bDoRightEdge := FALSE;
@ -4126,12 +4111,24 @@ begin
// necessary information about the selected area: is there any visible
// selected area, and what are its lines / columns?
// Moved to two local procedures to make it easier to read.
FillChar(TokenAccu,SizeOf(TokenAccu),0);
if Assigned(fHighlighter) then begin
fHighlighter.CurrentLines := FTheLinesView;
// Make sure the token accumulator string doesn't get reassigned to often.
TokenAccu.MaxLen := Max(128, fCharsInWindow * 4);
SetTokenAccuLength;
end;
FDisplayView.InitHighlighterTokens(FHighlighter);
fTextDrawer.Style := Font.Style;
fTextDrawer.BeginDrawing(dc);
try
PaintLines;
finally
fTextDrawer.EndDrawing;
FDisplayView.FinishHighlighterTokens;
ReAllocMem(TokenAccu.p,0);
end;
end;
@ -4151,7 +4148,6 @@ begin
end;
fMarkupManager.EndMarkup;
ReAllocMem(TokenAccu.p,0);
end;
procedure TCustomSynEdit.StartPaintBuffer(const ClipRect: TRect);

View File

@ -46,7 +46,7 @@ interface
uses
LCLProc, Graphics,
Classes, SysUtils, SynEditTextBase, SynEditTypes, SynEditMiscClasses,
Classes, SysUtils, LazSynEditText, SynEditTypes, SynEditMiscClasses,
SynEditMiscProcs, SynEditPointClasses,
SynEditHighlighter, SynEditHighlighterFoldBase;
@ -317,6 +317,19 @@ type
property FoldsAvailable: Boolean read GetFoldsAvailable;
end;
TSynEditFoldedView = class;
{ TLazSynDisplayFold }
TLazSynDisplayFold = class(TLazSynDisplayView)
private
FFoldView: TSynEditFoldedView;
public
constructor Create(AFoldView: TSynEditFoldedView);
procedure InitHighlighterTokens(AHighlighter: TSynCustomHighlighter); override;
procedure SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx); override;
end;
{ TSynTextFoldedView
*Line = Line (0-based) on Screen (except TopLine which should be TopViewPos)
*ViewPos = Line (1-based) in the array of viewable/visible lines
@ -325,7 +338,7 @@ type
{ TSynEditFoldedView }
TSynEditFoldedView = class // TODO: class(TSynEditStringsLinked)
TSynEditFoldedView = class
private
fCaret: TSynEditCaret;
FBlockSelection: TSynEditSelection;
@ -343,8 +356,10 @@ type
fNeedFixFrom, fNeedFixMinEnd : Integer;
fNeedCaretCheck : Boolean;
FInTopLineChanged: Boolean;
FDisplayView: TLazSynDisplayFold;
function GetCount : integer;
function GetDisplayView: TLazSynDisplayView;
function GetFoldClasifications(index : Integer): TFoldNodeClassifications;
function GetHighLighter: TSynCustomHighlighter;
function GetLines(index : Integer) : String;
@ -488,6 +503,8 @@ type
property HighLighter: TSynCustomHighlighter read GetHighLighter
write SetHighLighter;
property FoldProvider: TSynEditFoldProvider read FFoldProvider;
property DisplayView: TLazSynDisplayView read GetDisplayView;
end;
implementation
@ -626,6 +643,24 @@ begin
NumEncode86Values[NumEncode86Chars[i]] := i - 1;
end;
{ TLazSynDisplayFold }
constructor TLazSynDisplayFold.Create(AFoldView: TSynEditFoldedView);
begin
inherited Create;
FFoldView := AFoldView;
end;
procedure TLazSynDisplayFold.InitHighlighterTokens(AHighlighter: TSynCustomHighlighter);
begin
inherited InitHighlighterTokens(AHighlighter);
end;
procedure TLazSynDisplayFold.SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx);
begin
inherited SetHighlighterTokensLine(FFoldView.ViewPosToTextIndex(ALine + 1), ARealLine);
end;
{ TSynEditFoldExportStream }
constructor TSynEditFoldExportStream.Create;
@ -2828,6 +2863,7 @@ begin
fCaret.AddChangeHandler({$IFDEF FPC}@{$ENDIF}DoCaretChanged);
fFoldTree := TSynTextFoldAVLTree.Create;
FFoldProvider := TSynEditFoldProvider.Create(aTextView, fFoldTree);
FDisplayView := TLazSynDisplayFold.Create(Self);
FMarkupInfoFoldedCode := TSynSelectedColor.Create;
FMarkupInfoFoldedCode.Background := clNone;
@ -2845,6 +2881,7 @@ begin
fLines.RemoveNotifyHandler(senrCleared, {$IFDEF FPC}@{$ENDIF}LinesCleared);
fLines.RemoveEditHandler({$IFDEF FPC}@{$ENDIF}LineEdited);
fCaret.RemoveChangeHandler({$IFDEF FPC}@{$ENDIF}DoCaretChanged);
FreeAndNil(FDisplayView);
fFoldTree.Free;
fTextIndexList := nil;
fFoldTypeList := nil;
@ -2984,6 +3021,11 @@ begin
Result := fLines.Count - fFoldTree.FindLastFold.FoldedBefore;
end;
function TSynEditFoldedView.GetDisplayView: TLazSynDisplayView;
begin
Result := FDisplayView;
end;
function TSynEditFoldedView.GetFoldClasifications(index : Integer): TFoldNodeClassifications;
begin
if (index < -1) or (index > fLinesInWindow + 1) then exit([]);

View File

@ -11,7 +11,7 @@ unit SynEditMarks;
interface
uses
Classes, Controls, SysUtils, math, SynEditMiscClasses, SynEditTextBase, LCLProc;
Classes, Controls, SysUtils, math, SynEditMiscClasses, LazSynEditText, LCLProc;
type

View File

@ -26,7 +26,7 @@ unit SynEditMarkup;
interface
uses
Classes, SysUtils, Graphics, SynEditTypes, SynEditTextBase, SynEditPointClasses,
Classes, SysUtils, Graphics, SynEditTypes, LazSynEditText, SynEditPointClasses,
SynEditMiscClasses, SynEditMiscProcs, Controls, SynEditHighlighter, LCLProc;
type

View File

@ -27,7 +27,7 @@ interface
uses
Classes, SysUtils, Graphics, SynEditMarkup, SynEditMiscClasses,
SynEditMouseCmds, SynEditTextBase, Controls, LCLProc;
SynEditMouseCmds, LazSynEditText, Controls, LCLProc;
type

View File

@ -44,7 +44,7 @@ interface
uses
LCLIntf, LCLType, LCLProc,
Classes, Graphics, Controls, SysUtils, Clipbrd,
SynEditMiscProcs, SynEditTypes, SynEditTextBase, SynEditPointClasses;
SynEditMiscProcs, SynEditTypes, LazSynEditText, SynEditPointClasses;
type

View File

@ -40,7 +40,7 @@ uses
{$IFDEF SYN_MBCSSUPPORT}
Imm,
{$ENDIF}
SynEditTextBase, SynEditTypes, SynEditMiscProcs;//, SynEditTextBuffer;
LazSynEditText, SynEditTypes, SynEditMiscProcs;//, SynEditTextBuffer;
type

View File

@ -36,38 +36,6 @@ uses
Classes, SysUtils, LCLProc, SynEditMiscProcs, SynEditKeyCmds;
type
TSynEditStrings = class;
TStringListLineCountEvent = procedure(Sender: TSynEditStrings;
Index, Count: Integer) of object;
TStringListLineEditEvent = procedure(Sender: TSynEditStrings;
LinePos, BytePos, Count, LineBrkCnt: Integer;
Text: String) of object;
TSynEditNotifyReason = ( // TStringListLineCountEvent
senrLineCount, // Lines Inserted or Deleted (if not empty, they will trigger senrLineChange too)
senrLineChange, // Lines modified (also triggered by senrEditAction)
senrHighlightChanged, // used by Highlighter (invalidate and fold checks needed)
// TStringListLineEditEvent
senrEditAction, // EditInsert, EditDelete, EditLineBreak, ...
// TNotifyEvent
senrCleared,
senrUndoRedoAdded,
senrModifiedChanged, // The modified flag was changed
// Paintlocks are managed by SynEdit, but need distribution to shared edits
senrIncOwnedPaintLock, // Inform other SynEdits (ForeignPaintLock)
senrDecOwnedPaintLock,
senrIncPaintLock, // Actual PaintLock
senrDecPaintLock,
senrAfterIncPaintLock, // For plugins, etc...
senrBeforeDecPaintLock,
senrTextBufferChanging, // About to change
senrTextBufferChanged
);
TPhysicalCharWidths = Array of Shortint;
TPhysicalCharWidth = ShortInt;
PPhysicalCharWidth = ^TPhysicalCharWidth;
TSynEditUndoList = class;
TSynEditUndoItem = class;
@ -136,30 +104,6 @@ type
read GetStorageMems write SetStorageMems; default;
end;
{ TSynLogicalPhysicalConvertor }
const
SYN_LP_MIN_ALLOC = 1024; // Keep at least n*SizeOf(TPhysicalCharWidths) allocated
type
TSynLogicalPhysicalConvertor = class
private
FLines: TSynEditStrings;
FCurrentWidths: TPhysicalCharWidths;
FCurrentWidthsLen, FCurrentWidthsAlloc: Integer;
FCurrentLine: Integer;
FTextChangeStamp, FViewChangeStamp: Int64;
// TODOtab-width
procedure PrepareWidthsForLine(AIndex: Integer; AForce: Boolean = False);
public
constructor Create(ALines: TSynEditStrings);
destructor Destroy; override;
// Line is 0-based // Column is 1-based
function PhysicalToLogical(AIndex, AColumn: Integer): Integer;
function PhysicalToLogical(AIndex, AColumn: Integer; out AColOffset: Integer): Integer;
// ACharPos 1=before 1st char
function LogicalToPhysical(AIndex, ABytePos: Integer): Integer;
function LogicalToPhysical(AIndex, ABytePos: Integer; var AColOffset: Integer): Integer;
end;
{ TSynEditStringsBase }
TSynEditStringsBase = class(TStrings)
@ -173,190 +117,6 @@ type
property Ranges[Index: Pointer]: TSynManagedStorageMem read GetRange write PutRange;
end;
{ TSynEditStrings }
TSynEditStrings = class(TSynEditStringsBase)
private
FSenderUpdateCount: Integer;
FLogPhysConvertor :TSynLogicalPhysicalConvertor;
protected
FIsUtf8: Boolean;
function GetIsUtf8 : Boolean; virtual;
procedure SetIsUtf8(const AValue : Boolean); virtual;
function GetExpandedString(Index: integer): string; virtual; abstract;
function GetLengthOfLongestLine: integer; virtual; abstract;
procedure SetTextStr(const Value: string); override;
function GetTextChangeStamp: int64; virtual; abstract;
function GetViewChangeStamp: int64; virtual;
function GetIsInEditAction: Boolean; virtual; abstract;
procedure IncIsInEditAction; virtual; abstract;
procedure DecIsInEditAction; virtual; abstract;
function GetUndoList: TSynEditUndoList; virtual; abstract;
function GetRedoList: TSynEditUndoList; virtual; abstract;
function GetCurUndoList: TSynEditUndoList; virtual; abstract;
procedure SetIsUndoing(const AValue: Boolean); virtual; abstract;
function GetIsUndoing: Boolean; virtual; abstract;
procedure SetIsRedoing(const AValue: Boolean); virtual; abstract;
function GetIsRedoing: Boolean; virtual; abstract;
procedure IgnoreSendNotification(AReason: TSynEditNotifyReason;
ReEnable: Boolean); virtual; abstract;
procedure SetUpdateState(Updating: Boolean); override;
procedure SetUpdateState(Updating: Boolean; Sender: TObject); virtual; abstract;
procedure DoGetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer; PWidths: PPhysicalCharWidth); virtual; abstract;
public
constructor Create;
destructor Destroy; override;
procedure BeginUpdate(Sender: TObject); overload;
procedure EndUpdate(Sender: TObject); overload;
function IsUpdating: Boolean;
procedure DeleteLines(Index, NumLines: integer); virtual; abstract;
procedure InsertLines(Index, NumLines: integer); virtual; abstract;
procedure InsertStrings(Index: integer; NewStrings: TStrings); virtual; abstract;
procedure AddGenericHandler(AReason: TSynEditNotifyReason;
AHandler: TMethod); virtual; abstract;
procedure AddChangeHandler(AReason: TSynEditNotifyReason;
AHandler: TStringListLineCountEvent);
procedure AddNotifyHandler(AReason: TSynEditNotifyReason;
AHandler: TNotifyEvent);
procedure RemoveGenericHandler(AReason: TSynEditNotifyReason;
AHandler: TMethod); virtual; abstract;
procedure RemoveChangeHandler(AReason: TSynEditNotifyReason;
AHandler: TStringListLineCountEvent);
procedure RemoveNotifyHandler(AReason: TSynEditNotifyReason;
AHandler: TNotifyEvent);
procedure AddEditHandler(AHandler: TStringListLineEditEvent);
procedure RemoveEditHandler(AHandler: TStringListLineEditEvent);
procedure SendHighlightChanged(aIndex, aCount: Integer); override;
procedure SendNotification(AReason: TSynEditNotifyReason;
ASender: TSynEditStrings; aIndex, aCount: Integer;
aBytePos: Integer = -1; aLen: Integer = 0;
aTxt: String = ''); virtual; abstract;
procedure SendNotification(AReason: TSynEditNotifyReason;
ASender: TObject); virtual; abstract;
procedure FlushNotificationCache; virtual; abstract;
public
function GetPhysicalCharWidths(Index: Integer): TPhysicalCharWidths;
function GetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer): TPhysicalCharWidths;
// Byte to Char
function LogicalToPhysicalPos(const p: TPoint): TPoint;
function LogicalToPhysicalCol(const Line: String;
Index, LogicalPos: integer): integer; virtual;
// Char to Byte
function PhysicalToLogicalPos(const p: TPoint): TPoint;
function PhysicalToLogicalCol(const Line: string;
Index, PhysicalPos: integer): integer; virtual;
property LogPhysConvertor :TSynLogicalPhysicalConvertor read FLogPhysConvertor;
public
procedure EditInsert(LogX, LogY: Integer; AText: String); virtual; abstract;
function EditDelete(LogX, LogY, ByteLen: Integer): String; virtual; abstract;
procedure EditLineBreak(LogX, LogY: Integer); virtual; abstract;
procedure EditLineJoin(LogY: Integer; FillText: String = ''); virtual; abstract;
procedure EditLinesInsert(LogY, ACount: Integer; AText: String = ''); virtual; abstract;
procedure EditLinesDelete(LogY, ACount: Integer); virtual; abstract;
procedure EditUndo(Item: TSynEditUndoItem); virtual; abstract;
procedure EditRedo(Item: TSynEditUndoItem); virtual; abstract;
property IsInEditAction: Boolean read GetIsInEditAction;
property UndoList: TSynEditUndoList read GetUndoList;
property RedoList: TSynEditUndoList read GetRedoList;
property CurUndoList: TSynEditUndoList read GetCurUndoList; // Re or Undo (Redo while undoing)
property IsUndoing: Boolean read GetIsUndoing write SetIsUndoing;
property IsRedoing: Boolean read GetIsRedoing write SetIsRedoing;
public
property TextChangeStamp: int64 read GetTextChangeStamp;
property ViewChangeStamp: int64 read GetViewChangeStamp; // tabs-size, trailing-spaces, ...
property ExpandedStrings[Index: integer]: string read GetExpandedString;
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
property IsUtf8: Boolean read GetIsUtf8 write SetIsUtf8;
end;
{ TSynEditStringsLinked }
TSynEditStringsLinked = class(TSynEditStrings)
protected
fSynStrings: TSynEditStrings;
function GetIsUtf8 : Boolean; override;
procedure SetIsUtf8(const AValue : Boolean); override;
function GetTextChangeStamp: int64; override;
function GetViewChangeStamp: int64; override;
function GetRange(Index: Pointer): TSynManagedStorageMem; override;
procedure PutRange(Index: Pointer; const ARange: TSynManagedStorageMem); override;
function GetExpandedString(Index: integer): string; override;
function GetLengthOfLongestLine: integer; override;
procedure IgnoreSendNotification(AReason: TSynEditNotifyReason;
IncIgnore: Boolean); override;
function GetIsInEditAction: Boolean; override;
procedure IncIsInEditAction; override;
procedure DecIsInEditAction; override;
function GetUndoList: TSynEditUndoList; override;
function GetRedoList: TSynEditUndoList; override;
function GetCurUndoList: TSynEditUndoList; override;
procedure SetIsUndoing(const AValue: Boolean); override;
function GetIsUndoing: Boolean; override;
procedure SetIsRedoing(const AValue: Boolean); override;
function GetIsRedoing: Boolean; override;
protected
function GetCount: integer; override;
function GetCapacity: integer;
{$IFDEF SYN_COMPILER_3_UP} override; {$ELSE} virtual; {$ENDIF}
procedure SetCapacity(NewCapacity: integer);
{$IFDEF SYN_COMPILER_3_UP} override; {$ELSE} virtual; {$ENDIF}
function Get(Index: integer): string; override;
function GetObject(Index: integer): TObject; override;
procedure Put(Index: integer; const S: string); override;
procedure PutObject(Index: integer; AObject: TObject); override;
procedure SetUpdateState(Updating: Boolean; Sender: TObject); override;
procedure DoGetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer; PWidths: PPhysicalCharWidth); override;
public
constructor Create(ASynStringSource: TSynEditStrings);
function Add(const S: string): integer; override;
procedure AddStrings(AStrings: TStrings); override;
procedure Clear; override;
procedure Delete(Index: integer); override;
procedure DeleteLines(Index, NumLines: integer); override;
procedure Insert(Index: integer; const S: string); override;
procedure InsertLines(Index, NumLines: integer); override;
procedure InsertStrings(Index: integer; NewStrings: TStrings); override;
function GetPChar(ALineIndex: Integer; out ALen: Integer): PChar; override; // experimental
procedure AddGenericHandler(AReason: TSynEditNotifyReason;
AHandler: TMethod); override;
procedure RemoveGenericHandler(AReason: TSynEditNotifyReason;
AHandler: TMethod); override;
procedure SendNotification(AReason: TSynEditNotifyReason;
ASender: TSynEditStrings; aIndex, aCount: Integer;
aBytePos: Integer = -1; aLen: Integer = 0;
aTxt: String = ''); override;
procedure SendNotification(AReason: TSynEditNotifyReason;
ASender: TObject); override;
procedure FlushNotificationCache; override;
//function GetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer): TPhysicalCharWidths; override;
property NextLines: TSynEditStrings read fSynStrings write fSynStrings;
public
// LogX, LogY are 1-based
procedure EditInsert(LogX, LogY: Integer; AText: String); override;
function EditDelete(LogX, LogY, ByteLen: Integer): String; override;
procedure EditLineBreak(LogX, LogY: Integer); override;
procedure EditLineJoin(LogY: Integer; FillText: String = ''); override;
procedure EditLinesInsert(LogY, ACount: Integer; AText: String = ''); override;
procedure EditLinesDelete(LogY, ACount: Integer); override;
procedure EditUndo(Item: TSynEditUndoItem); override;
procedure EditRedo(Item: TSynEditUndoItem); override;
end;
{ TSynEditUndoItem }
TSynEditUndoItem = class(TObject)
@ -477,139 +237,6 @@ begin
raise ESynEditStorageMem.CreateFmt(SListIndexOutOfBounds, [Index]);
end;
{ TSynLogicalPhysicalConvertor }
procedure TSynLogicalPhysicalConvertor.PrepareWidthsForLine(AIndex: Integer;
AForce: Boolean);
var
LineLen: Integer;
Line: PChar;
//const dbg_cnt: integer = 0;
begin
if (not AForce) and (FCurrentLine = AIndex) and
(FLines.TextChangeStamp = FTextChangeStamp) and (FLines.ViewChangeStamp = FViewChangeStamp)
then begin
//debugln(['**************** RE-USING widths: ', AIndex,' (',dbgs(Pointer(self)),')']);
//dbg_cnt := dbg_cnt + 1;
exit;
end;
if (AIndex < 0) or (AIndex >= FLines.Count) then begin
FCurrentWidthsLen := 0;
FViewChangeStamp := FLines.ViewChangeStamp;
FTextChangeStamp := FLines.TextChangeStamp;
exit;
end;
Line := FLines.GetPChar(AIndex, LineLen);
if LineLen > FCurrentWidthsAlloc then begin
//debugln(['**************** COMPUTING widths (grow): ', AIndex,' (',dbgs(Pointer(self)),') old-alloc=', FCurrentWidthsAlloc, ' new-len=',LineLen]);
SetLength(FCurrentWidths, LineLen);
FCurrentWidthsAlloc := LineLen;
end
else if FCurrentWidthsAlloc > Max(Max(LineLen, FCurrentWidthsLen)*4, SYN_LP_MIN_ALLOC) then begin
//debugln(['**************** COMPUTING widths (shrink): ', AIndex,' (',dbgs(Pointer(self)),') old-alloc=', FCurrentWidthsAlloc, ' new-len=',LineLen]);
FCurrentWidthsAlloc := Max(Max(LineLen, FCurrentWidthsLen), SYN_LP_MIN_ALLOC) ;
SetLength(FCurrentWidths, FCurrentWidthsAlloc);
//end
//else begin
// debugln(['**************** COMPUTING widths: ', AIndex,' (',dbgs(Pointer(self)),') alloc=',FCurrentWidthsAlloc]);
end;
//debugln(['**************** NEW for index:: ', AIndex,' (',dbgs(Pointer(self)),') after index: ', FCurrentLine, ' used ', dbg_cnt,' times // old-alloc=', FCurrentWidthsAlloc, ' new-len=',LineLen, ' viewchg:',dbgs(not(FViewChangeStamp=FLines.ViewChangeStamp)),' txtchg:',dbgs(not(FTextChangeStamp=FLines.TextChangeStamp))]); dbg_cnt := 0;
FCurrentWidthsLen := LineLen;
if LineLen > 0 then
FLines.DoGetPhysicalCharWidths(Line, LineLen, AIndex, @FCurrentWidths[0]);
FViewChangeStamp := FLines.ViewChangeStamp;
FTextChangeStamp := FLines.TextChangeStamp;
FCurrentLine := AIndex;
end;
constructor TSynLogicalPhysicalConvertor.Create(ALines: TSynEditStrings);
begin
FLines := ALines;
FCurrentLine := -1;
FCurrentWidths := nil;
FCurrentWidthsLen := 0;
FCurrentWidthsAlloc := 0;
end;
destructor TSynLogicalPhysicalConvertor.Destroy;
begin
SetLength(FCurrentWidths, 0);
inherited Destroy;
end;
function TSynLogicalPhysicalConvertor.PhysicalToLogical(AIndex,
AColumn: Integer): Integer;
var
ColOffs: Integer;
begin
Result := PhysicalToLogical(AIndex, AColumn, ColOffs);
end;
function TSynLogicalPhysicalConvertor.PhysicalToLogical(AIndex, AColumn: Integer;
out AColOffset: Integer): Integer;
var
BytePos, ScreenPos, ScreenPosOld: integer;
begin
PrepareWidthsForLine(AIndex);
ScreenPos := 1;
BytePos := 0;
while BytePos < FCurrentWidthsLen do begin
ScreenPosOld := ScreenPos;
ScreenPos := ScreenPos + FCurrentWidths[BytePos];
inc(BytePos);
if ScreenPos > AColumn then begin
AColOffset := AColumn - ScreenPosOld;
exit(BytePos);
end;
end;
// Column at/past end of line
AColOffset := 0;
Result := BytePos + 1 + AColumn - ScreenPos;
end;
function TSynLogicalPhysicalConvertor.LogicalToPhysical(AIndex,
ABytePos: Integer): Integer;
var
ColOffs: Integer;
begin
ColOffs := 0;
Result := LogicalToPhysical(AIndex, ABytePos, ColOffs);
end;
function TSynLogicalPhysicalConvertor.LogicalToPhysical(AIndex, ABytePos: Integer;
var AColOffset: Integer): Integer;
var
i: integer;
CharWidths: TPhysicalCharWidths;
begin
{$IFDEF AssertSynMemIndex}
if (ABytePos <= 0) then
raise Exception.Create(Format('Bad Bytpos for PhystoLogical BytePos=%d ColOffs= %d idx= %d',[ABytePos, AColOffset, AIndex]));
{$ENDIF}
if (ABytePos = 0) or ((ABytePos = 1) and (AColOffset=0)) then
exit(ABytePos);
PrepareWidthsForLine(AIndex);
dec(ABytePos);
if ABytePos >= FCurrentWidthsLen then begin
Result := 1 + ABytePos - FCurrentWidthsLen;
ABytePos := FCurrentWidthsLen;
AColOffset := 0;
end
else begin
AColOffset := Min(AColOffset, FCurrentWidths[ABytePos]-1);
Result := 1 + AColOffset;
end;
for i := 0 to ABytePos - 1 do
Result := Result + FCurrentWidths[i];
end;
{ TSynEditStringsBase }
function TSynEditStringsBase.GetPChar(ALineIndex: Integer): PChar;
@ -619,501 +246,6 @@ begin
Result := GetPChar(ALineIndex, l);
end;
{ TSynEditStrings }
constructor TSynEditStrings.Create;
begin
FLogPhysConvertor := TSynLogicalPhysicalConvertor.Create(self);
inherited Create;
IsUtf8 := True;
end;
destructor TSynEditStrings.Destroy;
begin
FreeAndNil(FLogPhysConvertor);
inherited Destroy;
end;
procedure TSynEditStrings.BeginUpdate(Sender: TObject);
begin
if FSenderUpdateCount = 0 then
SetUpdateState(true, Sender);
inc(FSenderUpdateCount);
end;
procedure TSynEditStrings.EndUpdate(Sender: TObject);
begin
If FSenderUpdateCount>0 then
Dec(FSenderUpdateCount);
if FSenderUpdateCount=0 then
SetUpdateState(False, Sender);
end;
function TSynEditStrings.IsUpdating: Boolean;
begin
Result := (FSenderUpdateCount > 0) or (UpdateCount > 0);
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(senrEditAction, TMethod(AHandler));
end;
procedure TSynEditStrings.RemoveEditHandler(AHandler: TStringListLineEditEvent);
begin
RemoveGenericHandler(senrEditAction, TMethod(AHandler));
end;
procedure TSynEditStrings.SendHighlightChanged(aIndex, aCount: Integer);
begin
SendNotification(senrHighlightChanged, Self, aIndex, aCount);
end;
function TSynEditStrings.GetPhysicalCharWidths(Index: Integer): TPhysicalCharWidths;
var
s: string;
begin
s := Strings[Index];
Result := GetPhysicalCharWidths(PChar(s), length(s), Index);
end;
function TSynEditStrings.GetPhysicalCharWidths(Line: PChar; LineLen,
Index: Integer): TPhysicalCharWidths;
begin
SetLength(Result, LineLen);
if LineLen = 0 then
exit;
DoGetPhysicalCharWidths(Line, LineLen, Index, @Result[0]);
end;
function TSynEditStrings.GetIsUtf8 : Boolean;
begin
Result := FIsUtf8;
end;
procedure TSynEditStrings.SetIsUtf8(const AValue : Boolean);
begin
FIsUtf8 := AValue;
end;
procedure TSynEditStrings.SetTextStr(const Value : string);
var
StartPos: PChar;
p: PChar;
Last: PChar;
sl: TStringList;
s: string;
begin
if Value='' then begin
Clear;
exit;
end;
BeginUpdate;
sl:=TStringList.Create;
try
Clear;
p:=PChar(Value);
StartPos:=p;
Last:=p+length(Value);
while p<Last do begin
if not (p^ in [#10,#13]) then begin
inc(p);
end else begin
SetLength(s,p-StartPos);
if s<>'' then
System.Move(StartPos^,s[1],length(s));
sl.Add(s);
if (p[1] in [#10,#13]) and (p[1]<>p^) then
inc(p);
inc(p);
StartPos:=p;
end;
end;
if StartPos<Last then begin
SetLength(s,Last-StartPos);
if s<>'' then
System.Move(StartPos^,s[1],length(s));
sl.Add(s);
end;
AddStrings(sl);
finally
sl.Free;
EndUpdate;
end;
end;
function TSynEditStrings.GetViewChangeStamp: int64;
begin
Result := 0;
end;
procedure TSynEditStrings.SetUpdateState(Updating: Boolean);
begin
// Update/check "FSenderUpdateCount", to avoid extra locking/unlocking
if Updating then
BeginUpdate(nil)
else
EndUpdate(nil);
end;
function TSynEditStrings.LogicalToPhysicalPos(const p : TPoint) : TPoint;
begin
Result := p;
Result.X := FLogPhysConvertor.LogicalToPhysical(p.y - 1, p.x);
// if Result.Y - 1 < Count then
// Result.X:=LogicalToPhysicalCol(self[Result.Y - 1], Result.Y, Result.X);
end;
function TSynEditStrings.LogicalToPhysicalCol(const Line : String;
Index, LogicalPos: integer) : integer;
var
i, ByteLen: integer;
CharWidths: TPhysicalCharWidths;
begin
CharWidths := GetPhysicalCharWidths(Pchar(Line), length(Line), Index);
ByteLen := length(Line);
dec(LogicalPos);
if LogicalPos > ByteLen then begin
Result := 1 + LogicalPos - ByteLen;
LogicalPos := ByteLen;
end
else
Result := 1;
for i := 0 to LogicalPos - 1 do
Result := Result + CharWidths[i];
end;
function TSynEditStrings.PhysicalToLogicalPos(const p : TPoint) : TPoint;
begin
Result := p;
Result.X := FLogPhysConvertor.PhysicalToLogical(p.y - 1, p.x);
// if (Result.Y>=1) and (Result.Y <= Count) then
// Result.X:=PhysicalToLogicalCol(self[Result.Y - 1], Result.Y - 1, Result.X);
end;
function TSynEditStrings.PhysicalToLogicalCol(const Line : string;
Index, PhysicalPos : integer) : integer;
var
BytePos, ByteLen: integer;
ScreenPos: integer;
CharWidths: TPhysicalCharWidths;
begin
CharWidths := GetPhysicalCharWidths(PChar(Line), length(Line), Index);
ByteLen := Length(Line);
ScreenPos := 1;
BytePos := 0;
while BytePos < ByteLen do begin
if ScreenPos + CharWidths[BytePos] > PhysicalPos then
exit(BytePos+1);
ScreenPos := ScreenPos + CharWidths[BytePos];
inc(BytePos);
end;
Result := BytePos + 1 + PhysicalPos - ScreenPos;
end;
{ TSynEditStringsLinked }
constructor TSynEditStringsLinked.Create(ASynStringSource: TSynEditStrings);
begin
fSynStrings := ASynStringSource;
Inherited Create;
end;
function TSynEditStringsLinked.Add(const S: string): integer;
begin
Result := fSynStrings.Add(S);
end;
procedure TSynEditStringsLinked.AddStrings(AStrings: TStrings);
begin
fSynStrings.AddStrings(AStrings);
end;
procedure TSynEditStringsLinked.Clear;
begin
fSynStrings.Clear;
end;
procedure TSynEditStringsLinked.Delete(Index: integer);
begin
fSynStrings.Delete(Index);
end;
procedure TSynEditStringsLinked.DeleteLines(Index, NumLines: integer);
begin
fSynStrings.DeleteLines(Index, NumLines);
end;
procedure TSynEditStringsLinked.Insert(Index: integer; const S: string);
begin
fSynStrings.Insert(Index, S);
end;
procedure TSynEditStringsLinked.InsertLines(Index, NumLines: integer);
begin
fSynStrings.InsertLines(Index, NumLines);
end;
procedure TSynEditStringsLinked.InsertStrings(Index: integer; NewStrings: TStrings);
begin
fSynStrings.InsertStrings(Index, NewStrings);
end;
function TSynEditStringsLinked.GetPChar(ALineIndex: Integer; out ALen: Integer): PChar;
begin
Result := fSynStrings.GetPChar(ALineIndex, ALen);
end;
procedure TSynEditStringsLinked.SetIsUndoing(const AValue: Boolean);
begin
fSynStrings.IsUndoing := AValue;
end;
function TSynEditStringsLinked.GetIsUndoing: Boolean;
begin
Result := fSynStrings.IsUndoing;
end;
procedure TSynEditStringsLinked.SetIsRedoing(const AValue: Boolean);
begin
fSynStrings.IsRedoing := AValue;
end;
function TSynEditStringsLinked.GetIsRedoing: Boolean;
begin
Result := fSynStrings.IsRedoing;
end;
function TSynEditStringsLinked.GetIsUtf8: Boolean;
begin
Result := FSynStrings.IsUtf8;
end;
procedure TSynEditStringsLinked.SetIsUtf8(const AValue: Boolean);
begin
FSynStrings.IsUtf8 := AValue;
end;
function TSynEditStringsLinked.GetTextChangeStamp: int64;
begin
Result := fSynStrings.GetTextChangeStamp;
end;
function TSynEditStringsLinked.GetViewChangeStamp: int64;
begin
Result := fSynStrings.GetViewChangeStamp;
end;
//Ranges
function TSynEditStringsLinked.GetRange(Index: Pointer): TSynManagedStorageMem;
begin
Result:= fSynStrings.Ranges[Index];
end;
procedure TSynEditStringsLinked.PutRange(Index: Pointer; const ARange: TSynManagedStorageMem);
begin
fSynStrings.Ranges[Index] := ARange;
end;
function TSynEditStringsLinked.GetExpandedString(Index: integer): string;
begin
Result:= fSynStrings.GetExpandedString(Index);
end;
function TSynEditStringsLinked.GetLengthOfLongestLine: integer;
begin
Result:= fSynStrings.GetLengthOfLongestLine;
end;
function TSynEditStringsLinked.GetRedoList: TSynEditUndoList;
begin
Result := fSynStrings.GetRedoList;
end;
function TSynEditStringsLinked.GetUndoList: TSynEditUndoList;
begin
Result := fSynStrings.GetUndoList;
end;
function TSynEditStringsLinked.GetCurUndoList: TSynEditUndoList;
begin
Result := fSynStrings.GetCurUndoList;
end;
procedure TSynEditStringsLinked.AddGenericHandler(AReason: TSynEditNotifyReason; AHandler: TMethod);
begin
fSynStrings.AddGenericHandler(AReason, AHandler);
end;
procedure TSynEditStringsLinked.RemoveGenericHandler(AReason: TSynEditNotifyReason; AHandler: TMethod);
begin
fSynStrings.RemoveGenericHandler(AReason, AHandler);
end;
// Count
function TSynEditStringsLinked.GetCount: integer;
begin
Result:= fSynStrings.Count;
end;
function TSynEditStringsLinked.GetCapacity: integer;
begin
Result:= fSynStrings.Capacity;
end;
procedure TSynEditStringsLinked.SetCapacity(NewCapacity: integer);
begin
fSynStrings.Capacity := NewCapacity;
end;
function TSynEditStringsLinked.Get(Index: integer): string;
begin
Result:= fSynStrings.Get(Index);
end;
function TSynEditStringsLinked.GetObject(Index: integer): TObject;
begin
Result:= fSynStrings.GetObject(Index);
end;
procedure TSynEditStringsLinked.Put(Index: integer; const S: string);
begin
fSynStrings.Put(Index, S);
end;
procedure TSynEditStringsLinked.PutObject(Index: integer; AObject: TObject);
begin
fSynStrings.PutObject(Index, AObject);
end;
//function TSynEditStringsLinked.GetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer): TPhysicalCharWidths;
//begin
// Result := fSynStrings.GetPhysicalCharWidths(Line, LineLen, Index);
//end;
procedure TSynEditStringsLinked.SetUpdateState(Updating: Boolean; Sender: TObject);
begin
// Update/check "FSenderUpdateCount" in linked lists too (avoid extra locking/unlocking)
if Updating then
fSynStrings.BeginUpdate(Sender)
else
fSynStrings.EndUpdate(Sender);
end;
procedure TSynEditStringsLinked.DoGetPhysicalCharWidths(Line: PChar;
LineLen, Index: Integer; PWidths: PPhysicalCharWidth);
begin
fSynStrings.DoGetPhysicalCharWidths(Line, LineLen, Index, PWidths);
end;
procedure TSynEditStringsLinked.EditInsert(LogX, LogY: Integer; AText: String);
begin
fSynStrings.EditInsert(LogX, LogY, AText);
end;
function TSynEditStringsLinked.EditDelete(LogX, LogY, ByteLen: Integer): String;
begin
Result := fSynStrings.EditDelete(LogX, LogY, ByteLen);
end;
procedure TSynEditStringsLinked.EditLineBreak(LogX, LogY: Integer);
begin
fSynStrings.EditLineBreak(LogX, LogY);
end;
procedure TSynEditStringsLinked.EditLineJoin(LogY: Integer;
FillText: String = '');
begin
fSynStrings.EditLineJoin(LogY, FillText);
end;
procedure TSynEditStringsLinked.EditLinesInsert(LogY, ACount: Integer; AText: String = '');
begin
fSynStrings.EditLinesInsert(LogY, ACount, AText);
end;
procedure TSynEditStringsLinked.EditLinesDelete(LogY, ACount: Integer);
begin
fSynStrings.EditLinesDelete(LogY, ACount);
end;
procedure TSynEditStringsLinked.EditUndo(Item: TSynEditUndoItem);
begin
fSynStrings.EditUndo(Item);
end;
procedure TSynEditStringsLinked.EditRedo(Item: TSynEditUndoItem);
begin
fSynStrings.EditRedo(Item);
end;
procedure TSynEditStringsLinked.SendNotification(AReason: TSynEditNotifyReason;
ASender: TSynEditStrings; aIndex, aCount: Integer;
aBytePos: Integer = -1; aLen: Integer = 0; aTxt: String = '');
begin
fSynStrings.SendNotification(AReason, ASender, aIndex, aCount, aBytePos, aLen, aTxt);
end;
procedure TSynEditStringsLinked.SendNotification(AReason: TSynEditNotifyReason;
ASender: TObject);
begin
fSynStrings.SendNotification(AReason, ASender);
end;
procedure TSynEditStringsLinked.FlushNotificationCache;
begin
fSynStrings.FlushNotificationCache;
end;
procedure TSynEditStringsLinked.IgnoreSendNotification(AReason: TSynEditNotifyReason;
IncIgnore: Boolean);
begin
fSynStrings.IgnoreSendNotification(AReason, IncIgnore);
end;
function TSynEditStringsLinked.GetIsInEditAction: Boolean;
begin
Result := fSynStrings.GetIsInEditAction;
end;
procedure TSynEditStringsLinked.IncIsInEditAction;
begin
fSynStrings.IncIsInEditAction;
end;
procedure TSynEditStringsLinked.DecIsInEditAction;
begin
fSynStrings.DecIsInEditAction;
end;
{ TSynEditUndoList }
constructor TSynEditUndoList.Create;

View File

@ -39,11 +39,16 @@ unit SynEditTextBuffer;
{$I synedit.inc}
{$IFOPT C+}
{$DEFINE SynAssert}
{$ENDIF}
interface
uses
Classes, SysUtils, LCLProc, LCLIntf, LCLType,
SynEditTextBase, SynEditMiscProcs, SynEditMiscClasses;
Classes, SysUtils, Graphics, LCLProc, LCLIntf, LCLType,
SynEditTypes, LazSynEditText, SynEditTextBase, SynEditMiscProcs, SynEditMiscClasses,
SynEditHighlighter;
type
TSynEditFlagsClass = class end; // For Register
@ -103,11 +108,29 @@ type
property Flags[Index: Integer]: TSynEditStringFlags read GetFlags write SetFlags;
end;
TSynEditStringList = class;
{ TLazSynDisplayBuffer }
TLazSynDisplayBuffer = class(TLazSynDisplayViewEx)
private
FBuffer: TSynEditStringList;
FAtLineStart: Boolean;
public
constructor Create(ABuffer: TSynEditStringList);
procedure SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx); override;
function GetNextHighlighterToken(out ATokenStart: PChar; out ATokenLength: integer;
out ATokenAttr: TSynHighlighterAttributes
): Boolean; override;
function GetDrawDividerInfo: TSynDividerDrawConfigSetting; override;
end;
{ TSynEditStringList }
TSynEditStringList = class(TSynEditStrings)
private
FList: TSynEditStringMemory;
FDisplayView: TLazSynDisplayBuffer;
FAttachedSynEditList: TFPList;
FNotifyLists: Array [TSynEditNotifyReason] of TSynMethodList;
@ -170,6 +193,8 @@ type
procedure UndoEditLinesDelete(LogY, ACount: Integer);
procedure IncreaseTextChangeStamp;
procedure DoGetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer; PWidths: PPhysicalCharWidth); override;
function GetDisplayView: TLazSynDisplayView; override;
public
constructor Create;
destructor Destroy; override;
@ -312,8 +337,59 @@ type
function PerformUndo(Caller: TObject): Boolean; override;
end;
{ TLazSynDisplayBuffer }
constructor TLazSynDisplayBuffer.Create(ABuffer: TSynEditStringList);
begin
inherited Create;
FBuffer := ABuffer;
end;
procedure TLazSynDisplayBuffer.SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx);
begin
CurrentTokenLine := ALine;
ARealLine := ALine;
FAtLineStart := True;
end;
function TLazSynDisplayBuffer.GetNextHighlighterToken(out ATokenStart: PChar; out
ATokenLength: integer; out ATokenAttr: TSynHighlighterAttributes): Boolean;
begin
Result := False;
if not Initialized then exit;
if CurrentTokenHighlighter = nil then begin
Result := FAtLineStart;
if not Result then exit;
ATokenStart := FBuffer.GetPChar(CurrentTokenLine, ATokenLength);
ATokenAttr := nil;
FAtLineStart := False;
end
else begin
if FAtLineStart then
CurrentTokenHighlighter.StartAtLineIndex(CurrentTokenLine);
FAtLineStart := False;
Result := not CurrentTokenHighlighter.GetEol;
if not Result then exit;
CurrentTokenHighlighter.GetTokenEx(ATokenStart, ATokenLength);
ATokenAttr := CurrentTokenHighlighter.GetTokenAttribute;
CurrentTokenHighlighter.Next;
end;
end;
function TLazSynDisplayBuffer.GetDrawDividerInfo: TSynDividerDrawConfigSetting;
begin
if CurrentTokenHighlighter <> nil then
Result := CurrentTokenHighlighter.DrawDivider[CurrentTokenLine]
else
Result.Color := clNone;
end;
{ TSynEditUndoTxtInsert }
function TSynEditUndoTxtInsert.DebugString: String;
function TSynEditUndoTxtInsert.DebugString: String;
begin
Result := 'X='+dbgs(FPosX) + ' Y='+ dbgs(FPosY) + ' len=' + dbgs(FLen);
end;
@ -452,6 +528,7 @@ var
r: TSynEditNotifyReason;
begin
fList := TSynEditStringMemory.Create;
FDisplayView := TLazSynDisplayBuffer.Create(Self);
FAttachedSynEditList := TFPList.Create;
FUndoList := TSynEditUndoList.Create;
@ -495,6 +572,7 @@ begin
FreeAndNil(FRedoList);
FreeAndNil(FAttachedSynEditList);
FreeAndNil(FDisplayView);
FreeAndNil(fList);
end;
@ -748,6 +826,11 @@ begin
end;
end;
function TSynEditStringList.GetDisplayView: TLazSynDisplayView;
begin
Result := FDisplayView;
end;
procedure TSynEditStringList.AttachSynEdit(AEdit: TSynEditBase);
begin
if FAttachedSynEditList.IndexOf(AEdit) < 0 then

View File

@ -33,7 +33,7 @@ unit SynEditTextDoubleWidthChars;
interface
uses
Classes, SysUtils, SynEditTextBase;
Classes, SysUtils, LazSynEditText;
type

View File

@ -26,7 +26,7 @@ unit SynEditTextTabExpander;
interface
uses
LCLProc, Classes, SysUtils, SynEditTextBase;
LCLProc, Classes, SysUtils, LazSynEditText, SynEditTextBase;
type

View File

@ -28,7 +28,7 @@ interface
uses
LCLProc,
Classes, SysUtils, SynEditTextBase,
Classes, SysUtils, LazSynEditText, SynEditTextBase, SynEditTypes, SynEditHighlighter,
SynEditPointClasses, SynEditMiscProcs;
type
@ -36,6 +36,24 @@ type
TSynEditStringTrimmingType = (settLeaveLine, settEditLine, settMoveCaret,
settIgnoreAll);
TSynEditStringTrimmingList = class;
{ TLazSynDisplayTrim }
TLazSynDisplayTrim = class(TLazSynDisplayViewEx)
private
FTrimer: TSynEditStringTrimmingList;
FTempLineStringForPChar: String;
FAtLineStart: Boolean;
public
constructor Create(ATrimer: TSynEditStringTrimmingList);
procedure FinishHighlighterTokens; override;
procedure SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx); override;
function GetNextHighlighterToken(out ATokenStart: PChar; out ATokenLength: integer;
out ATokenAttr: TSynHighlighterAttributes
): Boolean; override;
end;
{ TSynEditStringTrimmingList }
TSynEditStringTrimmingList = class(TSynEditStringsLinked)
@ -53,6 +71,7 @@ type
FLineEdited: Boolean;
FTempLineStringForPChar: String; // experimental; used by GetPChar;
FViewChangeStamp: int64;
FDisplayView: TLazSynDisplayTrim;
procedure DoCaretChanged(Sender : TObject);
procedure ListCleared(Sender: TObject);
Procedure LinesChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
@ -79,6 +98,7 @@ type
procedure Put(Index: integer; const S: string); override;
procedure PutObject(Index: integer; AObject: TObject); override;
function GetPCharSpaces(ALineIndex: Integer; out ALen: Integer): PChar; // experimental
function GetDisplayView: TLazSynDisplayView; override;
public
constructor Create(ASynStringSource: TSynEditStrings; ACaret: TSynEditCaret);
destructor Destroy; override;
@ -184,6 +204,48 @@ type
function PerformUndo(Caller: TObject): Boolean; override;
end;
{ TLazSynDisplayTrim }
constructor TLazSynDisplayTrim.Create(ATrimer: TSynEditStringTrimmingList);
begin
inherited Create;
FTrimer := ATrimer;
end;
procedure TLazSynDisplayTrim.FinishHighlighterTokens;
begin
inherited FinishHighlighterTokens;
FTempLineStringForPChar := '';
end;
procedure TLazSynDisplayTrim.SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx);
begin
CurrentTokenLine := ALine;
FAtLineStart := True;
inherited SetHighlighterTokensLine(ALine, ARealLine);
end;
function TLazSynDisplayTrim.GetNextHighlighterToken(out ATokenStart: PChar; out
ATokenLength: integer; out ATokenAttr: TSynHighlighterAttributes): Boolean;
begin
Result := False;
if not Initialized then exit;
if (CurrentTokenHighlighter = nil) and (FTrimer.Spaces(CurrentTokenLine) <> '') then begin
Result := FAtLineStart;
if not Result then exit;
FTempLineStringForPChar := FTrimer[CurrentTokenLine];
ATokenStart := PChar(FTempLineStringForPChar);
ATokenLength := length(FTempLineStringForPChar);
ATokenAttr := nil;
FAtLineStart := False;
end;
// highlighter currently includes trimed spaces
Result := inherited GetNextHighlighterToken(ATokenStart, ATokenLength, ATokenAttr);
end;
{ TSynEditUndoTrimMoveTo }
function TSynEditUndoTrimMoveTo.DebugString: String;
@ -344,6 +406,8 @@ begin
fCaret := ACaret;
fCaret.AddChangeHandler(@DoCaretChanged);
fLockList := TStringList.Create;
FDisplayView := TLazSynDisplayTrim.Create(Self);
FDisplayView.NextView := ASynStringSource.DisplayView;
fLineIndex:= -1;
fSpaces := '';
fEnabled:=false;
@ -363,6 +427,7 @@ begin
fSynStrings.RemoveChangeHandler(senrLineChange, {$IFDEF FPC}@{$ENDIF}LinesChanged);
fSynStrings.RemoveNotifyHandler(senrCleared, {$IFDEF FPC}@{$ENDIF}ListCleared);
fCaret.RemoveChangeHandler(@DoCaretChanged);
FreeAndNil(FDisplayView);
FreeAndNil(fLockList);
inherited Destroy;
end;
@ -740,6 +805,11 @@ begin
Result := PChar(FTempLineStringForPChar);
end;
function TSynEditStringTrimmingList.GetDisplayView: TLazSynDisplayView;
begin
Result := FDisplayView;
end;
function TSynEditStringTrimmingList.GetPChar(ALineIndex: Integer; out ALen: Integer): PChar;
begin
Result := inherited GetPChar(ALineIndex, ALen);

View File

@ -55,6 +55,9 @@ type
TSynIdentChars = set of char;
TLinePos = type integer; // 1..high(Integer);
TLineIdx = type integer; // 0..high(Integer);
{$IFDEF SYN_LAZARUS}
// NOTE: the note below is not valid for the LCL which uses UTF-8
{$ELSE}

View File

@ -6,7 +6,7 @@ interface
uses
Classes, SysUtils, Graphics, LCLType, LCLIntf, SynGutterBase,
SynEditMiscProcs, SynTextDrawer, SynEditMouseCmds, SynEditTextBuffer, SynEditTextBase;
SynEditMiscProcs, SynTextDrawer, SynEditMouseCmds, SynEditTextBuffer, LazSynEditText;
type

View File

@ -28,7 +28,7 @@ interface
uses
Classes, Graphics, Controls, LCLProc, LCLType, LCLIntf, FPCanvas, sysutils, math,
SynGutterBase, SynEditTypes, SynEditTextBase, SynEditTextBuffer, SynEditMarks,
SynGutterBase, SynEditTypes, LazSynEditText, SynEditTextBuffer, SynEditMarks,
SynEditMiscClasses;
type

View File

@ -27,7 +27,7 @@ interface
uses
Classes, Controls, SysUtils, math, LCLProc, Forms, Graphics, SynEditMiscClasses,
LCLType, SynEdit, SynPluginSyncronizedEditBase, SynEditTextBase, SynEditMiscProcs,
LCLType, SynEdit, SynPluginSyncronizedEditBase, LazSynEditText, SynEditMiscProcs,
SynEditMouseCmds, SynEditKeyCmds, SynEditTypes, LCLIntf;
type

View File

@ -26,8 +26,8 @@ unit SynPluginSyncronizedEditBase;
interface
uses
Classes, SysUtils, math, Graphics, LCLProc,
SynEditMiscClasses, SynEdit, SynEditMarkup, SynEditMiscProcs, SynEditTextBase,
Classes, SysUtils, math, Graphics, LCLProc, SynEditTextBase,
SynEditMiscClasses, SynEdit, SynEditMarkup, SynEditMiscProcs, LazSynEditText,
SynEditTextTrimmer, SynEditKeyCmds;
type

View File

@ -28,7 +28,7 @@ interface
uses
Classes, SysUtils, math, Graphics, LCLType, SynEditMiscClasses,
SynPluginSyncronizedEditBase, SynEditKeyCmds, SynEdit, SynEditMiscProcs,
SynEditTextBase, LCLProc;
LazSynEditText, LCLProc;
type

View File

@ -51,7 +51,7 @@ uses
SynEditLines, SynEditStrConst, SynEditTypes, SynEdit, SynRegExpr,
SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion,
SynEditMiscClasses, SynEditMarkupHighAll, SynEditMarks,
SynBeautifier, SynEditTextBase,
SynBeautifier, SynEditTextBase, LazSynEditText,
SynPluginSyncronizedEditBase, SourceSynEditor,
// Intf
SrcEditorIntf, MenuIntf, LazIDEIntf, PackageIntf, IDEHelpIntf, IDEImagesIntf,

View File

@ -41,7 +41,7 @@ uses
SynEdit, SynEditMiscClasses, SynGutter, SynGutterBase, SynEditMarks,
SynGutterLineNumber, SynGutterCodeFolding, SynGutterMarks, SynGutterChanges,
SynGutterLineOverview, SynEditMarkup, SynEditMarkupGutterMark,
SynEditTextBuffer, SynEditFoldedView, SynTextDrawer, SynEditTextBase,
SynEditTextBuffer, SynEditFoldedView, SynTextDrawer, SynEditTextBase, LazSynEditText,
SynPluginTemplateEdit, SynPluginSyncroEdit,
SynEditHighlighter, SynEditHighlighterFoldBase, SynHighlighterPas;