SynEdit: Refactored SynSelection

git-svn-id: trunk@20942 -
This commit is contained in:
martin 2009-07-25 01:02:55 +00:00
parent 8e986531c0
commit f32f484ae9
2 changed files with 67 additions and 67 deletions

View File

@ -336,6 +336,7 @@ type
{$IFDEF SYN_LAZARUS} {$IFDEF SYN_LAZARUS}
FCaret: TSynEditCaret; FCaret: TSynEditCaret;
FInternalCaret: TSynEditCaret; FInternalCaret: TSynEditCaret;
FInternalBlockSelection: TSynEditSelection;
fCtrlMouseActive: boolean; fCtrlMouseActive: boolean;
fMarkupManager : TSynEditMarkupManager; fMarkupManager : TSynEditMarkupManager;
fMarkupHighAll : TSynEditMarkupHighlightAll; fMarkupHighAll : TSynEditMarkupHighlightAll;
@ -1549,6 +1550,11 @@ begin
FBlockSelection.InvalidateLinesMethod := {$IFDEF FPC}@{$ENDIF}InvalidateLines; FBlockSelection.InvalidateLinesMethod := {$IFDEF FPC}@{$ENDIF}InvalidateLines;
FBlockSelection.AddChangeHandler({$IFDEF FPC}@{$ENDIF}DoBlockSelectionChanged); FBlockSelection.AddChangeHandler({$IFDEF FPC}@{$ENDIF}DoBlockSelectionChanged);
FInternalBlockSelection := TSynEditSelection.Create(FTheLinesView, False);
FInternalBlockSelection.UndoList := fUndoList;
FInternalBlockSelection.InvalidateLinesMethod := {$IFDEF FPC}@{$ENDIF}InvalidateLines;
// No need for caret, on interanl block
FWordBreaker := TSynWordBreaker.Create; FWordBreaker := TSynWordBreaker.Create;
{$IFDEF SYN_COMPILER_4_UP} {$IFDEF SYN_COMPILER_4_UP}
{$IFNDEF SYN_LAZARUS} {$IFNDEF SYN_LAZARUS}
@ -1806,6 +1812,7 @@ begin
FreeAndNil(fFontDummy); FreeAndNil(fFontDummy);
FreeAndNil(FWordBreaker); FreeAndNil(FWordBreaker);
FreeAndNil(FFoldedLinesView); FreeAndNil(FFoldedLinesView);
FreeAndNil(FInternalBlockSelection);
FreeAndNil(FBlockSelection); FreeAndNil(FBlockSelection);
FreeAndNil(FStrings); FreeAndNil(FStrings);
FreeAndNil(FTabbedLinesView); FreeAndNil(FTabbedLinesView);
@ -5693,17 +5700,12 @@ begin
end else end else
WP := Point(Len + 1, CaretY); WP := Point(Len + 1, CaretY);
if (WP.X <> CaretX) or (WP.Y <> CaretY) then begin if (WP.X <> CaretX) or (WP.Y <> CaretY) then begin
OldSelMode := FBlockSelection.ActiveSelectionMode; FInternalBlockSelection.StartLineBytePos := PhysicalToLogicalPos(WP);
try FInternalBlockSelection.EndLineBytePos := PhysicalToLogicalPos(CaretXY);
SetBlockBegin(PhysicalToLogicalPos(WP)); FInternalBlockSelection.ActiveSelectionMode := smNormal;
SetBlockEnd(PhysicalToLogicalPos(CaretXY)); FInternalBlockSelection.SetSelTextPrimitive(smNormal, nil);
FBlockSelection.ActiveSelectionMode := smNormal; if Helper <> '' then
SetSelTextPrimitive(smNormal, nil, true); FTabbedLinesView.EditInsert(CaretX, CaretY, Helper);
if Helper <> '' then
FTabbedLinesView.EditInsert(CaretX, CaretY, Helper);
finally
FBlockSelection.ActiveSelectionMode := OldSelMode;
end;
CaretXY := Caret; CaretXY := Caret;
end; end;
end; end;
@ -5714,19 +5716,13 @@ begin
else else
WP := Point(1, CaretY); WP := Point(1, CaretY);
if (WP.X <> CaretX) or (WP.Y <> CaretY) then begin if (WP.X <> CaretX) or (WP.Y <> CaretY) then begin
OldSelMode := FBlockSelection.ActiveSelectionMode; FInternalBlockSelection.StartLineBytePos := PhysicalToLogicalPos(WP);
try FInternalBlockSelection.EndLineBytePos := PhysicalToLogicalPos(CaretXY);
SetBlockBegin(PhysicalToLogicalPos(WP)); FInternalBlockSelection.ActiveSelectionMode := smNormal;
SetBlockEnd(PhysicalToLogicalPos(CaretXY)); FInternalBlockSelection.SetSelTextPrimitive(smNormal, nil);
FBlockSelection.ActiveSelectionMode := smNormal;
SetSelTextPrimitive(smNormal, nil, true)
finally
FBlockSelection.ActiveSelectionMode := OldSelMode;
end;
CaretXY := WP; CaretXY := WP;
end; end;
end; end;
{end} //mh 2000-10-30
ecDeleteLine: ecDeleteLine:
if not ReadOnly and not ((FTheLinesView.Count = 1) and (Length(FTheLinesView[0]) = 0)) if not ReadOnly and not ((FTheLinesView.Count = 1) and (Length(FTheLinesView[0]) = 0))
then begin then begin

