mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-17 04:29:25 +02:00
SynEdit: Move caret up/down by viewed line.
git-svn-id: trunk@63283 -
This commit is contained in:
parent
c326b7a628
commit
80b71e85fb
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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([]);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user