mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 21:18:01 +02:00
SynEdit: refactor painting
git-svn-id: trunk@34165 -
This commit is contained in:
parent
21848dbdaa
commit
400f05dee0
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -25,7 +25,7 @@ uses
|
||||
SynMacroRecorder, SynMemo, SynPluginSyncroEdit, SynPluginSyncronizedEditBase,
|
||||
SynPluginTemplateEdit, SynPropertyEditObjectList, SynRegExpr, SynTextDrawer,
|
||||
SynEditMarkupGutterMark, SynHighlighterBat, SynHighlighterIni, SynEditMarkupSpecialChar,
|
||||
LazarusPackageIntf;
|
||||
LazSynEditText, LazarusPackageIntf;
|
||||
|
||||
implementation
|
||||
|
||||
|
1072
components/synedit/lazsynedittext.pas
Normal file
1072
components/synedit/lazsynedittext.pas
Normal file
File diff suppressed because it is too large
Load Diff
@ -40,7 +40,7 @@ unit SynBeautifier;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, LCLProc, SynEditMiscClasses, SynEditTextBase, SynEditPointClasses,
|
||||
Classes, SysUtils, LCLProc, SynEditMiscClasses, LazSynEditText, SynEditPointClasses,
|
||||
SynEditKeyCmds;
|
||||
|
||||
type
|
||||
|
@ -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);
|
||||
|
@ -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([]);
|
||||
|
@ -11,7 +11,7 @@ unit SynEditMarks;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, Controls, SysUtils, math, SynEditMiscClasses, SynEditTextBase, LCLProc;
|
||||
Classes, Controls, SysUtils, math, SynEditMiscClasses, LazSynEditText, LCLProc;
|
||||
|
||||
type
|
||||
|
||||
|
@ -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
|
||||
|
@ -27,7 +27,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Graphics, SynEditMarkup, SynEditMiscClasses,
|
||||
SynEditMouseCmds, SynEditTextBase, Controls, LCLProc;
|
||||
SynEditMouseCmds, LazSynEditText, Controls, LCLProc;
|
||||
|
||||
type
|
||||
|
||||
|
@ -44,7 +44,7 @@ interface
|
||||
uses
|
||||
LCLIntf, LCLType, LCLProc,
|
||||
Classes, Graphics, Controls, SysUtils, Clipbrd,
|
||||
SynEditMiscProcs, SynEditTypes, SynEditTextBase, SynEditPointClasses;
|
||||
SynEditMiscProcs, SynEditTypes, LazSynEditText, SynEditPointClasses;
|
||||
|
||||
type
|
||||
|
||||
|
@ -40,7 +40,7 @@ uses
|
||||
{$IFDEF SYN_MBCSSUPPORT}
|
||||
Imm,
|
||||
{$ENDIF}
|
||||
SynEditTextBase, SynEditTypes, SynEditMiscProcs;//, SynEditTextBuffer;
|
||||
LazSynEditText, SynEditTypes, SynEditMiscProcs;//, SynEditTextBuffer;
|
||||
|
||||
type
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -33,7 +33,7 @@ unit SynEditTextDoubleWidthChars;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, SynEditTextBase;
|
||||
Classes, SysUtils, LazSynEditText;
|
||||
|
||||
type
|
||||
|
||||
|
@ -26,7 +26,7 @@ unit SynEditTextTabExpander;
|
||||
interface
|
||||
|
||||
uses
|
||||
LCLProc, Classes, SysUtils, SynEditTextBase;
|
||||
LCLProc, Classes, SysUtils, LazSynEditText, SynEditTextBase;
|
||||
|
||||
type
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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}
|
||||
|
@ -6,7 +6,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Graphics, LCLType, LCLIntf, SynGutterBase,
|
||||
SynEditMiscProcs, SynTextDrawer, SynEditMouseCmds, SynEditTextBuffer, SynEditTextBase;
|
||||
SynEditMiscProcs, SynTextDrawer, SynEditMouseCmds, SynEditTextBuffer, LazSynEditText;
|
||||
|
||||
type
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -28,7 +28,7 @@ interface
|
||||
uses
|
||||
Classes, SysUtils, math, Graphics, LCLType, SynEditMiscClasses,
|
||||
SynPluginSyncronizedEditBase, SynEditKeyCmds, SynEdit, SynEditMiscProcs,
|
||||
SynEditTextBase, LCLProc;
|
||||
LazSynEditText, LCLProc;
|
||||
|
||||
type
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user