mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-03 02:59:51 +01:00
SynEdit: Refactor Line-Viewers, Add LineViewer for tab-expansion
git-svn-id: trunk@18110 -
This commit is contained in:
parent
98372de302
commit
4849ad30c1
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -1428,6 +1428,7 @@ components/synedit/syneditsearch.pp svneol=native#text/pascal
|
||||
components/synedit/syneditstrconst.pp svneol=native#text/pascal
|
||||
components/synedit/synedittextbase.pas svneol=native#text/plain
|
||||
components/synedit/synedittextbuffer.pp svneol=native#text/pascal
|
||||
components/synedit/synedittexttabexpander.pas svneol=native#text/plain
|
||||
components/synedit/synedittexttrimmer.pas svneol=native#text/plain
|
||||
components/synedit/synedittypes.pp svneol=native#text/pascal
|
||||
components/synedit/synexporthtml.pas svneol=native#text/pascal
|
||||
|
||||
@ -77,7 +77,7 @@ uses
|
||||
{$ifdef SYN_LAZARUS}
|
||||
SynEditMarkup, SynEditMarkupHighAll, SynEditMarkupBracket,
|
||||
SynEditMarkupCtrlMouseLink, SynEditMarkupSpecialLine, SynEditMarkupSelection,
|
||||
SynEditTextBase, SynEditTextTrimmer, SynEditFoldedView,
|
||||
SynEditTextBase, SynEditTextTrimmer, SynEditFoldedView, SynEditTextTabExpander,
|
||||
SynGutter,
|
||||
{$ENDIF}
|
||||
SynEditMiscClasses, SynEditTextBuffer, SynEditHighlighter, SynTextDrawer;
|
||||
@ -370,10 +370,12 @@ type
|
||||
fHighlighterNeedsUpdateEndLine: integer; // 1 based, 0 means invalid
|
||||
fBeautifier: TSynCustomBeautifier;
|
||||
fExtraCharSpacing: integer;
|
||||
fTextView : TSynEditFoldedView;
|
||||
fTrimLines: TStrings; //TSynEditStringTrimmingList;
|
||||
{$ENDIF}
|
||||
fLines: TStrings;
|
||||
FFoldedLinesView: TSynEditFoldedView;
|
||||
FTrimmedLinesView: TSynEditStringTrimmingList;
|
||||
FTabbedLinesView: TSynEditStringTabExpander;
|
||||
FTheLinesView: TStrings;
|
||||
fLines: TStrings; // The real (un-mapped) line-buffer
|
||||
fLinesInWindow: Integer;// MG: fully visible lines in window
|
||||
fLeftChar: Integer; // first visible screen column
|
||||
fMaxLeftChar: Integer; // 1024
|
||||
@ -706,7 +708,7 @@ type
|
||||
function GetSelStart: integer;
|
||||
procedure SetSelEnd(const Value: integer);
|
||||
procedure SetSelStart(const Value: integer);
|
||||
property TextView : TSynEditFoldedView read fTextView;
|
||||
property TextView : TSynEditFoldedView read FFoldedLinesView;
|
||||
property TopView: Integer read GetTopView write SetTopView; // TopLine converted into Visible(View) lines
|
||||
{$ENDIF}
|
||||
public
|
||||
@ -873,8 +875,8 @@ type
|
||||
property LinesInWindow: Integer read fLinesInWindow; // MG: fully visible lines
|
||||
property LineText: string read GetLineText write SetLineText;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
property RealLines: TStrings read fLines write SetRealLines; // No trailing (trimmable) spaces
|
||||
property Lines: TStrings read fTrimLines write SetLines;
|
||||
property RealLines: TStrings read FLines write SetRealLines; // No trailing (trimmable) spaces
|
||||
property Lines: TStrings read FTheLinesView write SetLines;
|
||||
{$ELSE}
|
||||
property Lines: TStrings read fLines write SetLines;
|
||||
{$ENDIF}
|
||||
@ -1247,8 +1249,8 @@ function TCustomSynEdit.ScreenRowToRow(ScreenRow: integer): integer;
|
||||
// ScreenRow is 0-base
|
||||
// result is 1-based
|
||||
begin
|
||||
Result := fTextView.ScreenLineToTextIndex(ScreenRow)+1;
|
||||
// DebugLn(['=== SrceenRow TO Row In:',ScreenRow,' out:',Result, ' topline=',TopLine, ' view topline=',fTextView.TopLine]);
|
||||
Result := FFoldedLinesView.ScreenLineToTextIndex(ScreenRow)+1;
|
||||
// DebugLn(['=== SrceenRow TO Row In:',ScreenRow,' out:',Result, ' topline=',TopLine, ' view topline=',FFoldedLinesView.TopLine]);
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.RowToScreenRow(PhysicalRow: integer): integer;
|
||||
@ -1257,7 +1259,7 @@ function TCustomSynEdit.RowToScreenRow(PhysicalRow: integer): integer;
|
||||
// 0 to LinesInWindow for visible lines (incl last partial visble line)
|
||||
// and returns LinesInWindow+1 for lines below visible screen
|
||||
begin
|
||||
Result := fTextView.TextIndexToScreenLine(PhysicalRow-1);
|
||||
Result := FFoldedLinesView.TextIndexToScreenLine(PhysicalRow-1);
|
||||
if Result < -1 then Result := -1;
|
||||
if Result > LinesInWindow+1 then Result := LinesInWindow+1;
|
||||
// DebugLn(['=== Row TO ScreenRow In:',PhysicalRow,' out:',Result]);
|
||||
@ -1396,21 +1398,26 @@ end;
|
||||
constructor TCustomSynEdit.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited Create(AOwner);
|
||||
{begin} //mh 2000-10-10
|
||||
// fLines := TSynEditList.Create;
|
||||
|
||||
fLines := TSynEditStringList.Create;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
fCaret := TSynEditCaret.Create;
|
||||
|
||||
fTrimLines := TSynEditStringTrimmingList.Create(TSynEditStrings(fLines),
|
||||
fCaret);
|
||||
fCaret.Lines := TSynEditStrings(fTrimLines);
|
||||
fTextView := TSynEditFoldedView.Create(TSynEditStringList(fLines),
|
||||
TSynEditStrings(fTrimLines),
|
||||
fCaret);
|
||||
fTextView.OnFoldChanged := {$IFDEF FPC}@{$ENDIF}FoldChanged;
|
||||
{$ENDIF}
|
||||
// with TSynEditList(fLines) do begin
|
||||
// Create the lines/views
|
||||
FTrimmedLinesView := TSynEditStringTrimmingList.Create
|
||||
(TSynEditStrings(fLines), fCaret);
|
||||
|
||||
FTabbedLinesView := TSynEditStringTabExpander.Create
|
||||
(TSynEditStrings(FTrimmedLinesView));
|
||||
|
||||
FFoldedLinesView := TSynEditFoldedView.Create
|
||||
(TSynEditStrings(FTabbedLinesView), fCaret);
|
||||
FFoldedLinesView.OnFoldChanged := {$IFDEF FPC}@{$ENDIF}FoldChanged;
|
||||
|
||||
// Pointer to the First/Lowest View
|
||||
// TODO: this should be Folded...
|
||||
FTheLinesView := FTabbedLinesView;
|
||||
|
||||
fCaret.Lines := TSynEditStrings(FTheLinesView);
|
||||
with TSynEditStringList(fLines) do begin
|
||||
OnAdded := {$IFDEF FPC}@{$ENDIF}ListAdded;
|
||||
OnChange := {$IFDEF FPC}@{$ENDIF}LinesChanged;
|
||||
@ -1421,17 +1428,16 @@ begin
|
||||
OnPutted := {$IFDEF FPC}@{$ENDIF}ListPutted;
|
||||
// OnScanRanges := {$IFDEF FPC}@{$ENDIF}ListScanRanges;
|
||||
end;
|
||||
{end} //mh 2000-10-10
|
||||
|
||||
fFontDummy := TFont.Create;
|
||||
fUndoList := TSynEditUndoList.Create;
|
||||
fUndoList.OnAddedUndo := {$IFDEF FPC}@{$ENDIF}UndoRedoAdded;
|
||||
fRedoList := TSynEditUndoList.Create;
|
||||
fRedoList.OnAddedUndo := {$IFDEF FPC}@{$ENDIF}UndoRedoAdded;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
TSynEditStringTrimmingList(fTrimLines).UndoList := fUndoList;
|
||||
{$ENDIF}
|
||||
|
||||
FBlockSelection := TSynEditSelection.Create(TSynEditStrings(FTrimLines));
|
||||
FTrimmedLinesView.UndoList := fUndoList;
|
||||
|
||||
FBlockSelection := TSynEditSelection.Create(TSynEditStrings(FTheLinesView));
|
||||
FBlockSelection.Caret := FCaret;
|
||||
FBlockSelection.UndoList := fUndoList;
|
||||
FBlockSelection.InvalidateLinesMethod := {$IFDEF FPC}@{$ENDIF}InvalidateLines;
|
||||
@ -1454,7 +1460,7 @@ begin
|
||||
fBookMarkOpt.OnChange := {$IFDEF FPC}@{$ENDIF}BookMarkOptionsChanged;
|
||||
// fRightEdge has to be set before FontChanged is called for the first time
|
||||
fRightEdge := 80;
|
||||
fGutter := TSynGutter.Create(self, fTextView, fBookMarkOpt, fTextDrawer);
|
||||
fGutter := TSynGutter.Create(self, FFoldedLinesView, fBookMarkOpt, fTextDrawer);
|
||||
fGutter.OnChange := {$IFDEF FPC}@{$ENDIF}GutterChanged;
|
||||
fGutterWidth := fGutter.Width;
|
||||
fTextOffset := fGutterWidth + 2;
|
||||
@ -1534,7 +1540,7 @@ begin
|
||||
fLeftChar := 1;
|
||||
fTopLine := 1;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
fTextView.TopLine := 1;
|
||||
FFoldedLinesView.TopLine := 1;
|
||||
{$ELSE}
|
||||
fCaretX := 1;
|
||||
fCaretY := 1;
|
||||
@ -1543,8 +1549,8 @@ begin
|
||||
// find / replace
|
||||
fTSearch := TSynEditSearch.Create;
|
||||
fOptions := SYNEDIT_DEFAULT_OPTIONS;
|
||||
FTrimmedLinesView.Enabled := eoTrimTrailingSpaces in fOptions;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
TSynEditStringTrimmingList(fTrimLines).Enabled := eoTrimTrailingSpaces in fOptions;
|
||||
fOptions2 := SYNEDIT_DEFAULT_OPTIONS2;
|
||||
{$ENDIF}
|
||||
fScrollTimer := TTimer.Create(Self);
|
||||
@ -1602,7 +1608,7 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
fTextView.UnLock; // after ScanFrom, but before UpdateCaret
|
||||
FFoldedLinesView.UnLock; // after ScanFrom, but before UpdateCaret
|
||||
{$ENDIF}
|
||||
Dec(fPaintLock);
|
||||
if (fPaintLock = 0) and HandleAllocated then begin
|
||||
@ -1649,7 +1655,10 @@ begin
|
||||
fTextDrawer.Free;
|
||||
fFontDummy.Free;
|
||||
fBlockSelection.Free;
|
||||
FTabbedLinesView.Free;
|
||||
FTrimmedLinesView.Free;
|
||||
Lines.Free;
|
||||
fCaret.Free;
|
||||
{$ELSE}
|
||||
fHookedCommandHandlers:=nil;
|
||||
fPlugins:=nil;
|
||||
@ -1664,9 +1673,10 @@ begin
|
||||
FreeAndNil(fGutter);
|
||||
FreeAndNil(fTextDrawer);
|
||||
FreeAndNil(fFontDummy);
|
||||
FreeAndNil(fTextView);
|
||||
FreeAndNil(FFoldedLinesView);
|
||||
FreeAndNil(fBlockSelection);
|
||||
FreeAndNil(fTrimLines);
|
||||
FreeAndNil(FTabbedLinesView);
|
||||
FreeAndNil(FTrimmedLinesView);
|
||||
FreeAndNil(fLines);
|
||||
FreeAndNil(fCaret);
|
||||
{$ENDIF}
|
||||
@ -1799,7 +1809,7 @@ end;
|
||||
procedure TCustomSynEdit.SetRealLines(const AValue : TStrings);
|
||||
begin
|
||||
if HandleAllocated then
|
||||
fLines.Assign(AValue);
|
||||
FLines.Assign(AValue);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.SetUseIncrementalColor(const AValue : Boolean);
|
||||
@ -1839,12 +1849,12 @@ end;
|
||||
|
||||
procedure TCustomSynEdit.SetCFDividerDrawLevel(const AValue: Integer);
|
||||
begin
|
||||
fTextView.CFDividerDrawLevel := AValue;
|
||||
FFoldedLinesView.CFDividerDrawLevel := AValue;
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.GetCFDividerDrawLevel : Integer;
|
||||
begin
|
||||
Result := fTextView.CFDividerDrawLevel;
|
||||
Result := FFoldedLinesView.CFDividerDrawLevel;
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.SetLogicalCaretXY(const NewLogCaretXY: TPoint);
|
||||
@ -1953,7 +1963,7 @@ procedure TCustomSynEdit.IncPaintLock;
|
||||
begin
|
||||
inc(fPaintLock);
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
fTextView.Lock; //DecPaintLock triggers ScanFrom, and folds must wait
|
||||
FFoldedLinesView.Lock; //DecPaintLock triggers ScanFrom, and folds must wait
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
@ -2470,7 +2480,7 @@ begin
|
||||
else
|
||||
TopView := TopView + fScrollDeltaY;
|
||||
if fScrollDeltaY > 0
|
||||
then Y := fTextView.TextIndex[LinesInWindow-1]+1 // scrolling down
|
||||
then Y := FFoldedLinesView.TextIndex[LinesInWindow-1]+1 // scrolling down
|
||||
else Y := TopLine; // scrolling up
|
||||
{$ELSE}
|
||||
if GetKeyState(VK_SHIFT) < 0 then
|
||||
@ -2605,7 +2615,7 @@ begin
|
||||
{$ENDIF}
|
||||
);
|
||||
nL2 := Min({$IFDEF SYN_LAZARUS}
|
||||
(rcClip.Bottom-1) div fTextHeight, fTextView.Count - fTextView.TopLine
|
||||
(rcClip.Bottom-1) div fTextHeight, FFoldedLinesView.Count - FFoldedLinesView.TopLine
|
||||
{$ELSE}
|
||||
TopLine + (rcClip.Bottom + fTextHeight - 1) div fTextHeight, Lines.Count
|
||||
{$ENDIF}
|
||||
@ -2648,10 +2658,10 @@ procedure TCustomSynEdit.CodeFoldAction(iLine: integer);
|
||||
begin
|
||||
if (iLine<=0) or (iLine>Lines.Count) then exit;
|
||||
dec(iLine);
|
||||
//DebugLn(['****** FoldAction at ',iLine,' scrline=',fTextView.TextIndexToScreenLine(iLine), ' type ', SynEditCodeFoldTypeNames[fTextView.FoldType[fTextView.TextIndexToScreenLine(iLine)]], ' view topline=',fTextView.TopLine ]);
|
||||
case fTextView.FoldType[fTextView.TextIndexToScreenLine(iLine)] of
|
||||
cfCollapsed : fTextView.UnFoldAtTextIndex(iLine);
|
||||
cfExpanded : fTextView.FoldAtTextIndex(iLine);
|
||||
//DebugLn(['****** FoldAction at ',iLine,' scrline=',FFoldedLinesView.TextIndexToScreenLine(iLine), ' type ', SynEditCodeFoldTypeNames[FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)]], ' view topline=',FFoldedLinesView.TopLine ]);
|
||||
case FFoldedLinesView.FoldType[FFoldedLinesView.TextIndexToScreenLine(iLine)] of
|
||||
cfCollapsed : FFoldedLinesView.UnFoldAtTextIndex(iLine);
|
||||
cfExpanded : FFoldedLinesView.FoldAtTextIndex(iLine);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2661,19 +2671,19 @@ function TCustomSynEdit.FindNextUnfoldedLine(iLine: integer; Down: boolean
|
||||
begin
|
||||
Result:=iLine;
|
||||
while (Result>0) and (Result<=Lines.Count)
|
||||
and (fTextView.FoldedAtTextIndex[Result-1]) do
|
||||
and (FFoldedLinesView.FoldedAtTextIndex[Result-1]) do
|
||||
if Down then inc(Result) else dec(Result);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.UnfoldAll;
|
||||
begin
|
||||
fTextView.UnfoldAll;
|
||||
FFoldedLinesView.UnfoldAll;
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.FoldAll(StartLevel : Integer = 0; IgnoreNested : Boolean = False);
|
||||
begin
|
||||
fTextView.FoldAll(StartLevel, IgnoreNested);
|
||||
FFoldedLinesView.FoldAll(StartLevel, IgnoreNested);
|
||||
Invalidate;
|
||||
end;
|
||||
{$ENDIF}
|
||||
@ -2928,8 +2938,8 @@ var
|
||||
eolx := rcToken.Left; // remeber end of actual line, so we can decide to draw the right edge
|
||||
NextPos := Min(LastCol, TokenAccu.PhysicalEndPos+1);
|
||||
Repeat
|
||||
MarkupInfo := fMarkupManager.GetMarkupAttributeAtRowCol(fTextView.TextIndex[CurLine]+1, NextPos);
|
||||
NextPos := fMarkupManager.GetNextMarkupColAfterRowCol(fTextView.TextIndex[CurLine]+1, NextPos);
|
||||
MarkupInfo := fMarkupManager.GetMarkupAttributeAtRowCol(FFoldedLinesView.TextIndex[CurLine]+1, NextPos);
|
||||
NextPos := fMarkupManager.GetNextMarkupColAfterRowCol(FFoldedLinesView.TextIndex[CurLine]+1, NextPos);
|
||||
|
||||
with fTextDrawer do
|
||||
if MarkupInfo = nil
|
||||
@ -3137,7 +3147,7 @@ var
|
||||
{TODO: cache NextPhysPos, and MarkupInfo between 2 calls }
|
||||
while (nTokenByteLen > 0) do begin
|
||||
// Calculate Token Sublen for current Markup
|
||||
NextPhysPos := fMarkupManager.GetNextMarkupColAfterRowCol(fTextView.TextIndex[CurLine]+1, PhysicalStartPos);
|
||||
NextPhysPos := fMarkupManager.GetNextMarkupColAfterRowCol(FFoldedLinesView.TextIndex[CurLine]+1, PhysicalStartPos);
|
||||
if NextPhysPos < 1
|
||||
then SubCharLen := TokenCharLen
|
||||
else SubCharLen := NextPhysPos - PhysicalStartPos;
|
||||
@ -3160,7 +3170,7 @@ var
|
||||
FG := DefaultFGCol;
|
||||
FC := DefaultFCCol;
|
||||
Style := DefaultStyle;
|
||||
MarkupInfo := fMarkupManager.GetMarkupAttributeAtRowCol(fTextView.TextIndex[CurLine]+1, PhysicalStartPos);
|
||||
MarkupInfo := fMarkupManager.GetMarkupAttributeAtRowCol(FFoldedLinesView.TextIndex[CurLine]+1, PhysicalStartPos);
|
||||
if assigned(MarkupInfo)
|
||||
then MarkupInfo.ModifyColors(FG, BG, FC, Style);
|
||||
// Deal with equal colors
|
||||
@ -3222,9 +3232,9 @@ var
|
||||
LastFSX := -1;
|
||||
LastFEX := -1;
|
||||
|
||||
fMarkupManager.PrepareMarkupForRow(fTextView.TextIndex[CurLine]+1);
|
||||
fMarkupManager.PrepareMarkupForRow(FFoldedLinesView.TextIndex[CurLine]+1);
|
||||
// Get the line.
|
||||
sLine := fTextView[CurLine];
|
||||
sLine := FFoldedLinesView[CurLine];
|
||||
// Update the rcLine rect to this line.
|
||||
rcLine.Top := rcLine.Bottom;
|
||||
Inc(rcLine.Bottom, fTextHeight);
|
||||
@ -3240,8 +3250,8 @@ var
|
||||
// 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.SetRange(fTextView.Ranges[CurLine]); //mh 2000-10-10
|
||||
fHighlighter.SetLine(sLine, fTextView.TextIndex[CurLine]);
|
||||
fHighlighter.SetRange(FFoldedLinesView.Ranges[CurLine]); //mh 2000-10-10
|
||||
fHighlighter.SetLine(sLine, FFoldedLinesView.TextIndex[CurLine]);
|
||||
// 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
|
||||
@ -3262,11 +3272,11 @@ var
|
||||
// of the invalid area with the correct colors.
|
||||
PaintHighlightToken(TRUE);
|
||||
|
||||
fMarkupManager.FinishMarkupForRow(fTextView.TextIndex[CurLine]+1);
|
||||
fMarkupManager.FinishMarkupForRow(FFoldedLinesView.TextIndex[CurLine]+1);
|
||||
|
||||
// codefold draw splitter line
|
||||
if Gutter.ShowCodeFolding
|
||||
and (fTextView.DrawDivider[curLine]) then
|
||||
and (FFoldedLinesView.DrawDivider[curLine]) then
|
||||
begin
|
||||
ypos := rcToken.Bottom - 1;
|
||||
LCLIntf.MoveToEx(dc, nRightEdge, ypos, nil);
|
||||
@ -3371,7 +3381,7 @@ begin
|
||||
|
||||
// codefold draw splitter line
|
||||
if Gutter.ShowCodeFolding
|
||||
and (fTextView.DrawDivider[LastLine]) then
|
||||
and (FFoldedLinesView.DrawDivider[LastLine]) then
|
||||
begin
|
||||
ypos := rcToken.Bottom - 1;
|
||||
LCLIntf.MoveToEx(dc, nRightEdge, ypos, nil);
|
||||
@ -4287,7 +4297,7 @@ end;
|
||||
procedure TCustomSynEdit.SetLines(Value: TStrings);
|
||||
begin
|
||||
if HandleAllocated then
|
||||
Lines.Assign(Value);
|
||||
FTheLinesView.Assign(Value);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.SetLineText(Value: string);
|
||||
@ -4331,7 +4341,7 @@ procedure TCustomSynEdit.SetSelTextPrimitive(PasteMode: TSynSelectionMode;
|
||||
ChangeReason: TSynChangeReason = crInsert);
|
||||
Begin
|
||||
IncPaintLock;
|
||||
TSynEditStringTrimmingList(fTrimLines).Lock;
|
||||
FTrimmedLinesView.Lock;
|
||||
try
|
||||
FBlockSelection.SetSelTextPrimitive(PasteMode, Value, AddToUndoList,
|
||||
ChangeReason);
|
||||
@ -4342,7 +4352,7 @@ Begin
|
||||
Include(fStatusChanges, scCaretX);
|
||||
EnsureCursorPosVisible;
|
||||
finally
|
||||
TSynEditStringTrimmingList(fTrimLines).UnLock;
|
||||
FTrimmedLinesView.UnLock;
|
||||
DecPaintLock;
|
||||
end;
|
||||
end;
|
||||
@ -4351,7 +4361,7 @@ procedure TCustomSynEdit.SetSelTextExternal(const Value: string);
|
||||
begin
|
||||
// undo entry added
|
||||
BeginUndoBlock;
|
||||
TSynEditStringTrimmingList(fTrimLines).Lock;
|
||||
FTrimmedLinesView.Lock;
|
||||
try
|
||||
FBlockSelection.SelText := Value;
|
||||
// Force caret reset
|
||||
@ -4361,7 +4371,7 @@ begin
|
||||
Include(fStatusChanges, scCaretX);
|
||||
EnsureCursorPosVisible;
|
||||
finally
|
||||
TSynEditStringTrimmingList(fTrimLines).UnLock;
|
||||
FTrimmedLinesView.UnLock;
|
||||
EndUndoBlock;
|
||||
end;
|
||||
end;
|
||||
@ -4391,20 +4401,20 @@ begin
|
||||
Value := Min(Value, Lines.Count)
|
||||
else
|
||||
{$ifdef SYN_LAZARUS}
|
||||
Value := Min(Value, fTextView.TextPosAddLines(Lines.Count+1, -fLinesInWindow));
|
||||
Value := Min(Value, FFoldedLinesView.TextPosAddLines(Lines.Count+1, -fLinesInWindow));
|
||||
{$ELSE}
|
||||
Value := Min(Value, Lines.Count + 1 - fLinesInWindow);
|
||||
{$ENDIF}
|
||||
Value := Max(Value, 1);
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
if fTextView.FoldedAtTextIndex[Value-1] then
|
||||
if FFoldedLinesView.FoldedAtTextIndex[Value-1] then
|
||||
Value := FindNextUnfoldedLine(Value, False);
|
||||
{$ENDIF}
|
||||
if Value <> fTopLine then begin
|
||||
{$ifdef SYN_LAZARUS}
|
||||
OldTopLine:=TopLine;
|
||||
fTopLine := Value;
|
||||
fTextView.TopTextIndex := Value-1;
|
||||
FFoldedLinesView.TopTextIndex := Value-1;
|
||||
UpdateScrollBars;
|
||||
Delta := OldTopLine - TopLine;
|
||||
if (Abs(Delta) < fLinesInWindow) and not (sfPainting in fStateFlags)
|
||||
@ -4588,7 +4598,7 @@ begin
|
||||
{$ENDIF}
|
||||
end;
|
||||
if fScrollBars in [ssBoth, ssVertical] then begin
|
||||
nMaxScroll := {$IFDEF SYN_LAZARUS}fTextView.Count+1{$ELSE}Lines.Count{$ENDIF};
|
||||
nMaxScroll := {$IFDEF SYN_LAZARUS}FFoldedLinesView.Count+1{$ELSE}Lines.Count{$ENDIF};
|
||||
if (eoScrollPastEof in Options) then
|
||||
Inc(nMaxScroll, LinesInWindow - 1);
|
||||
{$IFNDEF SYN_LAZARUS}
|
||||
@ -4597,7 +4607,7 @@ begin
|
||||
ScrollInfo.nMax := Max(1, nMaxScroll);
|
||||
ScrollInfo.nPage := LinesInWindow;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
ScrollInfo.nPos := fTextView.TextIndexToViewPos(TopLine-1);
|
||||
ScrollInfo.nPos := FFoldedLinesView.TextIndexToViewPos(TopLine-1);
|
||||
{$ELSE}
|
||||
ScrollInfo.nPos := TopLine;
|
||||
{$ENDIF}
|
||||
@ -4878,7 +4888,7 @@ begin
|
||||
Result := Index;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
if not assigned(fHighlighter) or (Index > Lines.Count - 1) then begin
|
||||
fTextView.FixFoldingAtTextIndex(Index);
|
||||
FFoldedLinesView.FixFoldingAtTextIndex(Index);
|
||||
fMarkupManager.TextChangedScreen(Max(RowToScreenRow(Index+1), 0), LinesInWindow+1);
|
||||
Topline := TopLine;
|
||||
exit;
|
||||
@ -4892,7 +4902,7 @@ begin
|
||||
end;
|
||||
{$ENDIF}
|
||||
if Index >= Lines.Count - 1 then begin
|
||||
fTextView.FixFoldingAtTextIndex(Index);
|
||||
FFoldedLinesView.FixFoldingAtTextIndex(Index);
|
||||
fMarkupManager.TextChangedScreen(Max(RowToScreenRow(Index+1), 0), LinesInWindow+1);
|
||||
Topline := TopLine;
|
||||
Exit;
|
||||
@ -4938,7 +4948,7 @@ begin
|
||||
// => update code fold attributes of last scanned line
|
||||
if (Result>Index+1) and (Result<=Lines.Count) then
|
||||
SetCodeFoldAttributes;
|
||||
fTextView.FixFoldingAtTextIndex(FixFStart, Result);
|
||||
FFoldedLinesView.FixFoldingAtTextIndex(FixFStart, Result);
|
||||
fMarkupManager.TextChangedScreen(Max(RowToScreenRow(FixFStart+1), 0),
|
||||
Min(RowToScreenRow(Result), LinesInWindow+1));
|
||||
Topline := TopLine;
|
||||
@ -5100,7 +5110,7 @@ var
|
||||
i: Integer;
|
||||
begin
|
||||
TopLine := TopLine;
|
||||
i := fTextView.CollapsedLineForFoldAtLine(CaretY);
|
||||
i := FFoldedLinesView.CollapsedLineForFoldAtLine(CaretY);
|
||||
if i > 0 then
|
||||
SetCaretXY(Point(1, i))
|
||||
else
|
||||
@ -5114,12 +5124,12 @@ end;
|
||||
|
||||
procedure TCustomSynEdit.SetTopView(const AValue : Integer);
|
||||
begin
|
||||
TopLine := fTextView.ViewPosToTextIndex(AValue)+1;
|
||||
TopLine := FFoldedLinesView.ViewPosToTextIndex(AValue)+1;
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.GetTopView : Integer;
|
||||
begin
|
||||
Result := fTextView.TextIndexToViewPos(TopLine-1);
|
||||
Result := FFoldedLinesView.TextIndexToViewPos(TopLine-1);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
@ -5618,7 +5628,7 @@ begin
|
||||
{end} //mh 2000-11-20
|
||||
end;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
crTrimSpace: TSynEditStringTrimmingList(fTrimLines).ForceTrim;
|
||||
crTrimSpace: FTrimmedLinesView.ForceTrim;
|
||||
{$ENDIF}
|
||||
crLineBreak:
|
||||
{begin} //sbs 2000-11-20
|
||||
@ -5753,7 +5763,7 @@ begin
|
||||
{$ENDIF}
|
||||
finally
|
||||
// Todo: Decide what do to, If there are any trimable spaces.
|
||||
TSynEditStringTrimmingList(fTrimLines).ForceTrim;
|
||||
FTrimmedLinesView.ForceTrim;
|
||||
fUndoList.UnLock;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
fRedoList.EndBlock;
|
||||
@ -5843,7 +5853,7 @@ begin
|
||||
EnsureCursorPosVisible;
|
||||
end;
|
||||
crTrimRealSpace:
|
||||
TSynEditStringTrimmingList(fTrimLines).UndoRealSpaces(Item);
|
||||
FTrimmedLinesView.UndoRealSpaces(Item);
|
||||
crLineBreak:
|
||||
begin
|
||||
// If there's no selection, we have to set
|
||||
@ -6431,7 +6441,7 @@ begin
|
||||
TopLine := CaretY
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
else if CaretY > ScreenRowToRow(Max(1, LinesInWindow) - 1) then //mh 2000-10-19
|
||||
TopLine := fTextView.TextPosAddLines(CaretY, -Max(0, LinesInWindow-1))
|
||||
TopLine := FFoldedLinesView.TextPosAddLines(CaretY, -Max(0, LinesInWindow-1))
|
||||
{$ELSE}
|
||||
else if CaretY > TopLine + Max(1, LinesInWindow) - 1 then //mh 2000-10-19
|
||||
TopLine := CaretY - (LinesInWindow - 1)
|
||||
@ -6709,7 +6719,7 @@ begin
|
||||
ecEditorBottom, ecSelEditorBottom:
|
||||
begin
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
CaretNew := Point(1, fTextView.ViewPosToTextIndex(fTextView.Count)+1);
|
||||
CaretNew := Point(1, FFoldedLinesView.ViewPosToTextIndex(FFoldedLinesView.Count)+1);
|
||||
{$ELSE}
|
||||
CaretNew := Point(1, Lines.Count);
|
||||
{$ENDIF}
|
||||
@ -6742,7 +6752,7 @@ begin
|
||||
Caret := CaretXY;
|
||||
CaretNew := PrevWordPos;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
if fTextView.FoldedAtTextIndex[CaretNew.Y - 1] then begin
|
||||
if FFoldedLinesView.FoldedAtTextIndex[CaretNew.Y - 1] then begin
|
||||
CY := FindNextUnfoldedLine(CaretNew.Y, False);
|
||||
CaretNew := LogicalToPhysicalPos(Point(1 + Length(Lines[CY-1]), CY));
|
||||
end;
|
||||
@ -6761,7 +6771,7 @@ begin
|
||||
Caret := CaretXY;
|
||||
CaretNew := NextWordPos;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
if fTextView.FoldedAtTextIndex[CaretNew.Y - 1] then
|
||||
if FFoldedLinesView.FoldedAtTextIndex[CaretNew.Y - 1] then
|
||||
CaretNew := Point(1, FindNextUnfoldedLine(CaretNew.Y, True));
|
||||
MoveCaretAndSelectionPhysical
|
||||
{$ELSE}
|
||||
@ -7493,14 +7503,14 @@ begin
|
||||
UnfoldAll;
|
||||
EcFoldCurrent:
|
||||
begin
|
||||
CY := fTextView.ExpandedLineForBlockAtLine(CaretY);
|
||||
CY := FFoldedLinesView.ExpandedLineForBlockAtLine(CaretY);
|
||||
if CY > 0 then begin
|
||||
fTextView.FoldAtTextIndex(CY-1);
|
||||
FFoldedLinesView.FoldAtTextIndex(CY-1);
|
||||
SetCaretXY(Point(1, CY));
|
||||
end;
|
||||
end;
|
||||
EcUnFoldCurrent:
|
||||
fTextView.UnFoldAtTextIndex(CaretY-1);
|
||||
FFoldedLinesView.UnFoldAtTextIndex(CaretY-1);
|
||||
{$ENDIF}
|
||||
end;
|
||||
finally
|
||||
@ -7787,8 +7797,8 @@ begin
|
||||
fUndoList.BeginBlock;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
IncPaintLock;
|
||||
fTextView.Lock;
|
||||
TSynEditStringTrimmingList(fTrimLines).Lock;
|
||||
FFoldedLinesView.Lock;
|
||||
FTrimmedLinesView.Lock;
|
||||
{$ENDIF}
|
||||
end;
|
||||
{end} //sbs 2000-11-19
|
||||
@ -7804,8 +7814,8 @@ begin
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
// Write all trimming info to the end of the undo block,
|
||||
// so it will be undone first, and other UndoItems do see the expected spaces
|
||||
TSynEditStringTrimmingList(fTrimLines).UnLock;
|
||||
fTextView.UnLock;
|
||||
FTrimmedLinesView.UnLock;
|
||||
FFoldedLinesView.UnLock;
|
||||
// must be last => May call MoveCaretToVisibleArea, which must only happen
|
||||
// after unfold
|
||||
DecPaintLock;
|
||||
@ -8101,10 +8111,11 @@ end;
|
||||
|
||||
procedure TCustomSynEdit.SetTabWidth(Value: integer);
|
||||
begin
|
||||
Value := MinMax(Value, 1{0}, 256); //lt 2000-10-19
|
||||
Value := MinMax(Value, 1{0}, 256);
|
||||
if (Value <> fTabWidth) then begin
|
||||
fTabWidth := Value;
|
||||
TSynEditStringList(fLines).TabWidth := Value; //mh 2000-10-19
|
||||
FTabbedLinesView.TabWidth := Value;
|
||||
FBlockSelection.TabWidth := Value;
|
||||
Invalidate; // to redraw text containing tab chars
|
||||
end;
|
||||
end;
|
||||
@ -8430,9 +8441,7 @@ begin
|
||||
{$ENDIF}
|
||||
bSetDrag := (eoDropFiles in fOptions) <> (eoDropFiles in Value);
|
||||
fOptions := Value;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
TSynEditStringTrimmingList(fTrimLines).Enabled := eoTrimTrailingSpaces in fOptions;
|
||||
{$ENDIF}
|
||||
FTrimmedLinesView.Enabled := eoTrimTrailingSpaces in fOptions;
|
||||
// Reset column position in case Cursor is past EOL.
|
||||
if not (eoScrollPastEol in fOptions) then
|
||||
CaretX := CaretX;
|
||||
@ -8508,7 +8517,7 @@ begin
|
||||
fCharsInWindow := Max(1,(ClientWidth - fGutterWidth - 2 - ScrollBarWidth)
|
||||
div fCharWidth);
|
||||
fLinesInWindow := Max(0,ClientHeight - ScrollBarWidth) div Max(1,fTextHeight);
|
||||
fTextView.LinesInWindow := fLinesInWindow;
|
||||
FFoldedLinesView.LinesInWindow := fLinesInWindow;
|
||||
|
||||
fMarkupManager.LinesInWindow:= fLinesInWindow;
|
||||
//DebugLn('TCustomSynEdit.SizeOrFontChanged fLinesInWindow=',dbgs(fLinesInWindow),' ClientHeight=',dbgs(ClientHeight),' ',dbgs(fTextHeight));
|
||||
@ -8551,7 +8560,7 @@ begin
|
||||
NewCaret.X:=1
|
||||
else begin
|
||||
// move to end of prev line
|
||||
NewCaret.Y:= fTextView.TextPosAddLines(NewCaret.Y, -1);
|
||||
NewCaret.Y:= FFoldedLinesView.TextPosAddLines(NewCaret.Y, -1);
|
||||
s:=Lines[NewCaret.Y-1];
|
||||
PhysicalLineLen:=LogicalToPhysicalPos(Point(length(s)+1,NewCaret.Y)).X-1;
|
||||
NewCaret.X:=PhysicalLineLen+1;
|
||||
@ -8562,7 +8571,7 @@ begin
|
||||
if NewCaret.X>PhysicalLineLen+1 then begin
|
||||
// move to start of next line
|
||||
NewCaret.X:=1;
|
||||
NewCaret.Y:=fTextView.TextPosAddLines(NewCaret.Y, +1);
|
||||
NewCaret.Y:=FFoldedLinesView.TextPosAddLines(NewCaret.Y, +1);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -8639,7 +8648,7 @@ var
|
||||
begin
|
||||
OldCaret:=CaretXY;
|
||||
NewCaret:=OldCaret;
|
||||
NewCaret.Y:=fTextView.TextPosAddLines(NewCaret.Y, DY);
|
||||
NewCaret.Y:=FFoldedLinesView.TextPosAddLines(NewCaret.Y, DY);
|
||||
if (OldCaret.Y<>NewCaret.Y) and (fLastCaretX>0) and (eoKeepCaretX in Options)
|
||||
then
|
||||
NewCaret.X:=fLastCaretX;
|
||||
@ -8986,7 +8995,7 @@ begin
|
||||
inc(BB.x, fBlockIndent);
|
||||
BE.x := x;
|
||||
end;
|
||||
TSynEditStringTrimmingList(fTrimLines).ForceTrim; // Otherwise it may reset the block
|
||||
FTrimmedLinesView.ForceTrim; // Otherwise it may reset the block
|
||||
SetCaretAndSelection(LogicalToPhysicalPos(BE), BB, BE);
|
||||
{$ELSE}
|
||||
SetCaretAndSelection(OrgCaretPos,
|
||||
@ -9143,7 +9152,7 @@ begin
|
||||
dec(BB.x, FirstIndent);
|
||||
dec(BE.x, LastIndent);
|
||||
end;
|
||||
TSynEditStringTrimmingList(fTrimLines).ForceTrim; // Otherwise it may reset the block
|
||||
FTrimmedLinesView.ForceTrim; // Otherwise it may reset the block
|
||||
SetCaretAndSelection(LogicalToPhysicalPos(BE), BB, BE);
|
||||
{$ELSE}
|
||||
if FirstIndent = -1 then
|
||||
|
||||
@ -201,7 +201,7 @@ type
|
||||
function FixFolding(AStart : Integer; AMinEnd : Integer; aFoldTree : TSynTextFoldAVLTree) : Boolean;
|
||||
|
||||
procedure DoCaretChanged(Sender : TObject);
|
||||
Procedure LineCountChanged(AIndex, ACount : Integer);
|
||||
Procedure LineCountChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
|
||||
Procedure LinesInsertedAtTextIndex(AStartIndex, ALineCount : Integer;
|
||||
SkipFixFolding : Boolean = False);
|
||||
Procedure LinesInsertedAtViewPos(AStartPos, ALineCount : Integer;
|
||||
@ -211,7 +211,7 @@ type
|
||||
Procedure LinesDeletedAtViewPos(AStartPos, ALineCount : Integer;
|
||||
SkipFixFolding : Boolean = False);
|
||||
public
|
||||
constructor Create(aTextBuffer : TSynEditStringList; aTextView : TSynEditStrings; ACaret: TSynEditCaret);
|
||||
constructor Create(aTextView : TSynEditStrings; ACaret: TSynEditCaret);
|
||||
destructor Destroy; override;
|
||||
|
||||
// Converting between Folded and Unfolded Lines/Indexes
|
||||
@ -1390,20 +1390,21 @@ end;
|
||||
|
||||
{ TSynEditFoldedView }
|
||||
|
||||
constructor TSynEditFoldedView.Create(aTextBuffer : TSynEditStringList; aTextView : TSynEditStrings; ACaret: TSynEditCaret);
|
||||
constructor TSynEditFoldedView.Create(aTextView : TSynEditStrings; ACaret: TSynEditCaret);
|
||||
begin
|
||||
fCaret := ACaret;
|
||||
fCaret.AddChangeHandler(@DoCaretChanged);
|
||||
fCaret.AddChangeHandler({$IFDEF FPC}@{$ENDIF}DoCaretChanged);
|
||||
fLines := aTextView;
|
||||
fFoldTree := TSynTextFoldAVLTree.Create;
|
||||
fTopLine := 0;
|
||||
fLinesInWindow := -1;
|
||||
aTextBuffer.OnLineCountChanged := {$IFDEF FPC}@{$ENDIF}LineCountChanged;
|
||||
fLines.AddChangeHandler(senrLineCount, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
|
||||
end;
|
||||
|
||||
destructor TSynEditFoldedView.Destroy;
|
||||
begin
|
||||
fCaret.RemoveChangeHandler(@DoCaretChanged);
|
||||
fLines.RemoveChangeHandler(senrLineCount, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
|
||||
fCaret.RemoveChangeHandler({$IFDEF FPC}@{$ENDIF}DoCaretChanged);
|
||||
fFoldTree.Free;
|
||||
fTextIndexList := nil;
|
||||
fFoldTypeList := nil;
|
||||
@ -1849,7 +1850,7 @@ begin
|
||||
UnFoldAtTextIndex(i, true);
|
||||
end;
|
||||
|
||||
procedure TSynEditFoldedView.LineCountChanged(AIndex, ACount : Integer);
|
||||
procedure TSynEditFoldedView.LineCountChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
|
||||
begin
|
||||
// no need for fix folding => synedit will be called, and scanlines will call fixfolding
|
||||
{TODO: a "need fix folding" flag => to ensure it will be called if synedit doesnt}
|
||||
|
||||
@ -84,10 +84,10 @@ function ConvertTabs(const Line: AnsiString; TabWidth: integer): AnsiString;
|
||||
{begin} //mh 2000-10-19
|
||||
type
|
||||
TConvertTabsProcEx = function(const Line: AnsiString; TabWidth: integer;
|
||||
var HasTabs: boolean): AnsiString;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
TSimulateConvertTabsProcEx = function(const Line: AnsiString;
|
||||
TabWidth: integer; var HasTabs: boolean): integer;
|
||||
TabWidth: integer; out HasTabs: boolean): integer;
|
||||
// returns length of converted string
|
||||
{$ENDIF}
|
||||
|
||||
@ -98,7 +98,7 @@ function GetBestSimulateConvertTabsProcEx(
|
||||
{$ENDIF}
|
||||
// This is the slowest conversion function which can handle TabWidth <> 2^n.
|
||||
function ConvertTabsEx(const Line: AnsiString; TabWidth: integer;
|
||||
var HasTabs: boolean): AnsiString;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
{end} //mh 2000-10-19
|
||||
|
||||
function CharIndex2CaretPos(Index, TabWidth: integer;
|
||||
@ -268,7 +268,7 @@ end;
|
||||
|
||||
{begin} //mh 2000-10-19
|
||||
function ConvertTabs1Ex(const Line: AnsiString; TabWidth: integer;
|
||||
var HasTabs: boolean): AnsiString;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
var
|
||||
pDest: PChar;
|
||||
nBeforeTab: integer;
|
||||
@ -289,7 +289,7 @@ end;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function SimulateConvertTabs1Ex(const Line: AnsiString; TabWidth: integer;
|
||||
var HasTabs: boolean): integer;
|
||||
out HasTabs: boolean): integer;
|
||||
// TabWidth=1
|
||||
var
|
||||
i: integer;
|
||||
@ -309,7 +309,7 @@ begin
|
||||
end;
|
||||
|
||||
function ConvertTabs2nEx(const Line: AnsiString; TabWidth: integer;
|
||||
var HasTabs: boolean): AnsiString;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
var
|
||||
i, DestLen, TabCount, TabMask: integer;
|
||||
pSrc, pDest: PChar;
|
||||
@ -369,7 +369,7 @@ end;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function SimulateConvertTabs2nEx(const Line: AnsiString; TabWidth: integer;
|
||||
var HasTabs: boolean): integer;
|
||||
out HasTabs: boolean): integer;
|
||||
var
|
||||
LineLen, DestLen, SrcPos, TabMask: integer;
|
||||
begin
|
||||
@ -404,7 +404,7 @@ begin
|
||||
end;
|
||||
|
||||
function ConvertTabsEx(const Line: AnsiString; TabWidth: integer;
|
||||
var HasTabs: boolean): AnsiString;
|
||||
out HasTabs: boolean): AnsiString;
|
||||
var
|
||||
i, DestLen, TabCount: integer;
|
||||
pSrc, pDest: PChar;
|
||||
@ -461,7 +461,7 @@ end;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
function SimulateConvertTabsEx(const Line: AnsiString; TabWidth: integer;
|
||||
var HasTabs: boolean): integer;
|
||||
out HasTabs: boolean): integer;
|
||||
var
|
||||
LineLen, DestLen, SrcPos: integer;
|
||||
begin
|
||||
|
||||
@ -72,6 +72,7 @@ type
|
||||
FLinesInsertedMethod: TLinesCountChanged;
|
||||
FEnabled: Boolean;
|
||||
FSpacesToTabs: Boolean;
|
||||
FTabWidth: Integer;
|
||||
FActiveSelectionMode: TSynSelectionMode;
|
||||
FSelectionMode: TSynSelectionMode;
|
||||
FStartLinePos: Integer; // 1 based
|
||||
@ -124,6 +125,8 @@ type
|
||||
property LinesInsertedMethod: TLinesCountChanged write FLinesInsertedMethod;
|
||||
property Caret: TSynEditCaret read FCaret write FCaret;
|
||||
property UndoList: TSynEditUndoList read fUndoList write fUndoList;
|
||||
// TODO: Move dependend functions to Lines
|
||||
property TabWidth: integer read FTabWidth write FTabWidth;
|
||||
end;
|
||||
|
||||
{ TSynEditCaret }
|
||||
@ -568,8 +571,7 @@ var
|
||||
sLeftSide := sLeftSide
|
||||
+ CreateTabsAndSpaces(FCaret.CharPos,
|
||||
FCaret.CharPos-1-PhysicalLineEndPos,
|
||||
FLines.TabWidth,
|
||||
FSpacesToTabs);
|
||||
FTabWidth, FSpacesToTabs);
|
||||
end;
|
||||
sRightSide := Copy(FCaret.LineText, LogCaretXY.X,
|
||||
Length(FCaret.LineText) - (LogCaretXY.X - 1));
|
||||
|
||||
@ -21,7 +21,7 @@ of this file under either the MPL or the GPL.
|
||||
-------------------------------------------------------------------------------}
|
||||
unit SynEditTextBase;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$I synedit.inc}
|
||||
|
||||
interface
|
||||
|
||||
@ -29,33 +29,124 @@ uses
|
||||
Classes, SysUtils, LCLProc, SynEditTypes;
|
||||
|
||||
type
|
||||
TSynEditStrings = class;
|
||||
|
||||
TStringListLineCountEvent = procedure(Sender: TSynEditStrings;
|
||||
Index, Count: Integer) of object;
|
||||
TSynEditNotifyReason = (senrLineCount, senrLineChange);
|
||||
|
||||
{ TSynEditStrings }
|
||||
|
||||
TSynEditStrings = class(TStrings)
|
||||
protected
|
||||
FTabWidth: integer;
|
||||
FIsUtf8: Boolean;
|
||||
function GetIsUtf8 : Boolean; virtual;
|
||||
procedure SetIsUtf8(const AValue : Boolean); virtual;
|
||||
function GetTabWidth : integer; virtual;
|
||||
procedure SetTabWidth(const AValue : integer); virtual;
|
||||
function GetFoldEndLevel(Index: integer): integer; virtual; abstract;
|
||||
function GetFoldMinLevel(Index: integer): integer; virtual; abstract;
|
||||
procedure SetFoldEndLevel(Index: integer; const AValue: integer); virtual; abstract;
|
||||
procedure SetFoldMinLevel(Index: integer; const AValue: integer); virtual; abstract;
|
||||
function GetRange(Index: integer): TSynEditRange; virtual; abstract;
|
||||
procedure PutRange(Index: integer; ARange: TSynEditRange); virtual; abstract;
|
||||
function GetAttribute(const Owner: TClass; const Index: Integer): Pointer; virtual; abstract;
|
||||
procedure SetAttribute(const Owner: TClass; const Index: Integer; const AValue: Pointer); virtual; abstract;
|
||||
procedure RegisterAttribute(const Index: TClass; const Size: Word); virtual; abstract;
|
||||
|
||||
function GetExpandedString(Index: integer): string; virtual; abstract;
|
||||
function GetLengthOfLongestLine: integer; virtual; abstract;
|
||||
procedure SetTextStr(const Value: string); override;
|
||||
|
||||
property Attribute[Owner: TClass; Index: Integer]: Pointer
|
||||
read GetAttribute write SetAttribute;
|
||||
public
|
||||
constructor Create;
|
||||
procedure DeleteLines(Index, NumLines: integer); virtual; abstract;
|
||||
procedure InsertLines(Index, NumLines: integer); virtual; abstract;
|
||||
procedure InsertStrings(Index: integer; NewStrings: TStrings); virtual; abstract;
|
||||
procedure ClearRanges(ARange: TSynEditRange); virtual; abstract;
|
||||
|
||||
procedure AddChangeHandler(AReason: TSynEditNotifyReason;
|
||||
AHandler: TStringListLineCountEvent); virtual; abstract;
|
||||
procedure RemoveChangeHandler(AReason: TSynEditNotifyReason;
|
||||
AHandler: TStringListLineCountEvent); virtual; abstract;
|
||||
public
|
||||
// Byte to Char
|
||||
function LogicalToPhysicalPos(const p: TPoint): TPoint;
|
||||
function LogicalToPhysicalCol(const Line: string;
|
||||
LogicalPos: integer): integer;
|
||||
function LogicalToPhysicalCol(Line: PChar; LineLen: integer;
|
||||
LogicalPos, StartBytePos,
|
||||
StartPhysicalPos: integer): integer; virtual;
|
||||
// Char to Byte
|
||||
function PhysicalToLogicalPos(const p: TPoint): TPoint;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos: integer): integer;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos,
|
||||
StartPhysicalPos: integer): integer; virtual;
|
||||
public
|
||||
property ExpandedStrings[Index: integer]: string read GetExpandedString;
|
||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
||||
property IsUtf8: Boolean read GetIsUtf8 write SetIsUtf8;
|
||||
property Ranges[Index: integer]: TSynEditRange read GetRange write PutRange;
|
||||
property FoldMinLevel[Index: integer]: integer read GetFoldMinLevel
|
||||
write SetFoldMinLevel;
|
||||
property FoldEndLevel[Index: integer]: integer read GetFoldEndLevel
|
||||
write SetFoldEndLevel;
|
||||
end;
|
||||
|
||||
{ TSynEditStringsLinked }
|
||||
|
||||
TSynEditStringsLinked = class(TSynEditStrings)
|
||||
protected
|
||||
fSynStrings: TSynEditStrings;
|
||||
|
||||
function GetIsUtf8 : Boolean; override;
|
||||
procedure SetIsUtf8(const AValue : Boolean); override;
|
||||
|
||||
function GetFoldEndLevel(Index: integer): integer; override;
|
||||
function GetFoldMinLevel(Index: integer): integer; override;
|
||||
procedure SetFoldEndLevel(Index: integer; const AValue: integer); override;
|
||||
procedure SetFoldMinLevel(Index: integer; const AValue: integer); override;
|
||||
function GetRange(Index: integer): TSynEditRange; override;
|
||||
procedure PutRange(Index: integer; ARange: TSynEditRange); override;
|
||||
|
||||
function GetAttribute(const Owner: TClass; const Index: Integer): Pointer; override;
|
||||
procedure SetAttribute(const Owner: TClass; const Index: Integer; const AValue: Pointer); override;
|
||||
// Size: 0 = Bit (TODO); 1..8 Size In Byte "SizeOf()"
|
||||
procedure RegisterAttribute(const Index: TClass; const Size: Word); 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); 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;
|
||||
procedure Exchange(Index1, Index2: integer); override;
|
||||
|
||||
procedure ClearRanges(ARange: TSynEditRange); override;
|
||||
|
||||
procedure AddChangeHandler(AReason: TSynEditNotifyReason;
|
||||
AHandler: TStringListLineCountEvent); override;
|
||||
procedure RemoveChangeHandler(AReason: TSynEditNotifyReason;
|
||||
AHandler: TStringListLineCountEvent); override;
|
||||
(* public
|
||||
// Byte to Char
|
||||
function LogicalToPhysicalPos(const p: TPoint): TPoint;
|
||||
function LogicalToPhysicalCol(const Line: string;
|
||||
@ -68,19 +159,11 @@ type
|
||||
PhysicalPos: integer): integer;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
public
|
||||
property ExpandedStrings[Index: integer]: string read GetExpandedString;
|
||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
||||
property TabWidth: integer read GetTabWidth write SetTabWidth;
|
||||
property IsUtf8: Boolean read GetIsUtf8 write SetIsUtf8;
|
||||
property Ranges[Index: integer]: TSynEditRange read GetRange write PutRange;
|
||||
property FoldMinLevel[Index: integer]: integer read GetFoldMinLevel
|
||||
write SetFoldMinLevel;
|
||||
property FoldEndLevel[Index: integer]: integer read GetFoldEndLevel
|
||||
write SetFoldEndLevel;
|
||||
*)
|
||||
end;
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
@ -89,7 +172,6 @@ implementation
|
||||
constructor TSynEditStrings.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
TabWidth := 8;
|
||||
IsUtf8 := True;
|
||||
end;
|
||||
|
||||
@ -98,21 +180,11 @@ begin
|
||||
Result := FIsUtf8;
|
||||
end;
|
||||
|
||||
function TSynEditStrings.GetTabWidth : integer;
|
||||
begin
|
||||
Result := FTabWidth;
|
||||
end;
|
||||
|
||||
procedure TSynEditStrings.SetIsUtf8(const AValue : Boolean);
|
||||
begin
|
||||
FIsUtf8 := AValue;
|
||||
end;
|
||||
|
||||
procedure TSynEditStrings.SetTabWidth(const AValue : integer);
|
||||
begin
|
||||
FTabWidth := AValue;
|
||||
end;
|
||||
|
||||
procedure TSynEditStrings.SetTextStr(const Value : string);
|
||||
var
|
||||
StartPos: Integer;
|
||||
@ -165,21 +237,16 @@ var
|
||||
ScreenPos: integer;
|
||||
begin
|
||||
ByteLen := LineLen;
|
||||
// map UTF8 and Tab chars
|
||||
// map UTF8
|
||||
ScreenPos := StartPhysicalPos;
|
||||
BytePos:= StartBytePos;
|
||||
while BytePos<LogicalPos do begin
|
||||
if (BytePos <= ByteLen) then begin
|
||||
if Line[BytePos-1] = #9 then begin
|
||||
inc(ScreenPos, TabWidth - ((ScreenPos-1) mod TabWidth));
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@Line[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end else begin
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@Line[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end;
|
||||
end else begin
|
||||
// beyond end of line
|
||||
inc(ScreenPos,LogicalPos-BytePos);
|
||||
@ -213,19 +280,14 @@ begin
|
||||
ScreenPos := StartPhysicalPos;
|
||||
BytePos := StartBytePos;
|
||||
PLine := PChar(Line);
|
||||
// map utf and tab chars
|
||||
// map utf
|
||||
while ScreenPos < PhysicalPos do begin
|
||||
if (BytePos <= ByteLen) then begin
|
||||
if (PLine[BytePos-1] <> #9) then begin
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@PLine[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end else begin
|
||||
inc(ScreenPos, TabWidth - ((ScreenPos-1) mod TabWidth));
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@PLine[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end;
|
||||
end else begin
|
||||
// beyond end of line
|
||||
inc(BytePos,PhysicalPos-ScreenPos);
|
||||
@ -238,5 +300,175 @@ begin
|
||||
Result := BytePos;
|
||||
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;
|
||||
|
||||
procedure TSynEditStringsLinked.Exchange(Index1, Index2: integer);
|
||||
begin
|
||||
fSynStrings.Exchange(Index1, Index2);
|
||||
end;
|
||||
|
||||
function TSynEditStringsLinked.GetIsUtf8: Boolean;
|
||||
begin
|
||||
Result := FSynStrings.IsUtf8;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.SetIsUtf8(const AValue: Boolean);
|
||||
begin
|
||||
FSynStrings.IsUtf8 := AValue;
|
||||
end;
|
||||
|
||||
//Fold
|
||||
function TSynEditStringsLinked.GetFoldEndLevel(Index: integer): integer;
|
||||
begin
|
||||
Result:= fSynStrings.FoldEndLevel[Index];
|
||||
end;
|
||||
|
||||
function TSynEditStringsLinked.GetFoldMinLevel(Index: integer): integer;
|
||||
begin
|
||||
Result:= fSynStrings.FoldMinLevel[Index];
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.SetFoldEndLevel(Index: integer; const AValue: integer);
|
||||
begin
|
||||
fSynStrings.FoldEndLevel[Index] := AValue;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.SetFoldMinLevel(Index: integer; const AValue: integer);
|
||||
begin
|
||||
fSynStrings.FoldMinLevel[Index] := AValue;
|
||||
end;
|
||||
|
||||
//Ranges
|
||||
function TSynEditStringsLinked.GetRange(Index: integer): TSynEditRange;
|
||||
begin
|
||||
Result:= fSynStrings.Ranges[Index];
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.PutRange(Index: integer; ARange: TSynEditRange);
|
||||
begin
|
||||
fSynStrings.Ranges[Index] := ARange;
|
||||
end;
|
||||
|
||||
function TSynEditStringsLinked.GetAttribute(const Owner: TClass; const Index: Integer): Pointer;
|
||||
begin
|
||||
Result := fSynStrings.Attribute[Owner, Index];
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.SetAttribute(const Owner: TClass;
|
||||
const Index: Integer; const AValue: Pointer);
|
||||
begin
|
||||
fSynStrings.Attribute[Owner, Index] := AValue;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.RegisterAttribute(const Index: TClass; const Size: Word);
|
||||
begin
|
||||
fSynStrings.RegisterAttribute(Index, Size);
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.ClearRanges(ARange: TSynEditRange);
|
||||
begin
|
||||
fSynStrings.ClearRanges(ARange);
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.AddChangeHandler(AReason: TSynEditNotifyReason; AHandler: TStringListLineCountEvent);
|
||||
begin
|
||||
fSynStrings.AddChangeHandler(AReason, AHandler);
|
||||
end;
|
||||
|
||||
procedure TSynEditStringsLinked.RemoveChangeHandler(AReason: TSynEditNotifyReason; AHandler: TStringListLineCountEvent);
|
||||
begin
|
||||
fSynStrings.RemoveChangeHandler(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;
|
||||
|
||||
procedure TSynEditStringsLinked.SetUpdateState(Updating: Boolean);
|
||||
begin
|
||||
if Updating then
|
||||
fSynStrings.BeginUpdate
|
||||
else
|
||||
fSynStrings.EndUpdate;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
258
components/synedit/synedittexttabexpander.pas
Normal file
258
components/synedit/synedittexttabexpander.pas
Normal file
@ -0,0 +1,258 @@
|
||||
unit SynEditTextTabExpander;
|
||||
|
||||
{$I synedit.inc}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
LCLProc,
|
||||
Classes, SysUtils, SynEditTypes, SynEditTextBase, SynEditTextBuffer,
|
||||
SynEditMiscClasses, SynEditMiscProcs;
|
||||
|
||||
const
|
||||
// Offset to add to LengthOfLine, if Line has no tabs.
|
||||
// (Length will still be valid if tab-width changes)
|
||||
NoTabLengthOffset = MaxInt div 2;
|
||||
|
||||
type
|
||||
|
||||
{ TSynEditStringTabExpander }
|
||||
|
||||
TSynEditStringTabExpander = class(TSynEditStringsLinked)
|
||||
private
|
||||
FTabWidth: integer;
|
||||
FConvertTabsProc: TConvertTabsProcEx;
|
||||
FSimulateConvertTabsProc: TSimulateConvertTabsProcEx;
|
||||
FIndexOfLongestLine: Integer;
|
||||
function GetLengthOfLine(Index: Integer): integer;
|
||||
procedure SetLengthOfLine(Index: Integer; const AValue: integer);
|
||||
Procedure LineCountChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
|
||||
function ExpandedString(Index: integer): string;
|
||||
function ExpandedStringLength(Index: integer): Integer;
|
||||
protected
|
||||
function GetTabWidth : integer;
|
||||
procedure SetTabWidth(const AValue : integer);
|
||||
function GetExpandedString(Index: integer): string; override;
|
||||
function GetLengthOfLongestLine: integer; override;
|
||||
property LengthOfLine[Index: Integer]: integer
|
||||
read GetLengthOfLine write SetLengthOfLine;
|
||||
public
|
||||
constructor Create(ASynStringSource: TSynEditStrings);
|
||||
destructor Destroy; override;
|
||||
|
||||
property ExpandedStrings[Index: integer]: string read GetExpandedString;
|
||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
||||
|
||||
// TODO: maybe use inherited for utf8?
|
||||
function LogicalToPhysicalCol(Line: PChar; LineLen: integer;
|
||||
LogicalPos, StartBytePos,
|
||||
StartPhysicalPos: integer): integer; override;
|
||||
function PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos,
|
||||
StartPhysicalPos: integer): integer; override;
|
||||
public
|
||||
property TabWidth: integer read GetTabWidth write SetTabWidth;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
{ TSynEditStringTabExpander }
|
||||
|
||||
constructor TSynEditStringTabExpander.Create(ASynStringSource: TSynEditStrings);
|
||||
begin
|
||||
FIndexOfLongestLine := -1;
|
||||
inherited Create(ASynStringSource);
|
||||
RegisterAttribute(TSynEditStringTabExpander, SizeOf(Integer));
|
||||
FTabWidth := 8;
|
||||
fSynStrings.AddChangeHandler(senrLineCount, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
|
||||
fSynStrings.AddChangeHandler(senrLineChange, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
|
||||
end;
|
||||
|
||||
destructor TSynEditStringTabExpander.Destroy;
|
||||
begin
|
||||
fSynStrings.RemoveChangeHandler(senrLineChange, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
|
||||
fSynStrings.RemoveChangeHandler(senrLineCount, {$IFDEF FPC}@{$ENDIF}LineCountChanged);
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.GetLengthOfLine(Index: Integer): integer;
|
||||
begin
|
||||
Result := Integer(PtrUInt(Attribute[TSynEditStringTabExpander, Index]));
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTabExpander.SetLengthOfLine(Index: Integer; const AValue: integer);
|
||||
begin
|
||||
Attribute[TSynEditStringTabExpander, Index] := Pointer(PtrUInt(AValue));
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.GetTabWidth: integer;
|
||||
begin
|
||||
Result := FTabWidth;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTabExpander.SetTabWidth(const AValue: integer);
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
if FTabWidth = AValue then exit;
|
||||
|
||||
FTabWidth := AValue;
|
||||
FConvertTabsProc := GetBestConvertTabsProcEx(fTabWidth);
|
||||
FSimulateConvertTabsProc := GetBestSimulateConvertTabsProcEx(fTabWidth);
|
||||
FIndexOfLongestLine := -1;
|
||||
for i := 0 to Count - 1 do
|
||||
if not(LengthOfLine[i] >= NoTabLengthOffset) then
|
||||
LengthOfLine[i] := -1;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTabExpander.LineCountChanged(Sender: TSynEditStrings; AIndex, ACount: Integer);
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
FIndexOfLongestLine := -1;
|
||||
for i := AIndex to AIndex + ACount - 1 do
|
||||
LengthOfLine[i] := -1;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.ExpandedString(Index: integer): string;
|
||||
var
|
||||
HasTabs: boolean;
|
||||
begin
|
||||
if fSynStrings[Index] = '' then begin
|
||||
Result := '';
|
||||
LengthOfLine[Index] := 0 + NoTabLengthOffset;
|
||||
end else begin
|
||||
Result := fConvertTabsProc(fSynStrings[Index], fTabWidth, HasTabs);
|
||||
if HasTabs then
|
||||
LengthOfLine[Index] := length(Result)
|
||||
else
|
||||
LengthOfLine[Index] := length(Result) + NoTabLengthOffset;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.ExpandedStringLength(Index: integer): Integer;
|
||||
var
|
||||
HasTabs: boolean;
|
||||
begin
|
||||
if fSynStrings[Index] = '' then begin
|
||||
Result := 0;
|
||||
LengthOfLine[Index] := 0 + NoTabLengthOffset;
|
||||
end else begin
|
||||
Result := fSimulateConvertTabsProc(fSynStrings[Index], fTabWidth, HasTabs);
|
||||
if HasTabs then
|
||||
LengthOfLine[Index] := Result
|
||||
else
|
||||
LengthOfLine[Index] := Result + NoTabLengthOffset;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.GetExpandedString(Index: integer): string;
|
||||
begin
|
||||
if (Index >= 0) and (Index < Count) then begin
|
||||
if LengthOfLine[Index] >= NoTabLengthOffset then
|
||||
Result := fSynStrings[Index]
|
||||
else
|
||||
Result := ExpandedString(Index);
|
||||
end else
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.GetLengthOfLongestLine: integer;
|
||||
var
|
||||
i, j, MaxLen: integer;
|
||||
begin
|
||||
if fIndexOfLongestLine < 0 then begin
|
||||
MaxLen := 0;
|
||||
if Count > 0 then begin
|
||||
for i := 0 to Count - 1 do begin
|
||||
j := LengthOfLine[i];
|
||||
if j >= NoTabLengthOffset then j := j - NoTabLengthOffset;
|
||||
if j < 0 then
|
||||
j := ExpandedStringLength(i);
|
||||
if j > MaxLen then begin
|
||||
MaxLen := j;
|
||||
fIndexOfLongestLine := i;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
exit(MaxLen);
|
||||
end;
|
||||
if (fIndexOfLongestLine >= 0) and (fIndexOfLongestLine < Count) then begin
|
||||
Result := LengthOfLine[fIndexOfLongestLine];
|
||||
if Result >= NoTabLengthOffset then Result := Result - NoTabLengthOffset;
|
||||
end else
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.LogicalToPhysicalCol(Line: PChar;
|
||||
LineLen: integer; LogicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
var
|
||||
BytePos, ByteLen: integer;
|
||||
ScreenPos: integer;
|
||||
begin
|
||||
ByteLen := LineLen;
|
||||
// map UTF8 and Tab chars
|
||||
ScreenPos := StartPhysicalPos;
|
||||
BytePos:= StartBytePos;
|
||||
while BytePos<LogicalPos do begin
|
||||
if (BytePos <= ByteLen) then begin
|
||||
if Line[BytePos-1] = #9 then begin
|
||||
inc(ScreenPos, TabWidth - ((ScreenPos-1) mod TabWidth));
|
||||
inc(BytePos);
|
||||
end else begin
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@Line[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end;
|
||||
end else begin
|
||||
// beyond end of line
|
||||
inc(ScreenPos,LogicalPos-BytePos);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if (BytePos>LogicalPos) and (ScreenPos>StartPhysicalPos) then
|
||||
dec(ScreenPos);
|
||||
Result := ScreenPos;
|
||||
end;
|
||||
|
||||
function TSynEditStringTabExpander.PhysicalToLogicalCol(const Line: string;
|
||||
PhysicalPos, StartBytePos, StartPhysicalPos: integer): integer;
|
||||
var
|
||||
BytePos, ByteLen: integer;
|
||||
ScreenPos: integer;
|
||||
PLine: PChar;
|
||||
begin
|
||||
ByteLen := Length(Line);
|
||||
ScreenPos := StartPhysicalPos;
|
||||
BytePos := StartBytePos;
|
||||
PLine := PChar(Line);
|
||||
// map utf and tab chars
|
||||
while ScreenPos < PhysicalPos do begin
|
||||
if (BytePos <= ByteLen) then begin
|
||||
if (PLine[BytePos-1] <> #9) then begin
|
||||
inc(ScreenPos);
|
||||
if IsUTF8 then
|
||||
inc(BytePos,UTF8CharacterLength(@PLine[BytePos-1]))
|
||||
else
|
||||
inc(BytePos);
|
||||
end else begin
|
||||
inc(ScreenPos, TabWidth - ((ScreenPos-1) mod TabWidth));
|
||||
inc(BytePos);
|
||||
end;
|
||||
end else begin
|
||||
// beyond end of line
|
||||
inc(BytePos,PhysicalPos-ScreenPos);
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
if (ScreenPos>PhysicalPos) and (BytePos>1) and (BytePos-2<ByteLen)
|
||||
and (PLine[BytePos-2]=#9) then
|
||||
dec(BytePos);
|
||||
Result := BytePos;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
@ -35,9 +35,8 @@ type
|
||||
|
||||
{ TSynEditStringTrimmingList }
|
||||
|
||||
TSynEditStringTrimmingList = class(TSynEditStrings)
|
||||
TSynEditStringTrimmingList = class(TSynEditStringsLinked)
|
||||
private
|
||||
fSynStrings: TSynEditStrings;
|
||||
fCaret: TSynEditCaret;
|
||||
fUndoList: TSynEditUndoList;
|
||||
fSpaces: String;
|
||||
@ -53,31 +52,12 @@ type
|
||||
procedure DoLinesChanged(Index, N: integer);
|
||||
procedure TrimAfterLock;
|
||||
protected
|
||||
function GetIsUtf8 : Boolean; override;
|
||||
procedure SetIsUtf8(const AValue : Boolean); override;
|
||||
function GetTabWidth : integer; override;
|
||||
procedure SetTabWidth(const AValue : integer); override;
|
||||
function GetFoldEndLevel(Index: integer): integer; override;
|
||||
function GetFoldMinLevel(Index: integer): integer; override;
|
||||
procedure SetFoldEndLevel(Index: integer; const AValue: integer); override;
|
||||
procedure SetFoldMinLevel(Index: integer; const AValue: integer); override;
|
||||
function GetRange(Index: integer): TSynEditRange; override;
|
||||
procedure PutRange(Index: integer; ARange: TSynEditRange); override;
|
||||
|
||||
function GetCount: integer; override;
|
||||
function GetCapacity: integer;
|
||||
{$IFDEF SYN_COMPILER_3_UP} override; {$ENDIF}
|
||||
procedure SetCapacity(NewCapacity: integer);
|
||||
{$IFDEF SYN_COMPILER_3_UP} override; {$ENDIF}
|
||||
|
||||
function GetExpandedString(Index: integer): string; override;
|
||||
function GetLengthOfLongestLine: integer; override;
|
||||
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); override;
|
||||
public
|
||||
constructor Create(ASynStringSource: TSynEditStrings; ACaret: TSynEditCaret);
|
||||
destructor Destroy; override;
|
||||
@ -91,7 +71,6 @@ type
|
||||
procedure InsertLines(Index, NumLines: integer); override;
|
||||
procedure InsertStrings(Index: integer; NewStrings: TStrings); override;
|
||||
procedure Exchange(Index1, Index2: integer); override;
|
||||
procedure ClearRanges(ARange: TSynEditRange); override;
|
||||
property ExpandedStrings[Index: integer]: string read GetExpandedString;
|
||||
property LengthOfLongestLine: integer read GetLengthOfLongestLine;
|
||||
public
|
||||
@ -110,14 +89,13 @@ implementation
|
||||
|
||||
constructor TSynEditStringTrimmingList.Create(ASynStringSource : TSynEditStrings; ACaret: TSynEditCaret);
|
||||
begin
|
||||
fSynStrings := ASynStringSource;
|
||||
fCaret := ACaret;
|
||||
fCaret.AddChangeHandler(@DoCaretChanged);
|
||||
fLockList := TStringList.Create;
|
||||
fLineIndex:= -1;
|
||||
fSpaces := '';
|
||||
fEnabled:=false;
|
||||
Inherited Create;
|
||||
Inherited Create(ASynStringSource);
|
||||
end;
|
||||
|
||||
destructor TSynEditStringTrimmingList.Destroy;
|
||||
@ -127,14 +105,6 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.SetUpdateState(Updating : Boolean);
|
||||
begin
|
||||
if Updating then
|
||||
fSynStrings.BeginUpdate
|
||||
else
|
||||
fSynStrings.EndUpdate;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.DoCaretChanged(Sender : TObject);
|
||||
var
|
||||
s: String;
|
||||
@ -294,84 +264,11 @@ begin
|
||||
fLockList.Clear;
|
||||
end;
|
||||
|
||||
function TSynEditStringTrimmingList.GetIsUtf8 : Boolean;
|
||||
begin
|
||||
Result := FSynStrings.IsUtf8;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.SetIsUtf8(const AValue : Boolean);
|
||||
begin
|
||||
FSynStrings.IsUtf8 := AValue;
|
||||
end;
|
||||
|
||||
function TSynEditStringTrimmingList.GetTabWidth : integer;
|
||||
begin
|
||||
Result := FSynStrings.TabWidth;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.SetTabWidth(const AValue : integer);
|
||||
begin
|
||||
FSynStrings.TabWidth := AValue;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.ForceTrim;
|
||||
begin
|
||||
TrimAfterLock;
|
||||
end;
|
||||
|
||||
// Fold
|
||||
function TSynEditStringTrimmingList.GetFoldEndLevel(Index : integer) : integer;
|
||||
begin
|
||||
Result:= fSynStrings.FoldEndLevel[Index];
|
||||
end;
|
||||
|
||||
function TSynEditStringTrimmingList.GetFoldMinLevel(Index : integer) : integer;
|
||||
begin
|
||||
Result:= fSynStrings.FoldMinLevel[Index];
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.SetFoldEndLevel(Index : integer; const AValue : integer);
|
||||
begin
|
||||
fSynStrings.FoldEndLevel[Index] := AValue;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.SetFoldMinLevel(Index : integer; const AValue : integer);
|
||||
begin
|
||||
fSynStrings.FoldMinLevel[Index] := AValue;
|
||||
end;
|
||||
|
||||
// Range
|
||||
function TSynEditStringTrimmingList.GetRange(Index : integer) : TSynEditRange;
|
||||
begin
|
||||
Result:= fSynStrings.Ranges[Index];
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.PutRange(Index : integer; ARange : TSynEditRange);
|
||||
begin
|
||||
fSynStrings.Ranges[Index] := ARange;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.ClearRanges(ARange : TSynEditRange);
|
||||
begin
|
||||
fSynStrings.ClearRanges(ARange);
|
||||
end;
|
||||
|
||||
// Count
|
||||
function TSynEditStringTrimmingList.GetCount : integer;
|
||||
begin
|
||||
Result:= fSynStrings.Count;
|
||||
end;
|
||||
|
||||
function TSynEditStringTrimmingList.GetCapacity : integer;
|
||||
begin
|
||||
Result:= fSynStrings.Capacity;
|
||||
end;
|
||||
|
||||
procedure TSynEditStringTrimmingList.SetCapacity(NewCapacity : integer);
|
||||
begin
|
||||
fSynStrings.Capacity := NewCapacity;
|
||||
end;
|
||||
|
||||
// Lines
|
||||
function TSynEditStringTrimmingList.GetExpandedString(Index : integer) : string;
|
||||
begin
|
||||
|
||||
Loading…
Reference in New Issue
Block a user