SynEdit: Move caret up/down by viewed line.

git-svn-id: trunk@63283 -
This commit is contained in:
martin 2020-06-03 23:28:15 +00:00
parent c326b7a628
commit 80b71e85fb
5 changed files with 318 additions and 31 deletions

View File

@ -152,14 +152,16 @@ type
function GetCurrentLine: Integer;
function GetCurrentWidths: PPhysicalCharWidth;
procedure PrepareWidthsForLine(AIndex: Integer; AForce: Boolean = False);
procedure SetCurrentLine(AValue: Integer);
protected
procedure SetWidthsForLine(AIndex: Integer; ANewWidths: TPhysicalCharWidths);
public
constructor Create(ALines: TSynEditStrings);
destructor Destroy; override;
property CurrentLine: Integer read GetCurrentLine;
property CurrentLine: Integer read GetCurrentLine write SetCurrentLine;
property CurrentWidths: PPhysicalCharWidth read GetCurrentWidths;
property CurrentWidthsDirect: TPhysicalCharWidths read FCurrentWidths; // may be longer than needed
property CurrentWidthsCount: Integer read FCurrentWidthsLen;
public
// Line is 0-based // Column is 1-based
@ -245,6 +247,24 @@ type
LPosFlag = (lpAllowPastEol, lpAdjustToNext, lpStopAtCodePoint);
LPosFlags = set of LPosFlag;
TViewedXYInfoFlag = (
vifAdjustLogXYToNextChar, // If PhysPos is not at a char bound, the bound to the NextChar will be used. (Otherwise no adjustment)
vifReturnPhysXY,
vifReturnLogXY, // return alternative coordinates
vifReturnLogEOL, // Return the logXPos of the EOL / -1 on a wrapped line
vifReturnPhysOffset // Physical distance of returned-ViewedPos.X from begin of LogPos
);
TViewedXYInfoFlags = set of TViewedXYInfoFlag;
TViewedXYInfo = record
CorrectedViewedXY: TPhysPoint; // Moved inside the wrapping bounds
PhysXY: TPhysPoint;
LogicalXY: TLogCaretPoint;
PhysBoundOffset: Integer;
LogEOLPos: Integer;
FirstViewedX: IntPos;
end;
{ TSynEditStrings }
TSynEditStrings = class(TSynEditStringsBase)
@ -283,6 +303,9 @@ type
procedure DoGetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer; PWidths: PPhysicalCharWidth); virtual; abstract;
procedure InternalGetInfoForViewedXY(AViewedXY: TPhysPoint; AFlags: TViewedXYInfoFlags;
out AViewedXYInfo: TViewedXYInfo; ALogPhysConvertor :TSynLogicalPhysicalConvertor); virtual;
function GetDisplayView: TLazSynDisplayView; virtual;
public
constructor Create;
@ -335,6 +358,8 @@ type
function ViewToTextIndex(aViewIndex : TLineIdx) : TLineIdx; virtual;
function AddVisibleOffsetToTextIndex(aTextIndex: TLineIdx; LineOffset : Integer) : TLineIdx; virtual; (* Add/Sub to/from TextIndex (0-based) skipping invisible (folded) *)
procedure GetInfoForViewedXY(AViewedXY: TPhysPoint; AFlags: TViewedXYInfoFlags; out AViewedXYInfo: TViewedXYInfo);
// ViewedToPhysAndLog
(* Convert between TextBuffer and ViewedText
X/Y are all 1-based
*)
@ -431,6 +456,10 @@ type
procedure SetUpdateState(Updating: Boolean; Sender: TObject); override;
procedure DoGetPhysicalCharWidths(Line: PChar; LineLen, Index: Integer; PWidths: PPhysicalCharWidth); override;
procedure InternalGetInfoForViewedXY(AViewedXY: TPhysPoint;
AFlags: TViewedXYInfoFlags; out AViewedXYInfo: TViewedXYInfo;
ALogPhysConvertor: TSynLogicalPhysicalConvertor); override;
function GetDisplayView: TLazSynDisplayView; override;
procedure AddGenericHandler(AReason: TSynEditNotifyReason; AHandler: TMethod);
@ -492,7 +521,10 @@ type
function ViewToTextIndex(aViewIndex : TLineIdx) : TLineIdx; override;
function AddVisibleOffsetToTextIndex(aTextIndex: TLineIdx; LineOffset: Integer): TLineIdx; override;
// ViewedToPhysAndLog
(* Convert between TextBuffer and ViewedText
X/Y are all 1-based
*)
function ViewXYToTextXY(APhysViewXY: TPhysPoint): TPhysPoint; override;
function TextXYToViewXY(APhysTextXY: TPhysPoint): TPhysPoint; override;
public
@ -699,6 +731,11 @@ begin
FCurrentLine := AIndex;
end;
procedure TSynLogicalPhysicalConvertor.SetCurrentLine(AValue: Integer);
begin
PrepareWidthsForLine(AValue);
end;
function TSynLogicalPhysicalConvertor.GetCurrentWidths: PPhysicalCharWidth;
begin
if FCurrentWidthsLen > 0
@ -1177,6 +1214,34 @@ begin
EndUpdate(nil);
end;
procedure TSynEditStrings.InternalGetInfoForViewedXY(AViewedXY: TPhysPoint;
AFlags: TViewedXYInfoFlags; out AViewedXYInfo: TViewedXYInfo;
ALogPhysConvertor: TSynLogicalPhysicalConvertor);
var
Offs: Integer;
begin
AViewedXYInfo.CorrectedViewedXY := AViewedXY;
if AFlags * [vifReturnPhysXY, vifReturnLogEOL] <> [] then begin
AViewedXYInfo.PhysXY := AViewedXYInfo.CorrectedViewedXY;
end;
if AFlags * [vifReturnLogXY, vifReturnPhysOffset] <> [] then begin
AViewedXYInfo.LogicalXY.y := AViewedXYInfo.PhysXY.y;
if vifAdjustLogXYToNextChar in AFlags then
AViewedXYInfo.LogicalXY.x := ALogPhysConvertor.PhysicalToLogical(ToIdx(AViewedXYInfo.PhysXY.y), AViewedXYInfo.PhysXY.x, Offs, cspDefault, [lpfAdjustToNextChar])
else
AViewedXYInfo.LogicalXY.x := ALogPhysConvertor.PhysicalToLogical(ToIdx(AViewedXYInfo.PhysXY.y), AViewedXYInfo.PhysXY.x, Offs, cspDefault, [lpfAdjustToCharBegin]);
AViewedXYInfo.LogicalXY.Offs := ALogPhysConvertor.UnAdjustedPhysToLogColOffs;
AViewedXYInfo.PhysBoundOffset := AViewedXYInfo.PhysXY.x - ALogPhysConvertor.AdjustedPhysToLogOrigin;
end;
if AFlags * [vifReturnLogEOL] <> [] then
AViewedXYInfo.LogEOLPos := ALogPhysConvertor.CurrentWidthsCount + 1;
// TODO wrap subline bounds
end;
function TSynEditStrings.LogicalToPhysicalPos(const p : TPoint) : TPoint;
begin
Result := p;
@ -1231,6 +1296,13 @@ begin
Result := aTextIndex + LineOffset;
end;
procedure TSynEditStrings.GetInfoForViewedXY(AViewedXY: TPhysPoint;
AFlags: TViewedXYInfoFlags; out AViewedXYInfo: TViewedXYInfo);
begin
InternalGetInfoForViewedXY(AViewedXY, AFlags, AViewedXYInfo,
LogPhysConvertor);
end;
function TSynEditStrings.ViewXYToTextXY(APhysViewXY: TPhysPoint): TPhysPoint;
begin
Result := APhysViewXY;
@ -1526,6 +1598,14 @@ begin
fSynStringsPhys.DoGetPhysicalCharWidths(Line, LineLen, Index, PWidths);
end;
procedure TSynEditStringsLinked.InternalGetInfoForViewedXY(
AViewedXY: TPhysPoint; AFlags: TViewedXYInfoFlags; out
AViewedXYInfo: TViewedXYInfo; ALogPhysConvertor: TSynLogicalPhysicalConvertor
);
begin
fSynStrings.InternalGetInfoForViewedXY(AViewedXY, AFlags, AViewedXYInfo, ALogPhysConvertor);
end;
function TSynEditStringsLinked.GetDisplayView: TLazSynDisplayView;
begin
Result := fSynStrings.GetDisplayView;

