mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 09:09:17 +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
|
FLinePos: Integer; // 1 based
|
||||||
FCharPos: Integer; // 1 based
|
FCharPos: Integer; // 1 based
|
||||||
FLastCharPos: Integer; // used by KeepCaretX
|
FLastCharPos: Integer; // used by KeepCaretX
|
||||||
|
FBytePos, FBytePosOffset: Integer; // 1 based
|
||||||
FOldLinePos: Integer; // 1 based
|
FOldLinePos: Integer; // 1 based
|
||||||
FOldCharPos: Integer; // 1 based
|
FOldCharPos: Integer; // 1 based
|
||||||
FAdjustToNextChar: Boolean;
|
FAdjustToNextChar: Boolean;
|
||||||
@ -185,6 +186,7 @@ type
|
|||||||
FTouched: Boolean;
|
FTouched: Boolean;
|
||||||
|
|
||||||
procedure AdjustToChar;
|
procedure AdjustToChar;
|
||||||
|
procedure UpdateBytePos;
|
||||||
function GetOldLineBytePos: TPoint;
|
function GetOldLineBytePos: TPoint;
|
||||||
function GetOldLineCharPos: TPoint;
|
function GetOldLineCharPos: TPoint;
|
||||||
procedure InternalSetLineCharPos(NewLine, NewCharPos: Integer;
|
procedure InternalSetLineCharPos(NewLine, NewCharPos: Integer;
|
||||||
@ -436,6 +438,8 @@ end;
|
|||||||
|
|
||||||
procedure TSynEditCaret.IncAutoMoveOnEdit;
|
procedure TSynEditCaret.IncAutoMoveOnEdit;
|
||||||
begin
|
begin
|
||||||
|
if FAutoMoveOnEdit =0 then
|
||||||
|
UpdateBytePos;;
|
||||||
inc(FAutoMoveOnEdit);
|
inc(FAutoMoveOnEdit);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -511,6 +515,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditCaret.UpdateBytePos;
|
||||||
|
begin
|
||||||
|
FBytePos := FLines.LogPhysConvertor.PhysicalToLogical(FLinePos-1, FCharPos, FBytePosOffset);
|
||||||
|
end;
|
||||||
|
|
||||||
function TSynEditCaret.GetOldLineBytePos: TPoint;
|
function TSynEditCaret.GetOldLineBytePos: TPoint;
|
||||||
begin
|
begin
|
||||||
Result := FLines.PhysicalToLogicalPos(OldLineCharPos);
|
Result := FLines.PhysicalToLogicalPos(OldLineCharPos);
|
||||||
@ -589,6 +598,8 @@ begin
|
|||||||
AdjustToChar;
|
AdjustToChar;
|
||||||
if (not KeepLastCharPos) or (not FKeepCaretX) then
|
if (not KeepLastCharPos) or (not FKeepCaretX) then
|
||||||
FLastCharPos := FCharPos;
|
FLastCharPos := FCharPos;
|
||||||
|
if FAutoMoveOnEdit <> 0 then
|
||||||
|
UpdateBytePos;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
Unlock;
|
Unlock;
|
||||||
@ -703,10 +714,17 @@ procedure TSynEditCaret.DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBytePo
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
p: TPoint;
|
||||||
begin
|
begin
|
||||||
if FAutoMoveOnEdit > 0 then begin
|
if FAutoMoveOnEdit > 0 then begin
|
||||||
IncForcePastEOL;
|
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;
|
DecForcePastEOL;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -242,6 +242,7 @@ type
|
|||||||
function PhysicalToLogicalPos(const p: TPoint): TPoint;
|
function PhysicalToLogicalPos(const p: TPoint): TPoint;
|
||||||
function PhysicalToLogicalCol(const Line: string;
|
function PhysicalToLogicalCol(const Line: string;
|
||||||
Index, PhysicalPos: integer): integer; virtual;
|
Index, PhysicalPos: integer): integer; virtual;
|
||||||
|
property LogPhysConvertor :TSynLogicalPhysicalConvertor read FLogPhysConvertor;
|
||||||
public
|
public
|
||||||
procedure EditInsert(LogX, LogY: Integer; AText: String); virtual; abstract;
|
procedure EditInsert(LogX, LogY: Integer; AText: String); virtual; abstract;
|
||||||
function EditDelete(LogX, LogY, ByteLen: Integer): String; virtual; abstract;
|
function EditDelete(LogX, LogY, ByteLen: Integer): String; virtual; abstract;
|
||||||
@ -469,11 +470,13 @@ procedure TSynLogicalPhysicalConvertor.PrepareWidthsForLine(AIndex: Integer;
|
|||||||
var
|
var
|
||||||
LineLen: Integer;
|
LineLen: Integer;
|
||||||
Line: PChar;
|
Line: PChar;
|
||||||
|
//const dbg_cnt: integer = 0;
|
||||||
begin
|
begin
|
||||||
if (not AForce) and (FCurrentLine = AIndex) and
|
if (not AForce) and (FCurrentLine = AIndex) and
|
||||||
(FLines.TextChangeStamp = FTextChangeStamp) and (FLines.ViewChangeStamp = FViewChangeStamp)
|
(FLines.TextChangeStamp = FTextChangeStamp) and (FLines.ViewChangeStamp = FViewChangeStamp)
|
||||||
then begin
|
then begin
|
||||||
//debugln(['**************** RE-USING widths: ', AIndex,' (',dbgs(Pointer(self)),')']);
|
//debugln(['**************** RE-USING widths: ', AIndex,' (',dbgs(Pointer(self)),')']);
|
||||||
|
//dbg_cnt := dbg_cnt + 1;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -498,6 +501,7 @@ begin
|
|||||||
//else begin
|
//else begin
|
||||||
// debugln(['**************** COMPUTING widths: ', AIndex,' (',dbgs(Pointer(self)),') alloc=',FCurrentWidthsAlloc]);
|
// debugln(['**************** COMPUTING widths: ', AIndex,' (',dbgs(Pointer(self)),') alloc=',FCurrentWidthsAlloc]);
|
||||||
end;
|
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;
|
FCurrentWidthsLen := LineLen;
|
||||||
if LineLen > 0 then
|
if LineLen > 0 then
|
||||||
|
@ -587,18 +587,23 @@ var
|
|||||||
begin
|
begin
|
||||||
if (not fEnabled) then exit;
|
if (not fEnabled) then exit;
|
||||||
FIsTrimming := True;
|
FIsTrimming := True;
|
||||||
IncViewChangeStamp;
|
|
||||||
{$IFDEF SynTrimDebug}debugln(['--- Trimmer -- TrimAfterLock', ' fLineIndex=', fLineIndex, ' fSpaces=',length(fSpaces), ' Index=', Index, ' LockList=',fLockList.CommaText]);{$ENDIF}
|
{$IFDEF SynTrimDebug}debugln(['--- Trimmer -- TrimAfterLock', ' fLineIndex=', fLineIndex, ' fSpaces=',length(fSpaces), ' Index=', Index, ' LockList=',fLockList.CommaText]);{$ENDIF}
|
||||||
i := fLockList.IndexOfObject(TObject(Pointer(PtrUInt(fLineIndex))));
|
i := fLockList.IndexOfObject(TObject(Pointer(PtrUInt(fLineIndex))));
|
||||||
if i >= 0 then begin
|
if i >= 0 then begin
|
||||||
|
if fSpaces <> fLockList[i] then
|
||||||
|
IncViewChangeStamp;
|
||||||
fSpaces:= fLockList[i];
|
fSpaces:= fLockList[i];
|
||||||
if (fLineIndex >= 0) and (fLineIndex < fSynStrings.Count) then
|
if (fLineIndex >= 0) and (fLineIndex < fSynStrings.Count) then
|
||||||
fLineText := fSynStrings[fLineIndex];
|
fLineText := fSynStrings[fLineIndex];
|
||||||
fLockList.Delete(i);
|
fLockList.Delete(i);
|
||||||
DoCaretChanged(fCaret);
|
DoCaretChanged(fCaret);
|
||||||
end;
|
end
|
||||||
|
else if fSpaces <> '' then
|
||||||
|
IncViewChangeStamp;
|
||||||
FIsTrimming := True;
|
FIsTrimming := True;
|
||||||
BeginUpdate;
|
BeginUpdate;
|
||||||
|
if fLockList.Count > 0 then
|
||||||
|
IncViewChangeStamp;
|
||||||
try
|
try
|
||||||
for i := 0 to fLockList.Count-1 do begin
|
for i := 0 to fLockList.Count-1 do begin
|
||||||
index := Integer(PtrUInt(Pointer(fLockList.Objects[i])));
|
index := Integer(PtrUInt(Pointer(fLockList.Objects[i])));
|
||||||
|
@ -7,7 +7,7 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Forms, fpcunit, SynEdit, LCLType, LCLProc, math,
|
Classes, SysUtils, Forms, fpcunit, SynEdit, LCLType, LCLProc, math,
|
||||||
SynEditTypes, Clipbrd;
|
SynEditTypes, SynEditPointClasses, Clipbrd;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -24,6 +24,7 @@ type
|
|||||||
property ViewedTextBuffer;
|
property ViewedTextBuffer;
|
||||||
property TextBuffer;
|
property TextBuffer;
|
||||||
property TextView; // foldedview
|
property TextView; // foldedview
|
||||||
|
property CaretObj: TSynEditCaret read GetCaretObj;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TTestBase }
|
{ TTestBase }
|
||||||
@ -318,6 +319,7 @@ end;
|
|||||||
procedure TTestBase.TestFail(Name, Func, Expect, Got: String; Result: Boolean = False);
|
procedure TTestBase.TestFail(Name, Func, Expect, Got: String; Result: Boolean = False);
|
||||||
begin
|
begin
|
||||||
if Result then exit;
|
if Result then exit;
|
||||||
|
DebugLn(DbgStr(SynEdit.Text));
|
||||||
if BaseTestName <> '' then
|
if BaseTestName <> '' then
|
||||||
Fail(Format('%s: %s (%s)%sExpected: %s%s Got: %s', [BaseTestName, Name, Func, LineEnding, Expect, LineEnding, Got]))
|
Fail(Format('%s: %s (%s)%sExpected: %s%s Got: %s', [BaseTestName, Name, Func, LineEnding, Expect, LineEnding, Got]))
|
||||||
else
|
else
|
||||||
|
@ -28,6 +28,7 @@ type
|
|||||||
procedure TestEditEmpty;
|
procedure TestEditEmpty;
|
||||||
procedure TestEditTabs;
|
procedure TestEditTabs;
|
||||||
procedure TestEditPhysicalLogical;
|
procedure TestEditPhysicalLogical;
|
||||||
|
procedure TestCaretAutoMove;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -249,6 +250,65 @@ begin
|
|||||||
|
|
||||||
end;
|
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
|
initialization
|
||||||
|
Loading…
Reference in New Issue
Block a user