View File

@ -71,6 +71,7 @@ type
TSynEditSelection = class(TSynEditPointBase) TSynEditSelection = class(TSynEditPointBase)
FCaret: TSynEditCaret; FCaret: TSynEditCaret;
FInternalCaret: TSynEditCaret;
fUndoList: TSynEditUndoList; fUndoList: TSynEditUndoList;
FInvalidateLinesMethod: TInvalidateLines; FInvalidateLinesMethod: TInvalidateLines;
FEnabled: Boolean; FEnabled: Boolean;
@ -97,6 +98,7 @@ type
function GetSelText: string; function GetSelText: string;
procedure SetSelText(const Value: string); procedure SetSelText(const Value: string);
procedure DoCaretChanged(Sender: TObject); procedure DoCaretChanged(Sender: TObject);
procedure AdjustAfterTrimming; // TODO: Move into TrimView?
protected protected
Procedure LineChanged(Sender: TSynEditStrings; AIndex, ACount : Integer); Procedure LineChanged(Sender: TSynEditStrings; AIndex, ACount : Integer);
procedure DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBytePos, aCount, procedure DoLinesEdited(Sender: TSynEditStrings; aLinePos, aBytePos, aCount,
@ -104,7 +106,6 @@ type
public public
constructor Create(ALines: TSynEditStrings; aActOnLineChanges: Boolean); constructor Create(ALines: TSynEditStrings; aActOnLineChanges: Boolean);
destructor Destroy; override; destructor Destroy; override;
procedure AdjustAfterTrimming; // TODO: Move into TrimView
procedure SetSelTextPrimitive(PasteMode: TSynSelectionMode; Value: PChar); procedure SetSelTextPrimitive(PasteMode: TSynSelectionMode; Value: PChar);
function SelAvail: Boolean; function SelAvail: Boolean;
function SelCanContinue(ACaret: TSynEditCaret): Boolean; function SelCanContinue(ACaret: TSynEditCaret): Boolean;
@ -245,6 +246,7 @@ end;
constructor TSynEditCaret.Create; constructor TSynEditCaret.Create;
begin begin
inherited Create; inherited Create;
FMaxLeftChar := nil;
fLinePos:= 1; fLinePos:= 1;
fCharPos:= 1; fCharPos:= 1;
FAllowPastEOL := True; FAllowPastEOL := True;
@ -361,7 +363,10 @@ var
begin begin
Lock; Lock;
try try
nMaxX := FMaxLeftChar^; if FMaxLeftChar <> nil then
nMaxX := FMaxLeftChar^
else
nMaxX := MaxInt;
if NewLine > FLines.Count then if NewLine > FLines.Count then
NewLine := FLines.Count; NewLine := FLines.Count;
if NewLine < 1 then begin if NewLine < 1 then begin
@ -369,12 +374,11 @@ begin
NewLine := 1; NewLine := 1;
if (not FAllowPastEOL) and (FForcePastEOL = 0) then if (not FAllowPastEOL) and (FForcePastEOL = 0) then
nMaxX := 1; nMaxX := 1;
end else begin end else
Line := Lines[NewLine - 1]; if (not FAllowPastEOL) and (FForcePastEOL = 0) then begin
nMaxX := Lines.LogicalToPhysicalCol(Line, NewLine - 1, length(Line)+1); Line := Lines[NewLine - 1];
if ((FAllowPastEOL) or (FForcePastEOL > 0)) and (nMaxX < FMaxLeftChar^) then nMaxX := Lines.LogicalToPhysicalCol(Line, NewLine - 1, length(Line)+1);
nMaxX := FMaxLeftChar^; end;
end;
if NewCharPos > nMaxX then if NewCharPos > nMaxX then
NewCharPos := nMaxX; NewCharPos := nMaxX;
if NewCharPos < 1 then if NewCharPos < 1 then
@ -441,6 +445,9 @@ end;
constructor TSynEditSelection.Create(ALines : TSynEditStrings; aActOnLineChanges: Boolean); constructor TSynEditSelection.Create(ALines : TSynEditStrings; aActOnLineChanges: Boolean);
begin begin
Inherited Create(ALines); Inherited Create(ALines);
FInternalCaret := TSynEditCaret.Create;
FInternalCaret.Lines := FLines;
FActiveSelectionMode := smNormal; FActiveSelectionMode := smNormal;
FStartLinePos := 1; FStartLinePos := 1;
FStartBytePos := 1; FStartBytePos := 1;
@ -457,6 +464,7 @@ end;
destructor TSynEditSelection.Destroy; destructor TSynEditSelection.Destroy;
begin begin
FreeAndNil(FInternalCaret);
if FHookedLines then begin if FHookedLines then begin
FLines.RemoveEditHandler(@DoLinesEdited); FLines.RemoveEditHandler(@DoLinesEdited);
FLines.RemoveChangeHandler(senrLineChange, {$IFDEF FPC}@{$ENDIF}LineChanged); FLines.RemoveChangeHandler(senrLineChange, {$IFDEF FPC}@{$ENDIF}LineChanged);
@ -699,14 +707,14 @@ var
end; end;
FLines.EditDelete(BB.X, BB.Y, BE.X - BB.X); FLines.EditDelete(BB.X, BB.Y, BE.X - BB.X);
end; end;
FCaret.LineBytePos := BB; FInternalCaret.LineBytePos := BB;
end; end;
smColumn: smColumn:
begin begin
FCaret.LineBytePos := BB; FInternalCaret.LineBytePos := BB;
l := FCaret.CharPos; l := FInternalCaret.CharPos;
FCaret.LineBytePos := BE; FInternalCaret.LineBytePos := BE;
r := FCaret.CharPos; r := FInternalCaret.CharPos;
// swap l, r if needed // swap l, r if needed
if l > r then if l > r then
{$IFDEF SYN_COMPILER_3_UP} {$IFDEF SYN_COMPILER_3_UP}
@ -719,15 +727,15 @@ var
end; end;
{$ENDIF} {$ENDIF}
for y := BB.Y to BE.Y do begin for y := BB.Y to BE.Y do begin
FCaret.LineCharPos := Point(l, y); FInternalCaret.LineCharPos := Point(l, y);
xb := FCaret.BytePos; xb := FInternalCaret.BytePos;
FCaret.LineCharPos := Point(r, y); FInternalCaret.LineCharPos := Point(r, y);
xe := Min(FCaret.BytePos, 1 + length(FCaret.LineText)); xe := Min(FInternalCaret.BytePos, 1 + length(FInternalCaret.LineText));
if xe > xb then if xe > xb then
FLines.EditDelete(xb, y, xe - xb); FLines.EditDelete(xb, y, xe - xb);
end; end;
// FLines never get deleted completely, so keep caret at end. // FLines never get deleted completely, so keep caret at end.
FCaret.LineCharPos := Point(l, FEndLinePos); FInternalCaret.LineCharPos := Point(l, FEndLinePos);
// Column deletion never removes a line entirely, so no mark // Column deletion never removes a line entirely, so no mark
// updating is needed here. // updating is needed here.
end; end;
@ -740,7 +748,7 @@ var
end; end;
if BE.Y >= BB.Y then if BE.Y >= BB.Y then
FLines.EditLinesDelete(BB.Y, BE.Y - BB.Y + 1); FLines.EditLinesDelete(BB.Y, BE.Y - BB.Y + 1);
FCaret.LineCharPos := Point(1, BB.Y); FInternalCaret.LineCharPos := Point(1, BB.Y);
end; end;
end; end;
end; end;
@ -768,13 +776,13 @@ var
LogCaretXY: TPoint; LogCaretXY: TPoint;
begin begin
Result := 0; Result := 0;
LogCaretXY := FCaret.LineBytePos; LogCaretXY := FInternalCaret.LineBytePos;
Start := PChar(Value); Start := PChar(Value);
P := GetEOL(Start); P := GetEOL(Start);
if P^ = #0 then begin if P^ = #0 then begin
FLines.EditInsert(LogCaretXY.X, LogCaretXY.Y, Value); FLines.EditInsert(LogCaretXY.X, LogCaretXY.Y, Value);
FCaret.BytePos := FCaret.BytePos + Length(Value); FInternalCaret.BytePos := FInternalCaret.BytePos + Length(Value);
end else begin end else begin
SetString(Str, Value, P - Start); SetString(Str, Value, P - Start);
FLines.EditInsert(LogCaretXY.X, LogCaretXY.Y, Str); FLines.EditInsert(LogCaretXY.X, LogCaretXY.Y, Str);
@ -797,8 +805,8 @@ var
else else
Str := ''; Str := '';
end; end;
FCaret.LinePos := LogCaretXY.Y; FInternalCaret.LinePos := LogCaretXY.Y;
FCaret.BytePos := 1 + Length(Str); FInternalCaret.BytePos := 1 + Length(Str);
end; end;
end; end;
@ -810,29 +818,29 @@ var
begin begin
// Insert string at current position // Insert string at current position
Result := 0; Result := 0;
FCaret.IncForcePastEOL; FInternalCaret.IncForcePastEOL;
Start := PChar(Value); Start := PChar(Value);
repeat repeat
P := GetEOL(Start); P := GetEOL(Start);
if P <> Start then begin if P <> Start then begin
SetLength(Str, P - Start); SetLength(Str, P - Start);
Move(Start^, Str[1], P - Start); Move(Start^, Str[1], P - Start);
FLines.EditInsert(FCaret.BytePos, FCaret.LinePos, Str); FLines.EditInsert(FInternalCaret.BytePos, FInternalCaret.LinePos, Str);
end; end;
if p^ in [#10,#13] then begin if p^ in [#10,#13] then begin
if (p[1] in [#10,#13]) and (p[1]<>p^) then if (p[1] in [#10,#13]) and (p[1]<>p^) then
inc(p,2) inc(p,2)
else else
Inc(P); Inc(P);
if FCaret.LinePos = FLines.Count then if FInternalCaret.LinePos = FLines.Count then
FLines.EditLinesInsert(FCaret.LinePos + 1, 1); FLines.EditLinesInsert(FInternalCaret.LinePos + 1, 1);
// No need to inc result => adding at EOF // No need to inc result => adding at EOF
FCaret.LinePos := FCaret.LinePos + 1; FInternalCaret.LinePos := FInternalCaret.LinePos + 1;
end; end;
Start := P; Start := P;
until P^ = #0; until P^ = #0;
FCaret.BytePos:= FCaret.BytePos + Length(Str); FInternalCaret.BytePos:= FInternalCaret.BytePos + Length(Str);
FCaret.DecForcePastEOL; FInternalCaret.DecForcePastEOL;
end; end;
function InsertLine: Integer; function InsertLine: Integer;
@ -842,7 +850,7 @@ var
Str: string; Str: string;
begin begin
Result := 0; Result := 0;
FCaret.CharPos := 1; FInternalCaret.CharPos := 1;
// Insert string before current line // Insert string before current line
Start := PChar(Value); Start := PChar(Value);
repeat repeat
@ -853,11 +861,11 @@ var
end else end else
Str := ''; Str := '';
if (P^ = #0) then begin // Not a full line? if (P^ = #0) then begin // Not a full line?
FLines.EditInsert(1, FCaret.LinePos, Str); FLines.EditInsert(1, FInternalCaret.LinePos, Str);
FCaret.BytePos := 1 + Length(Str); FInternalCaret.BytePos := 1 + Length(Str);
end else begin end else begin
FLines.EditLinesInsert(FCaret.LinePos, 1, Str); FLines.EditLinesInsert(FInternalCaret.LinePos, 1, Str);
FCaret.LinePos := FCaret.LinePos + 1; FInternalCaret.LinePos := FInternalCaret.LinePos + 1;
Inc(Result); Inc(Result);
if P^ = #13 then if P^ = #13 then
Inc(P); Inc(P);
@ -896,7 +904,6 @@ var
begin begin
FIsSettingText := True; FIsSettingText := True;
FLines.BeginUpdate; FLines.BeginUpdate;
FCaret.Lock;
try try
// BB is lower than BE // BB is lower than BE
BB := FirstLineBytePos; BB := FirstLineBytePos;
@ -908,13 +915,14 @@ begin
StartLineBytePos := BB; // deletes selection // calls selection changed StartLineBytePos := BB; // deletes selection // calls selection changed
end; end;
if (Value <> nil) and (Value[0] <> #0) then begin if (Value <> nil) and (Value[0] <> #0) then begin
FCaret.LineBytePos := StartLineBytePos; FInternalCaret.LineBytePos := StartLineBytePos;
InsertText; InsertText;
StartLineBytePos := FCaret.LineBytePos; // reset selection StartLineBytePos := FInternalCaret.LineBytePos; // reset selection
end; end;
if FCaret <> nil then
FCaret.LineCharPos := FInternalCaret.LineCharPos;
finally finally
FCaret.Unlock; FLines.EndUpdate;
FLines.EndUpdate; // May reset Block Begin
FIsSettingText := False; FIsSettingText := False;
end; end;
end; end;
@ -937,14 +945,12 @@ procedure TSynEditSelection.SetStartLineBytePos(Value : TPoint);
var var
nInval1, nInval2: integer; nInval1, nInval2: integer;
SelChanged: boolean; SelChanged: boolean;
Line: string;
begin begin
Value.y := MinMax(Value.y, 1, fLines.Count); Value.y := MinMax(Value.y, 1, fLines.Count);
Line := Lines[Value.y - 1];
if (FCaret <> nil) and FCaret.AllowPastEOL then if (FCaret <> nil) and FCaret.AllowPastEOL then
Value.x := Max(Value.x, 1) Value.x := Max(Value.x, 1)
else else
Value.x := MinMax(Value.x, 1, Lines.LogicalToPhysicalCol(Line, Value.y - 1, length(Line)+1)); Value.x := MinMax(Value.x, 1, length(Lines[Value.y - 1])+1);
if (ActiveSelectionMode = smNormal) then if (ActiveSelectionMode = smNormal) then
if (Value.y >= 1) and (Value.y <= FLines.Count) then if (Value.y >= 1) and (Value.y <= FLines.Count) then
Value.x := AdjustBytePosToCharacterStart(Value.y,Value.x) Value.x := AdjustBytePosToCharacterStart(Value.y,Value.x)
@ -982,18 +988,16 @@ end;
procedure TSynEditSelection.SetEndLineBytePos(Value : TPoint); procedure TSynEditSelection.SetEndLineBytePos(Value : TPoint);
var var
nLine: integer; nLine: integer;
Line: String;
{$IFDEF SYN_MBCSSUPPORT} {$IFDEF SYN_MBCSSUPPORT}
s: string; s: string;
{$ENDIF} {$ENDIF}
begin begin
if FEnabled then begin if FEnabled then begin
Value.y := MinMax(Value.y, 1, fLines.Count); Value.y := MinMax(Value.y, 1, fLines.Count);
Line := Lines[Value.y - 1];
if (FCaret <> nil) and FCaret.AllowPastEOL then if (FCaret <> nil) and FCaret.AllowPastEOL then
Value.x := Max(Value.x, 1) Value.x := Max(Value.x, 1)
else else
Value.x := MinMax(Value.x, 1, Lines.LogicalToPhysicalCol(Line, Value.y - 1, length(Line)+1)); Value.x := MinMax(Value.x, 1, length(Lines[Value.y - 1])+1);
if (ActiveSelectionMode = smNormal) then if (ActiveSelectionMode = smNormal) then
if (Value.y >= 1) and (Value.y <= fLines.Count) then if (Value.y >= 1) and (Value.y <= fLines.Count) then
Value.x := AdjustBytePosToCharacterStart(Value.y,Value.x) Value.x := AdjustBytePosToCharacterStart(Value.y,Value.x)