View File

@ -789,7 +789,7 @@ type
function IsPointInSelection(Value: TPoint): boolean;
procedure LockUndo;
procedure MoveCaretHorz(DX: integer);
procedure MoveCaretVert(DY: integer);
procedure MoveCaretVert(DY: integer; UseScreenLine: Boolean = False);
procedure PrimarySelectionRequest(const RequestedFormatID: TClipboardFormat;
Data: TStream);
procedure ScanRanges(ATextChanged: Boolean = True);
@ -6974,11 +6974,11 @@ begin
// vertical caret movement or selection
ecUp, ecSelUp, ecColSelUp:
begin
MoveCaretVert(-1);
MoveCaretVert(-1, (Command = ecUp) or (Command = ecSelUp) );
end;
ecDown, ecSelDown, ecColSelDown:
begin
MoveCaretVert(1);
MoveCaretVert(1, (Command = ecDown) or (Command = ecSelDown));
end;
ecPageUp, ecSelPageUp, ecPageDown, ecSelPageDown, ecColSelPageUp, ecColSelPageDown:
begin
@ -6990,7 +6990,10 @@ begin
if (Command in [ecPageUp, ecSelPageUp, ecColSelPageUp]) then
counter := -counter;
TopView := TopView + counter;
MoveCaretVert(counter);
MoveCaretVert(counter,
(Command = ecPageUp) or (Command = ecSelPageUp) or
(Command = ecPageDown) or (Command = ecSelPageDown)
);
end;
ecPageTop, ecSelPageTop, ecColSelPageTop:
begin
@ -8615,17 +8618,20 @@ begin
end;
end;
procedure TCustomSynEdit.MoveCaretVert(DY: integer);
procedure TCustomSynEdit.MoveCaretVert(DY: integer; UseScreenLine: Boolean);
// moves Caret vertical DY unfolded lines
var
NewCaret: TPoint;
OldCaret: TPoint;
begin
OldCaret:=CaretXY;
NewCaret:=OldCaret;
NewCaret.Y:=ToPos(FTheLinesView.AddVisibleOffsetToTextIndex(ToIdx(NewCaret.Y), DY));
DoIncPaintLock(Self); // No editing is taking place
FCaret.LinePos := NewCaret.Y;
if UseScreenLine then begin
FCaret.ViewedLinePos := FCaret.ViewedLinePos + DY;
end
else begin
NewCaret:=CaretXY;
NewCaret.Y:=ToPos(FTheLinesView.AddVisibleOffsetToTextIndex(ToIdx(NewCaret.Y), DY));
FCaret.LinePos := NewCaret.Y;
end;
DoDecPaintLock(Self);
end;

