mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-11 16:56:01 +02:00
SynEdit: fixed caret-auto-move for lines with tab. (required by syncro-edit, shared-edit)
git-svn-id: trunk@30087 -
This commit is contained in:
parent
9566d1e771
commit
6b7a173ac3
@ -176,6 +176,7 @@ type
|
||||
FLinePos: Integer; // 1 based
|
||||
FCharPos: Integer; // 1 based
|
||||
FLastCharPos: Integer; // used by KeepCaretX
|
||||
FBytePos, FBytePosOffset: Integer; // 1 based
|
||||
FOldLinePos: Integer; // 1 based
|
||||
FOldCharPos: Integer; // 1 based
|
||||
FAdjustToNextChar: Boolean;
|
||||
@ -185,6 +186,7 @@ type
|
||||
FTouched: Boolean;
|
||||
|
||||
procedure AdjustToChar;
|
||||
procedure UpdateBytePos;
|
||||
function GetOldLineBytePos: TPoint;
|
||||
function GetOldLineCharPos: TPoint;
|
||||
procedure InternalSetLineCharPos(NewLine, NewCharPos: Integer;
|
||||
@ -436,6 +438,8 @@ end;
|
||||
|
||||
procedure TSynEditCaret.IncAutoMoveOnEdit;
|
||||
begin
|
||||
if FAutoMoveOnEdit =0 then
|
||||
UpdateBytePos;;
|
||||
inc(FAutoMoveOnEdit);
|
||||
end;
|
||||
|
||||
@ -511,6 +515,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynEditCaret.UpdateBytePos;
|
||||
begin
|
||||
FBytePos := FLines.LogPhysConvertor.PhysicalToLogical(FLinePos-1, FCharPos, FBytePosOffset);
|
||||
end;
|
||||
|
||||
function TSynEditCaret.GetOldLineBytePos: TPoint;
|
||||
begin
|
||||
Result := FLines.PhysicalToLogicalPos(OldLineCharPos);
|
||||
@ -589,6 +598,8 @@ begin
|
||||
AdjustToChar;
|
||||
if (not KeepLastCharPos) or (not FKeepCaretX) then
|
||||
FLastCharPos := FCharPos;
|
||||
if FAutoMoveOnEdit <> 0 then
|
||||
UpdateBytePos;
|
||||
end;
|
||||
finally
|
||||
Unlock;
|
||||
@ -703,10 +714,17 @@ procedure TSynEditCaret.DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBytePo
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
p: TPoint;
|
||||
begin
|
||||
if FAutoMoveOnEdit > 0 then begin
|
||||
IncForcePastEOL;
|
||||
LineBytePos := AdjustPoint(LineBytePos);
|
||||
p := AdjustPoint(Point(FBytePos, FLinePos));
|
||||
p.x := FLines.LogPhysConvertor.LogicalToPhysical(p.y-1, p.x, FBytePosOffset);
|
||||
FBytePos := -1;
|
||||
LineCharPos := p;
|
||||
if FBytePos < 0 then
|
||||
UpdateBytePos;
|
||||
DecForcePastEOL;
|
||||
end;
|
||||
end;
|
||||
|
@ -242,6 +242,7 @@ type
|
||||
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;
|
||||
@ -469,11 +470,13 @@ procedure TSynLogicalPhysicalConvertor.PrepareWidthsForLine(AIndex: Integer;
|
||||
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;
|
||||
|
||||
@ -498,6 +501,7 @@ begin
|
||||
//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
|
||||
|
@ -587,18 +587,23 @@ var
|
||||
begin
|
||||
if (not fEnabled) then exit;
|
||||
FIsTrimming := True;
|
||||
IncViewChangeStamp;
|
||||
{$IFDEF SynTrimDebug}debugln(['--- Trimmer -- TrimAfterLock', ' fLineIndex=', fLineIndex, ' fSpaces=',length(fSpaces), ' Index=', Index, ' LockList=',fLockList.CommaText]);{$ENDIF}
|
||||
i := fLockList.IndexOfObject(TObject(Pointer(PtrUInt(fLineIndex))));
|
||||
if i >= 0 then begin
|
||||
if fSpaces <> fLockList[i] then
|
||||
IncViewChangeStamp;
|
||||
fSpaces:= fLockList[i];
|
||||
if (fLineIndex >= 0) and (fLineIndex < fSynStrings.Count) then
|
||||
fLineText := fSynStrings[fLineIndex];
|
||||
fLockList.Delete(i);
|
||||
DoCaretChanged(fCaret);
|
||||
end;
|
||||
end
|
||||
else if fSpaces <> '' then
|
||||
IncViewChangeStamp;
|
||||
FIsTrimming := True;
|
||||
BeginUpdate;
|
||||
if fLockList.Count > 0 then
|
||||
IncViewChangeStamp;
|
||||
try
|
||||
for i := 0 to fLockList.Count-1 do begin
|
||||
index := Integer(PtrUInt(Pointer(fLockList.Objects[i])));
|
||||
|
@ -7,7 +7,7 @@ interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, Forms, fpcunit, SynEdit, LCLType, LCLProc, math,
|
||||
SynEditTypes, Clipbrd;
|
||||
SynEditTypes, SynEditPointClasses, Clipbrd;
|
||||
|
||||
type
|
||||
|
||||
@ -24,6 +24,7 @@ type
|
||||
property ViewedTextBuffer;
|
||||
property TextBuffer;
|
||||
property TextView; // foldedview
|
||||
property CaretObj: TSynEditCaret read GetCaretObj;
|
||||
end;
|
||||
|
||||
{ TTestBase }
|
||||
@ -318,6 +319,7 @@ end;
|
||||
procedure TTestBase.TestFail(Name, Func, Expect, Got: String; Result: Boolean = False);
|
||||
begin
|
||||
if Result then exit;
|
||||
DebugLn(DbgStr(SynEdit.Text));
|
||||
if BaseTestName <> '' then
|
||||
Fail(Format('%s: %s (%s)%sExpected: %s%s Got: %s', [BaseTestName, Name, Func, LineEnding, Expect, LineEnding, Got]))
|
||||
else
|
||||
|
@ -28,6 +28,7 @@ type
|
||||
procedure TestEditEmpty;
|
||||
procedure TestEditTabs;
|
||||
procedure TestEditPhysicalLogical;
|
||||
procedure TestCaretAutoMove;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@ -249,6 +250,65 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
procedure TTestBasicSynEdit.TestCaretAutoMove;
|
||||
|
||||
procedure DoTest(name: string; y, x, insertY, insertX, InsertY2, InsertX2: integer;
|
||||
txt: string; expY, expX: Integer);
|
||||
begin
|
||||
name := name + ' y='+inttostr(y)+' x='+inttostr(x);
|
||||
if y > 0 then begin
|
||||
ReCreateEdit;
|
||||
SynEdit.TabWidth := 6;
|
||||
SetLines(['x', 'abc', ' ääX', #9'mn', 'abc'#9'de', #9'Xää.']);
|
||||
SynEdit.CaretXY := Point(x, y);
|
||||
end;
|
||||
|
||||
SynEdit.TextBetweenPointsEx[Point(insertX, insertY), point(insertX2, InsertY2), scamAdjust]
|
||||
:= txt;
|
||||
debugln(dbgstr(SynEdit.Text));
|
||||
TestIsCaretPhys(name, expX, expY);
|
||||
end;
|
||||
|
||||
const
|
||||
cr = LineEnding;
|
||||
begin
|
||||
|
||||
|
||||
DoTest('simple insert', 2,2, 2,1, 2,1, 'X', 2,3);
|
||||
DoTest('simple insert CR', 2,2, 2,1, 2,1, 'X'+cr, 3,2);
|
||||
DoTest('simple insert CR+', 2,2, 2,1, 2,1, cr+'X', 3,3);
|
||||
DoTest('simple delete', 2,2, 2,1, 2,2, '', 2,1);
|
||||
DoTest('simple delete CR', 2,2, 1,2, 2,1, '', 1,3);
|
||||
DoTest('+simple delete CR', 2,2, 1,1, 2,1, '', 1,2);
|
||||
|
||||
DoTest('simple insert (eol)', 2,4, 2,1, 2,1, 'X', 2,5);
|
||||
DoTest('simple insert (past eol)', 2,7, 2,1, 2,1, 'X', 2,8);
|
||||
|
||||
DoTest('insert with tab', 4,8, 4,1, 4,1, 'X', 4,8);
|
||||
DoTest('insert with tab (cont)', -4,8, 4,2, 4,2, 'Y', 4,8);
|
||||
DoTest('insert with tab (cont)', -4,8, 4,3, 4,3, 'abc', 4,8);
|
||||
DoTest('insert with tab (cont)', -4,8, 4,6, 4,6, 'Z', 4,14);
|
||||
DoTest('insert with tab (cont)', -4,8, 4,7, 4,7, '.', 4,14);
|
||||
DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,14);
|
||||
DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
|
||||
DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
|
||||
DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
|
||||
|
||||
|
||||
SynEdit.CaretObj.IncAutoMoveOnEdit;
|
||||
DoTest('insert with tab (am-block)', 4,8, 4,1, 4,1, 'X', 4,8);
|
||||
DoTest('insert with tab (am-block) (cont)', -4,8, 4,2, 4,2, 'Y', 4,8);
|
||||
DoTest('insert with tab (am-block) (cont)', -4,8, 4,3, 4,3, 'abc', 4,8);
|
||||
DoTest('insert with tab (am-block) (cont)', -4,8, 4,6, 4,6, 'Z', 4,14);
|
||||
DoTest('insert with tab (am-block) (cont)', -4,8, 4,7, 4,7, '.', 4,14);
|
||||
DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,14);
|
||||
DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
|
||||
DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
|
||||
DoTest('delete with tab (cont)', -4,8, 4,1, 4,2, '', 4,8);
|
||||
SynEdit.CaretObj.DecAutoMoveOnEdit;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
|
||||
initialization
|
||||
|
Loading…
Reference in New Issue
Block a user