View File

@ -414,6 +414,9 @@ type
function GetViewedLines(index : Integer) : String; override;
function GetViewedCount: integer; override;
function GetDisplayView: TLazSynDisplayView; override;
procedure InternalGetInfoForViewedXY(AViewedXY: TPhysPoint;
AFlags: TViewedXYInfoFlags; out AViewedXYInfo: TViewedXYInfo;
ALogPhysConvertor: TSynLogicalPhysicalConvertor); override;
procedure DoBlockSelChanged(Sender: TObject);
Procedure CalculateMaps;
function FoldNodeAtTextIndex(AStartIndex, ColIndex: Integer): TSynTextFoldAVLNode; (* Returns xth Fold at nth TextIndex (all lines in buffer) / 1-based *)
@ -3284,6 +3287,15 @@ begin
Result := FDisplayView;
end;
procedure TSynEditFoldedView.InternalGetInfoForViewedXY(AViewedXY: TPhysPoint;
AFlags: TViewedXYInfoFlags; out AViewedXYInfo: TViewedXYInfo;
ALogPhysConvertor: TSynLogicalPhysicalConvertor);
begin
AViewedXY.y := ToPos(InternViewToTextIndex(ToIdx(AViewedXY.y)));
inherited InternalGetInfoForViewedXY(AViewedXY, AFlags, AViewedXYInfo,
ALogPhysConvertor);
end;
function TSynEditFoldedView.GetFoldClasifications(index : Integer): TFoldNodeClassifications;
begin
if (index < -1) or (index > fLinesInWindow + 1) then exit([]);

View File

@ -231,8 +231,11 @@ type
{ TSynEditCaret }
TSynEditCaretFlag = (
// TSynEditBaseCaret
scCharPosValid, scBytePosValid, scViewedPosValid,
scHasLineMapHandler
scHasLineMapHandler,
// TSynEditCaret
scfUpdateLastCaretX
);
TSynEditCaretFlags = set of TSynEditCaretFlag;
@ -251,7 +254,6 @@ type
TSynEditBaseCaret = class(TSynEditPointBase)
private
FFlags: TSynEditCaretFlags;
FLinePos: Integer; // 1 based
FCharPos: Integer; // 1 based
FBytePos, FBytePosOffset: Integer; // 1 based
@ -266,6 +268,7 @@ type
function GetLineBytePos: TPoint;
function GetLineCharPos: TPoint;
function GetViewedLineCharPos: TPoint;
function GetViewedLinePos: TLinePos;
procedure SetBytePos(AValue: Integer);
procedure SetBytePosOffset(AValue: Integer);
procedure SetCharPos(AValue: Integer);
@ -276,15 +279,21 @@ type
function GetLineText: string;
procedure SetLineText(AValue: string);
procedure SetViewedLineCharPos(AValue: TPoint);
procedure SetViewedLinePos(AValue: TLinePos);
protected
FFlags: TSynEditCaretFlags;
procedure ValidateBytePos;
procedure ValidateCharPos;
procedure ValidateViewedPos;
procedure InternalEmptyLinesSetPos(NewCharPos: Integer; UpdFlags: TSynEditCaretUpdateFlags); virtual;
procedure InternalSetLineCharPos(NewLine, NewCharPos: Integer;
UpdFlags: TSynEditCaretUpdateFlags); virtual;
procedure InternalSetLineByterPos(NewLine, NewBytePos, NewByteOffs: Integer;
UpdFlags: TSynEditCaretUpdateFlags); virtual;
procedure InternalSetViewedPos(NewLine, NewCharPos: Integer;
UpdFlags: TSynEditCaretUpdateFlags); virtual;
public
constructor Create;
procedure AssignFrom(Src: TSynEditBaseCaret);
@ -303,7 +312,8 @@ type
property BytePosOffset: Integer read GetBytePosOffset write SetBytePosOffset;
property LineBytePos: TPoint read GetLineBytePos write SetLineBytePos;
property FullLogicalPos: TLogCaretPoint read GetFullLogicalPos write SetFullLogicalPos;
property ViewedLineCharPos: TPoint read GetViewedLineCharPos;
property ViewedLineCharPos: TPoint read GetViewedLineCharPos write SetViewedLineCharPos;
property ViewedLinePos: TLinePos read GetViewedLinePos write SetViewedLinePos;
property LineText: string read GetLineText write SetLineText;
end;
@ -318,7 +328,7 @@ type
FForcePastEOL: Integer;
FForceAdjustToNextChar: Integer;
FKeepCaretX: Boolean;
FLastCharPos: Integer; // used by KeepCaretX
FLastCharPos, FLastViewedCharPos: Integer; // used by KeepCaretX
FOldLinePos: Integer; // 1 based
FOldCharPos: Integer; // 1 based
@ -339,6 +349,7 @@ type
procedure SetAllowPastEOL(const AValue: Boolean);
procedure SetSkipTabs(const AValue: Boolean);
procedure SetKeepCaretX(const AValue: Boolean);
procedure UpdateLastCaretX;
procedure RegisterLinesEditedHandler;
protected
@ -347,6 +358,8 @@ type
UpdFlags: TSynEditCaretUpdateFlags); override;
procedure InternalSetLineByterPos(NewLine, NewBytePos, NewByteOffs: Integer;
UpdFlags: TSynEditCaretUpdateFlags); override;
procedure InternalSetViewedPos(NewLine, NewCharPos: Integer;
UpdFlags: TSynEditCaretUpdateFlags); override;
procedure DoLock; override;
Procedure DoUnlock; override;
@ -697,9 +710,7 @@ end;
function TSynEditBaseCaret.GetViewedLineCharPos: TPoint;
begin
if not(scViewedPosValid in FFlags) then
FViewedLineCharPos := Lines.TextXYToViewXY(LineCharPos);
include(FFlags, scViewedPosValid);
ValidateViewedPos;
Result := FViewedLineCharPos;
if scHasLineMapHandler in FFlags then begin
Lines.AddChangeHandler(senrLineMappingChanged, @DoLinesMappingChanged);
@ -707,6 +718,11 @@ begin
end;
end;
function TSynEditBaseCaret.GetViewedLinePos: TLinePos;
begin
Result := ViewedLineCharPos.y;
end;
procedure TSynEditBaseCaret.SetBytePos(AValue: Integer);
begin
InternalSetLineByterPos(FLinePos, AValue, 0, [scuChangedX]);
@ -762,24 +778,57 @@ begin
FLines[LinePos - 1] := AValue;
end;
procedure TSynEditBaseCaret.SetViewedLineCharPos(AValue: TPoint);
begin
InternalSetViewedPos(AValue.y, AValue.x, [scuChangedX, scuChangedY]);
end;
procedure TSynEditBaseCaret.SetViewedLinePos(AValue: TLinePos);
begin
ValidateViewedPos;
InternalSetViewedPos(AValue, FViewedLineCharPos.x, [scuChangedY]);
end;
procedure TSynEditBaseCaret.ValidateBytePos;
begin
if scBytePosValid in FFlags then
exit;
ValidateCharPos;
assert(scCharPosValid in FFlags, 'ValidateBytePos: no charpos set');
Include(FFlags, scBytePosValid);
FBytePos := FLines.LogPhysConvertor.PhysicalToLogical(FLinePos-1, FCharPos, FBytePosOffset);
end;
procedure TSynEditBaseCaret.ValidateCharPos;
var
p: TPhysPoint;
begin
if scCharPosValid in FFlags then
exit;
if not(scBytePosValid in FFlags) then begin
assert(scViewedPosValid in FFlags, 'ValidateCharPos: no viewedpos set');
Include(FFlags, scCharPosValid);
p := Lines.ViewXYToTextXY(FViewedLineCharPos);
FCharPos := p.x;
FLinePos := p.y;
exit;
end;
assert(scBytePosValid in FFlags, 'ValidateCharPos: no bytepos set');
Include(FFlags, scCharPosValid);
FCharPos := FLines.LogPhysConvertor.LogicalToPhysical(FLinePos-1, FBytePos, FBytePosOffset);
end;
procedure TSynEditBaseCaret.ValidateViewedPos;
begin
if scViewedPosValid in FFlags then
exit;
include(FFlags, scViewedPosValid);
FViewedLineCharPos := Lines.TextXYToViewXY(LineCharPos);
end;
procedure TSynEditBaseCaret.InternalEmptyLinesSetPos(NewCharPos: Integer;
UpdFlags: TSynEditCaretUpdateFlags);
begin
@ -789,7 +838,9 @@ begin
FLinePos := 1;
FBytePos := NewCharPos;
FCharPos := NewCharPos;
FFlags := FFlags + [scBytePosValid, scCharPosValid];
FViewedLineCharPos.y := 1;
FViewedLineCharPos.x := NewCharPos;
FFlags := FFlags + [scBytePosValid, scCharPosValid, scViewedPosValid];
end;
procedure TSynEditBaseCaret.InternalSetLineCharPos(NewLine, NewCharPos: Integer;
@ -845,6 +896,31 @@ begin
FLinePos := NewLine;
end;
procedure TSynEditBaseCaret.InternalSetViewedPos(NewLine, NewCharPos: Integer;
UpdFlags: TSynEditCaretUpdateFlags);
begin
if (FViewedLineCharPos.x = NewCharPos) and (FViewedLineCharPos.y= NewLine) and
(scViewedPosValid in FFlags) and not (scuForceSet in UpdFlags)
then
exit;
if not (scuNoInvalidate in UpdFlags) then
FFlags := FFlags - [scCharPosValid, scBytePosValid];
Include(FFlags, scViewedPosValid);
if NewLine < 1 then begin
NewLine := 1;
FFlags := FFlags - [scCharPosValid, scBytePosValid];
end;
if NewCharPos < 1 then begin
NewCharPos := 1;
FFlags := FFlags - [scCharPosValid, scBytePosValid];
end;
FViewedLineCharPos := Point(NewCharPos, NewLine);
end;
constructor TSynEditBaseCaret.Create;
begin
inherited Create;
@ -1000,10 +1076,11 @@ begin
inherited AssignFrom(Src);
if Src is TSynEditCaret then begin
FMaxLeftChar := TSynEditCaret(Src).FMaxLeftChar;
FAllowPastEOL := TSynEditCaret(Src).FAllowPastEOL;
FKeepCaretX := TSynEditCaret(Src).FKeepCaretX;
FLastCharPos := TSynEditCaret(Src).FLastCharPos;
FMaxLeftChar := TSynEditCaret(Src).FMaxLeftChar;
FAllowPastEOL := TSynEditCaret(Src).FAllowPastEOL;
FKeepCaretX := TSynEditCaret(Src).FKeepCaretX;
FLastCharPos := TSynEditCaret(Src).FLastCharPos;
FLastViewedCharPos := TSynEditCaret(Src).FLastViewedCharPos
end
else begin
AdjustToChar;
@ -1027,6 +1104,8 @@ begin
FChangeOnTouch := False;
ValidateCharPos;
//ValidateBytePos;
if scfUpdateLastCaretX in FFLags then
UpdateLastCaretX;
if (FOldCharPos <> FCharPos) or (FOldLinePos <> FLinePos) or FTouched then
fOnChangeList.CallNotifyEvents(self);
// All notifications called, reset oldpos
@ -1170,7 +1249,11 @@ begin
inherited InternalEmptyLinesSetPos(NewCharPos, UpdFlags);
if (scuChangedX in UpdFlags) then begin
//UpdateLastCaretX;
// No need to wait for UnLock
FLastCharPos := FCharPos;
FLastViewedCharPos := ViewedLineCharPos.x;
Exclude(FFLags, scfUpdateLastCaretX);
end;
end;
@ -1191,7 +1274,7 @@ begin
then begin
// Lines may have changed, so the other pos can be invalid
if not (scuNoInvalidate in UpdFlags) then
Exclude(FFlags, scBytePosValid);
FFlags := FFlags - [scBytePosValid, scViewedPosValid];
exit;
end;
@ -1250,8 +1333,8 @@ begin
inherited InternalSetLineCharPos(NewLine, NewCharPos, UpdFlags);
inherited InternalSetLineByterPos(NewLine, NewLogCharPos, Offs, [scuNoInvalidate, scuChangedX]);
if (scuChangedX in UpdFlags) or (not FKeepCaretX) then
FLastCharPos := FCharPos;
if (scuChangedX in UpdFlags) then
UpdateLastCaretX;
end;
finally
Unlock;
@ -1278,7 +1361,7 @@ begin
then begin
// Lines may have changed, so the other pos can be invalid
if not (scuNoInvalidate in UpdFlags) then
Exclude(FFlags, scCharPosValid);
FFlags := FFlags - [scCharPosValid, scViewedPosValid];
exit;
end;
@ -1331,8 +1414,94 @@ begin
inherited InternalSetLineByterPos(NewLine, NewBytePos, NewByteOffs, UpdFlags);
inherited InternalSetLineCharPos(NewLine, NewCharPos, [scuNoInvalidate, scuChangedX]);
if (scuChangedX in UpdFlags) and FKeepCaretX then
FLastCharPos := FCharPos;
if (scuChangedX in UpdFlags) then
UpdateLastCaretX;
end;
finally
Unlock;
end;
end;
procedure TSynEditCaret.InternalSetViewedPos(NewLine, NewCharPos: Integer;
UpdFlags: TSynEditCaretUpdateFlags);
var
EolOffs, NewPhysX: Integer;
Flags: TViewedXYInfoFlags;
Info: TViewedXYInfo;
begin
if not (scuChangedX in UpdFlags) and FKeepCaretX then
NewCharPos := FLastViewedCharPos;
Lock;
FTouched := True;
try
if (FViewedLineCharPos.x = NewCharPos) and (FViewedLineCharPos.y = NewLine) and
(scViewedPosValid in FFlags) and not (scuForceSet in UpdFlags)
then begin
// Lines may have changed, so the other pos can be invalid
if not (scuNoInvalidate in UpdFlags) then
FFlags := FFlags - [scBytePosValid, scCharPosValid];
exit;
end;
if NewLine < 1 then begin
NewLine := 1;
Exclude(UpdFlags, scuNoInvalidate);
end
else
if NewLine > FLines.ViewedCount then begin
NewLine := FLines.ViewedCount;
Exclude(UpdFlags, scuNoInvalidate);
end;
if FLines.Count = 0 then begin // Only allowed, if Lines.Count = 0
InternalEmptyLinesSetPos(NewCharPos, UpdFlags);
end else begin
Flags := [vifReturnPhysXY, vifReturnLogXY, vifReturnLogEOL, vifReturnPhysOffset];
if FAdjustToNextChar or (FForceAdjustToNextChar > 0) then
Flags := Flags + [vifAdjustLogXYToNextChar]; // can go to next wrapped line
Lines.GetInfoForViewedXY(Point(NewCharPos, NewLine), Flags, Info);
if (Info.LogicalXY.Offs <> 0) then begin
if FSkipTabs or (Lines[ToIdx(Info.LogicalXY.y)][Info.LogicalXY.x] <> #9) then begin
Info.LogicalXY.Offs := 0;
Info.CorrectedViewedXY.X := Info.CorrectedViewedXY.X - Info.PhysBoundOffset;
Info.PhysXY.X := Info.PhysXY.X - Info.PhysBoundOffset;
if Info.CorrectedViewedXY.x < Info.FirstViewedX then begin
Info.LogicalXY.X := Info.LogicalXY.X + 1;
Info.LogicalXY.Offs := 0;
NewPhysX := Lines.LogPhysConvertor.LogicalToPhysical( ToIdx(Info.LogicalXY.y), Info.LogicalXY.x, Info.LogicalXY.Offs, cslDefault, []);
Info.CorrectedViewedXY.x := Info.CorrectedViewedXY.x + NewPhysX - Info.PhysXY.x;
Info.PhysXY.x := NewPhysX;
end;
end;
end;
//if TestEOL and (Info.LogicalXY.X > Info.LogEOLPos) then begin
if (Info.LogicalXY.X > Info.LogEOLPos) then begin
if FAllowPastEOL or (FForcePastEOL > 0) then
EolOffs := Max(0, Info.PhysXY.X - GetMaxLeftPastEOL)
else
EolOffs := Info.LogicalXY.X - Info.LogEOLPos;
Info.CorrectedViewedXY.X := Info.CorrectedViewedXY.X - EolOffs;
Info.LogicalXY.X := Info.LogicalXY.X - EolOffs;
Info.PhysXY.X := Info.PhysXY.X - EolOffs;
Exclude(UpdFlags, scuNoInvalidate);
end;
if NewCharPos < 1 then begin
NewCharPos := 1;
Exclude(UpdFlags, scuNoInvalidate);
end;
inherited InternalSetLineCharPos(Info.PhysXY.Y, Info.PhysXY.X, UpdFlags);
inherited InternalSetLineByterPos(Info.LogicalXY.Y, Info.LogicalXY.X, Info.LogicalXY.Offs, [scuNoInvalidate, scuChangedX]);
inherited InternalSetViewedPos(Info.CorrectedViewedXY.Y, Info.CorrectedViewedXY.X, UpdFlags + [scuNoInvalidate]);
if (scuChangedX in UpdFlags) then
UpdateLastCaretX;
end;
finally
Unlock;
@ -1375,10 +1544,28 @@ begin
FKeepCaretX := AValue;
if FKeepCaretX then begin
ValidateCharPos;
FLastCharPos := FCharPos;
UpdateLastCaretX;
end;
end;
procedure TSynEditCaret.UpdateLastCaretX;
begin
if not FKeepCaretX then begin
Exclude(FFLags, scfUpdateLastCaretX);
exit;
end;
FLastCharPos := FCharPos;
if Locked then begin
Include(FFLags, scfUpdateLastCaretX);
exit;
end;
Exclude(FFLags, scfUpdateLastCaretX);
//FLastCharPos := FCharPos;
FLastViewedCharPos := ViewedLineCharPos.x;
end;
procedure TSynEditCaret.SetSkipTabs(const AValue: Boolean);
begin
if FSkipTabs = AValue then exit;

View File

@ -58,6 +58,8 @@ type
TLinePos = type integer; // 1..high(Integer);
TLineIdx = type integer; // 0..high(Integer);
IntPos = type integer; // 1..high(Integer);
IntIdx = type integer; // 0..high(Integer);
TLogPoint = Types.TPoint;
TPhysPoint = Types.TPoint;