772 lines
18 KiB
PHP
772 lines
18 KiB
PHP
{$ifdef nnn}begin end;{$endif}
|
|
|
|
function TATSynEdit.DoCommand_TextTabulation: TATCommandResults;
|
|
var
|
|
N1, N2: integer;
|
|
begin
|
|
//multiline selection?
|
|
//instead of tabulation, do indent
|
|
if FOptKeyTabIndents then
|
|
if Carets.Count=1 then
|
|
begin
|
|
Carets[0].GetSelLines(N1, N2);
|
|
if (N1>=0) and (N2>N1) then
|
|
begin
|
|
Result:= DoCommand_TextIndentUnindent(true);
|
|
Exit
|
|
end;
|
|
end;
|
|
|
|
if FOptTabSpaces then
|
|
Result:= DoCommand_TextInsertTabSpacesAtCarets(FOverwrite)
|
|
else
|
|
Result:= DoCommand_TextInsertAtCarets(#9, false, FOverwrite, false);
|
|
end;
|
|
|
|
|
|
function TATSynEdit.DoCommand_TextInsertAtCarets(const AText: atString;
|
|
AKeepCaret, AOvrMode, ASelectThen: boolean): TATCommandResults;
|
|
var
|
|
List: TStringList;
|
|
//
|
|
function TextItem(i: integer): atString;
|
|
begin
|
|
if Assigned(List) and (Carets.Count=List.Count) and (i>=0) and (i<List.Count) then
|
|
Result:= UTF8Decode(List[i])
|
|
else
|
|
Result:= AText;
|
|
end;
|
|
//
|
|
var
|
|
Caret: TATCaretItem;
|
|
Shift, PosAfter: TPoint;
|
|
bNeedGroup: boolean;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
List:= nil;
|
|
|
|
bNeedGroup:= (Carets.Count>1) or (Carets.IsSelection);
|
|
if bNeedGroup then Strings.BeginUndoGroup;
|
|
|
|
DoSelectionDeleteOrReset;
|
|
|
|
//list allows to insert each clip-line into one caret
|
|
if (AText<>sLineBreak) and (Length(AText)>1) and (Carets.Count>1) then
|
|
begin
|
|
List:= TStringList.Create;
|
|
List.Text:= UTF8Encode(AText);
|
|
end;
|
|
|
|
try
|
|
for i:= Carets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= Carets[i];
|
|
Strings.TextInsert(Caret.PosX, Caret.PosY, TextItem(i), AOvrMode, Shift, PosAfter);
|
|
DoCaretsShift(Caret.PosX, Caret.PosY, Shift.X, Shift.Y, PosAfter);
|
|
|
|
if not AKeepCaret then
|
|
begin
|
|
Caret.EndX:= IfThen(ASelectThen, Caret.PosX, -1);
|
|
Caret.EndY:= IfThen(ASelectThen, Caret.PosY, -1);
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
end;
|
|
end;
|
|
finally
|
|
if Assigned(List) then
|
|
FreeAndNil(List);
|
|
end;
|
|
|
|
if bNeedGroup then Strings.EndUndoGroup;
|
|
|
|
Result:= [cResultText, cResultCaretBottom];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextInsertTabSpacesAtCarets(AOvrMode: boolean): TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Shift, PosAfter: TPoint;
|
|
StrSpaces: atString;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
Strings.BeginUndoGroup;
|
|
try
|
|
DoSelectionDeleteOrReset;
|
|
|
|
for i:= Carets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= Carets[i];
|
|
StrSpaces:= StringOfChar(' ', FTabSize - Caret.PosX mod FTabSize);
|
|
Strings.TextInsert(Caret.PosX, Caret.PosY, StrSpaces, AOvrMode, Shift, PosAfter);
|
|
DoCaretsShift(Caret.PosX, Caret.PosY, Shift.X, Shift.Y, PosAfter);
|
|
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
Caret.EndX:= -1;
|
|
Caret.EndY:= -1;
|
|
end;
|
|
finally
|
|
Strings.EndUndoGroup;
|
|
end;
|
|
|
|
Result:= [cResultText, cResultCaretBottom];
|
|
end;
|
|
|
|
function TATSynEdit.DoCalcIndentCharsFromPrevLines(AX, AY: integer): integer;
|
|
var
|
|
Str: atString;
|
|
NIndent, i: integer;
|
|
begin
|
|
Result:= -1;
|
|
if not Strings.IsIndexValid(AY) then Exit;
|
|
|
|
//allow smart unindent only if caret on 1st nonspace char
|
|
//(else Bksp must delete 1 char)
|
|
Str:= Strings.Lines[AY];
|
|
NIndent:= SGetIndentChars(Str);
|
|
if not ((AX=NIndent) and (NIndent>0)) then Exit;
|
|
|
|
//calc indent of N prev lines.
|
|
//if indent<AX then ok
|
|
for i:= 1 to FOptMaxLinesToCountUnindent do
|
|
begin
|
|
Dec(AY);
|
|
if not Strings.IsIndexValid(AY) then Exit;
|
|
|
|
Str:= Strings.Lines[AY];
|
|
NIndent:= SGetIndentChars(Str);
|
|
if NIndent<AX then
|
|
Exit(NIndent);
|
|
end;
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextDeleteLeft(ALen: integer; AAllowUnindent: boolean): TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Shift, PosAfter: TPoint;
|
|
NIndent, NDeleteLen: integer;
|
|
bNeedGroup: boolean;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
//selection? delete it, exit.
|
|
if Carets.IsSelection then
|
|
begin
|
|
Result:= DoCommand_TextDeleteSelection;
|
|
Exit
|
|
end;
|
|
|
|
bNeedGroup:= Carets.Count>1;
|
|
if bNeedGroup then Strings.BeginUndoGroup;
|
|
|
|
for i:= 0 to Carets.Count-1 do
|
|
begin
|
|
Caret:= Carets[i];
|
|
NDeleteLen:= ALen;
|
|
|
|
if AAllowUnindent then
|
|
begin
|
|
NIndent:= DoCalcIndentCharsFromPrevLines(Caret.PosX, Caret.PosY);
|
|
if NIndent>=0 then
|
|
if Caret.PosX>NIndent then
|
|
NDeleteLen:= Caret.PosX-NIndent
|
|
else
|
|
NDeleteLen:= Caret.PosX;
|
|
end;
|
|
|
|
Strings.TextDeleteLeft(Caret.PosX, Caret.PosY, NDeleteLen, Shift, PosAfter);
|
|
DoCaretsShift(Caret.PosX, Caret.PosY, Shift.X, Shift.Y, PosAfter);
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
end;
|
|
|
|
if bNeedGroup then Strings.EndUndoGroup;
|
|
|
|
Result:= [cResultText, cResultCaretAny];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextDelete: TATCommandResults;
|
|
var
|
|
bColBlock: boolean;
|
|
begin
|
|
bColBlock:= not IsSelRectEmpty;
|
|
if bColBlock then
|
|
if FSelRect.Left=FSelRect.Right then
|
|
begin
|
|
DoSelect_None;
|
|
bColBlock:= false;
|
|
end;
|
|
|
|
if bColBlock or Carets.IsSelection then
|
|
Result:= DoCommand_TextDeleteSelection
|
|
else
|
|
Result:= DoCommand_TextDeleteRight(1);
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextDeleteSelection: TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Shift, PosAfter: TPoint;
|
|
i: integer;
|
|
AX1, AY1, AX2, AY2: integer;
|
|
bSel: boolean;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
if not IsSelRectEmpty and not OptCaretManyAllowed then
|
|
begin
|
|
DoSelectionDeleteColumnBlock;
|
|
Result:= [cResultText, cResultCaretTop];
|
|
Exit
|
|
end;
|
|
|
|
if not Carets.IsSelection then Exit;
|
|
|
|
Strings.BeginUndoGroup;
|
|
try
|
|
for i:= FCarets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= Carets[i];
|
|
Caret.GetRange(AX1, AY1, AX2, AY2, bSel);
|
|
if not bSel then Continue;
|
|
|
|
Strings.TextDeleteRange(AX1, AY1, AX2, AY2, Shift, PosAfter);
|
|
DoCaretsShift(AX1, AY1, Shift.X, Shift.Y, PosAfter);
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
Caret.EndX:= -1;
|
|
Caret.EndY:= -1;
|
|
end;
|
|
finally
|
|
Strings.EndUndoGroup;
|
|
end;
|
|
|
|
Result:= [cResultText, cResultCaretTop];
|
|
end;
|
|
|
|
|
|
function TATSynEdit.DoCommand_TextDeleteRight(ALen: integer): TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
i, Len, ShiftBelowX: integer;
|
|
Shift, PosAfter: TPoint;
|
|
bNeedGroup: boolean;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
//selection? delete it, exit.
|
|
if Carets.IsSelection then
|
|
begin
|
|
Result:= DoCommand_TextDeleteSelection;
|
|
exit
|
|
end;
|
|
|
|
bNeedGroup:= Carets.Count>1;
|
|
if bNeedGroup then Strings.BeginUndoGroup;
|
|
|
|
for i:= 0 to FCarets.Count-1 do
|
|
begin
|
|
Caret:= FCarets[i];
|
|
|
|
//offsetX for carets in line[PosY+1]
|
|
ShiftBelowX:= 0;
|
|
Len:= Length(Strings.Lines[Caret.PosY]);
|
|
if Caret.PosX=Len then
|
|
ShiftBelowX:= Len;
|
|
|
|
Strings.TextDeleteRight(Caret.PosX, Caret.PosY, ALen, Shift, PosAfter);
|
|
DoCaretsShift(Caret.PosX, Caret.PosY, Shift.X, Shift.Y, PosAfter, ShiftBelowX);
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
end;
|
|
|
|
if bNeedGroup then Strings.EndUndoGroup;
|
|
|
|
Result:= [cResultText, cResultCaretAny];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextInsertEol(AKeepCaret: boolean): TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Shift, PosAfter: TPoint;
|
|
Str: atString;
|
|
bNeedGroup: boolean;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
if ModeOneLine then Exit;
|
|
|
|
bNeedGroup:= Carets.Count>1;
|
|
if bNeedGroup then Strings.BeginUndoGroup;
|
|
|
|
DoSelectionDeleteOrReset;
|
|
|
|
for i:= FCarets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= FCarets[i];
|
|
Str:= GetAutoIndentString(Caret.PosX, Caret.PosY);
|
|
Strings.TextInsertEol(Caret.PosX, Caret.PosY, AKeepCaret, Str, Shift, PosAfter);
|
|
DoCaretsShift(Caret.PosX, Caret.PosY, Shift.X, Shift.Y, PosAfter);
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
end;
|
|
|
|
if bNeedGroup then Strings.EndUndoGroup;
|
|
|
|
Result:= [cResultText, cResultCaretBottom];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextDeleteLines: TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Shift, PosAfter: TPoint;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
Strings.BeginUndoGroup;
|
|
try
|
|
DoCaretsDeleteOnSameLines;
|
|
|
|
for i:= FCarets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= FCarets[i];
|
|
Strings.TextDeleteLine(Caret.PosX, Caret.PosY, Shift, PosAfter);
|
|
DoCaretsShift(Caret.PosX, Caret.PosY, Shift.X, Shift.Y, PosAfter);
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
end;
|
|
finally
|
|
Strings.EndUndoGroup;
|
|
end;
|
|
|
|
Result:= [cResultText, cResultCaretTop];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextDuplicateLine: TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Shift, PosAfter: TPoint;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
Strings.BeginUndoGroup;
|
|
try
|
|
DoCaretsDeleteOnSameLines;
|
|
|
|
for i:= FCarets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= FCarets[i];
|
|
Strings.TextDuplicateLine(Caret.PosX, Caret.PosY, Shift, PosAfter);
|
|
DoCaretsShift(Caret.PosX, Caret.PosY, Shift.X, Shift.Y, PosAfter);
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
end;
|
|
finally
|
|
Strings.EndUndoGroup;
|
|
end;
|
|
|
|
Result:= [cResultText, cResultCaretAny];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextDeleteToLineBegin: TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Str: atString;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
DoCaretsDeleteOnSameLines;
|
|
|
|
for i:= FCarets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= FCarets[i];
|
|
Str:= Strings.Lines[Caret.PosY];
|
|
Delete(Str, 1, Caret.PosX);
|
|
Strings.Lines[Caret.PosY]:= Str;
|
|
Caret.PosX:= 0;
|
|
end;
|
|
|
|
Result:= [cResultText, cResultCaretLeft];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextDeleteToLineEnd: TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Str: atString;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
DoCaretsDeleteOnSameLines;
|
|
|
|
for i:= FCarets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= FCarets[i];
|
|
Str:= Strings.Lines[Caret.PosY];
|
|
if Caret.PosX<Length(Str) then
|
|
begin
|
|
Delete(Str, Caret.PosX+1, MaxInt);
|
|
Strings.Lines[Caret.PosY]:= Str;
|
|
end;
|
|
end;
|
|
|
|
Result:= [cResultText, cResultCaretAny];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextDeleteWord(ANext: boolean): TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Str: atString;
|
|
Shift, PosAfter: TPoint;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
for i:= FCarets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= FCarets[i];
|
|
if not Strings.IsIndexValid(Caret.PosY) then Continue;
|
|
Str:= Strings.Lines[Caret.PosY];
|
|
Shift.X:= 0;
|
|
Shift.Y:= 0;
|
|
PosAfter.X:= Caret.PosX;
|
|
PosAfter.Y:= Caret.PosY;
|
|
|
|
//delete to prev line?
|
|
if (Caret.PosX=0) and (not ANext) then
|
|
begin
|
|
Strings.TextDeleteLeft(Caret.PosX, Caret.PosY, 1, Shift, PosAfter);
|
|
end
|
|
else
|
|
//delete to next line?
|
|
if (Caret.PosX>=Length(Str)) and ANext then
|
|
begin
|
|
Strings.TextDeleteRight(Caret.PosX, Caret.PosY, 1, Shift, PosAfter);
|
|
end
|
|
else
|
|
//jump from beyond eol to eol?
|
|
if (Caret.PosX>Length(Str)) and (not ANext) then
|
|
begin
|
|
Caret.PosX:= Length(Str);
|
|
end
|
|
else
|
|
//delete inside line?
|
|
if (Caret.PosX<=Length(Str)) then
|
|
begin
|
|
PosAfter.X:= SFindWordOffset(Str, Caret.PosX, ANext, false, FOptWordChars);
|
|
if PosAfter.X<>Caret.PosX then
|
|
begin
|
|
System.Delete(Str, Min(Caret.PosX, PosAfter.X)+1, Abs(Caret.PosX-PosAfter.X));
|
|
Strings.Lines[Caret.PosY]:= Str;
|
|
Shift.X:= -Abs(Caret.PosX-PosAfter.X);
|
|
PosAfter.X:= Min(Caret.PosX, PosAfter.X);
|
|
end;
|
|
end;
|
|
|
|
DoCaretsShift(Caret.PosX, Caret.PosY, Shift.X, Shift.Y, PosAfter);
|
|
|
|
if ((Caret.PosX<>PosAfter.X) or (Caret.PosY<>PosAfter.Y)) and
|
|
(FCarets.IndexOfPosXY(PosAfter.X, PosAfter.Y)>=0) then
|
|
begin
|
|
if FCarets.Count>1 then
|
|
FCarets.Delete(i);
|
|
end
|
|
else
|
|
begin
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
end;
|
|
end;
|
|
|
|
if ANext then
|
|
Result:= [cResultText, cResultCaretBottom]
|
|
else
|
|
Result:= [cResultText, cResultCaretTop];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextIndentUnindent(ARight: boolean): TATCommandResults;
|
|
var
|
|
Y1, Y2: integer;
|
|
NDecSpaces, NMinSpaces, i: integer;
|
|
Str: atString;
|
|
Caret: TATCaretItem;
|
|
NShiftInit, NShift1, NShift2, NIndent1, NIndent2: integer;
|
|
begin
|
|
Result:= [];
|
|
DoCaretSingleAsIs;
|
|
|
|
Caret:= Carets[0];
|
|
Caret.GetSelLines(Y1, Y2, true{Allow no sel});
|
|
if Y1<0 then Exit;
|
|
|
|
if Caret.EndY<0 then
|
|
begin
|
|
Caret.EndX:= Caret.PosX;
|
|
Caret.EndY:= Caret.PosY;
|
|
end;
|
|
|
|
if FOptIndentSize>=0 then
|
|
NDecSpaces:= FOptIndentSize
|
|
else
|
|
NDecSpaces:= Abs(FOptIndentSize)*FTabSize;
|
|
|
|
//calc minimal indent of all
|
|
NMinSpaces:= MaxInt;
|
|
for i:= Y1 to Y2 do
|
|
begin
|
|
Str:= Strings.Lines[i];
|
|
if Trim(Str)='' then Continue;
|
|
NMinSpaces:= Min(NMinSpaces, SGetIndentExpanded(Str, FTabSize));
|
|
end;
|
|
if NMinSpaces=MaxInt then Exit;
|
|
|
|
//consider "Unindent keeps align"
|
|
if FOptIndentKeepsAlign then
|
|
if (not ARight) and (NMinSpaces<NDecSpaces) then Exit;
|
|
|
|
//calc shifts (emulate Laz ide indent)
|
|
NIndent1:= SGetIndentChars(Strings.Lines[Caret.PosY]);
|
|
NIndent2:= SGetIndentChars(Strings.Lines[Caret.EndY]);
|
|
NShiftInit:= Abs(FOptIndentSize) * IfThen(ARight, 1, -1);
|
|
NShift1:= IfThen((Caret.PosX>=NIndent1) and (Caret.PosX>0), NShiftInit, 0);
|
|
NShift2:= IfThen((Caret.EndX>=NIndent2), NShiftInit, 0);
|
|
|
|
//do indent
|
|
Strings.BeginUndoGroup;
|
|
try
|
|
for i:= Y1 to Y2 do
|
|
begin
|
|
Str:= Strings.Lines[i];
|
|
if Trim(Str)='' then Continue;
|
|
Str:= SIndentUnindent(Str, ARight, FOptIndentSize, FTabSize);
|
|
if Strings.Lines[i]<>Str then
|
|
Strings.Lines[i]:= Str;
|
|
end;
|
|
finally
|
|
Strings.EndUndoGroup;
|
|
end;
|
|
|
|
//correct selection
|
|
Caret.PosX:= Max(0, Caret.PosX+NShift1);
|
|
Caret.EndX:= Max(0, Caret.EndX+NShift2);
|
|
|
|
Result:= [cResultText, cResultCaretAny];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_Undo: TATCommandResults;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
Strings.Undo(FOptUndoGrouped);
|
|
Result:= [cResultText, cResultCaretBottom];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_Redo: TATCommandResults;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
Strings.SetGroupMark;
|
|
Strings.Redo(FOptUndoGrouped);
|
|
Result:= [cResultText, cResultCaretBottom];
|
|
end;
|
|
|
|
|
|
function TATSynEdit.DoCommand_TextInsertColumnBlockOnce(const AText: atString;
|
|
AKeepCaret: boolean): TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Block: TATStrings;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
//cannot handle carets/selections for colblock
|
|
DoCaretSingleAsIs;
|
|
DoSelect_None;
|
|
Caret:= FCarets[0];
|
|
|
|
Block:= TATStrings.Create;
|
|
try
|
|
Block.LoadFromString(AText);
|
|
Block.ActionDeleteFakeLine;
|
|
if Block.Count=0 then Exit;
|
|
|
|
Strings.TextInsertColumnBlock(Caret.PosX, Caret.PosY, Block, FOverwrite);
|
|
if not AKeepCaret then
|
|
Inc(Caret.PosY, Block.Count-1);
|
|
finally
|
|
FreeAndNil(Block);
|
|
end;
|
|
|
|
Result:= [cResultText, cResultCaretBottom];
|
|
end;
|
|
|
|
|
|
function TATSynEdit.DoCommand_TextDeleteToFileEnd: TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Str: atString;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
DoCaretSingleAsIs;
|
|
|
|
Caret:= FCarets[0];
|
|
Str:= Strings.Lines[Caret.PosY];
|
|
if Caret.PosX<Length(Str) then
|
|
begin
|
|
Delete(Str, Caret.PosX+1, MaxInt);
|
|
Strings.Lines[Caret.PosY]:= Str;
|
|
end;
|
|
|
|
for i:= Strings.Count-1 downto Caret.PosY+1 do
|
|
Strings.LineDelete(i);
|
|
|
|
if Caret.PosY>=Strings.Count-1 then
|
|
Strings.LinesEnds[Caret.PosY]:= cEndNone;
|
|
|
|
Result:= [cResultText, cResultCaretBottom];
|
|
end;
|
|
|
|
|
|
function TATSynEdit.DoCommand_TextInsertEmptyAboveBelow(ADown: boolean): TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
PosAfter: TPoint;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
DoCaretsDeleteOnSameLines;
|
|
|
|
for i:= Carets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= Carets[i];
|
|
Strings.LineInsert(Caret.PosY + IfThen(ADown, 1), '');
|
|
|
|
PosAfter.X:= 0;
|
|
PosAfter.Y:= Caret.PosY+IfThen(ADown, 1);
|
|
|
|
DoCaretsShift(0, Caret.PosY, 0, 1, PosAfter);
|
|
|
|
Caret.PosX:= PosAfter.X;
|
|
Caret.PosY:= PosAfter.Y;
|
|
end;
|
|
|
|
Result:= [cResultText, cResultCaretAny];
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextChangeCase(AMode: TATCaseConvert): TATCommandResults;
|
|
var
|
|
Caret: TATCaretItem;
|
|
Str1, Str2: atString;
|
|
X1, Y1, X2, Y2: integer;
|
|
Shift, PosAfter: TPoint;
|
|
bSel: boolean;
|
|
i: integer;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
Strings.BeginUndoGroup;
|
|
for i:= Carets.Count-1 downto 0 do
|
|
begin
|
|
Caret:= Carets[i];
|
|
Caret.GetRange(X1, Y1, X2, Y2, bSel);
|
|
if not bSel then
|
|
begin
|
|
SFindWordBounds(Strings.Lines[Caret.PosY], Caret.PosX, X1, X2, FOptWordChars);
|
|
if X1<0 then Continue;
|
|
Y1:= Caret.PosY;
|
|
Y2:= Caret.PosY;
|
|
end;
|
|
|
|
Str1:= Strings.TextSubstring(X1, Y1, X2, Y2);
|
|
case AMode of
|
|
cCaseLower: Str2:= UnicodeLowerCase(Str1);
|
|
cCaseUpper: Str2:= UnicodeUpperCase(Str1);
|
|
cCaseTitle: Str2:= SCaseTitle(Str1, FOptWordChars);
|
|
cCaseInvert: Str2:= SCaseInvert(Str1);
|
|
cCaseSentence: Str2:= SCaseSentence(Str1, FOptWordChars);
|
|
end;
|
|
if Str1=Str2 then Continue;
|
|
|
|
Strings.TextDeleteRange(X1, Y1, X2, Y2, Shift, PosAfter);
|
|
Strings.TextInsert(X1, Y1, Str2, false, Shift, PosAfter);
|
|
end;
|
|
Strings.EndUndoGroup;
|
|
|
|
Result:= [cResultText, cResultCaretAny];
|
|
end;
|
|
|
|
|
|
procedure TATSynEdit.DoCommentSelectionLines(Act: TATCommentAction; const AComment: atString);
|
|
var
|
|
Caret: TATCaretItem;
|
|
L: TStringList;
|
|
NFrom, NTo, i: integer;
|
|
Shift, PosAfter: TPoint;
|
|
bChange: boolean;
|
|
begin
|
|
if Carets.Count=0 then exit;
|
|
Caret:= Carets[0];
|
|
Caret.GetSelLines(NFrom, NTo, true);
|
|
if NFrom<0 then exit;
|
|
if NTo<0 then exit;
|
|
|
|
L:= TStringList.Create;
|
|
try
|
|
for i:= NFrom to NTo do
|
|
L.Add(Utf8Encode(Strings.Lines[i]));
|
|
|
|
bChange:= SCommentLineAction(L, AComment, Act);
|
|
if not bChange then exit;
|
|
Assert(L.Count=(NTo-NFrom+1), 'DoCommentSel changed line count');
|
|
|
|
Strings.BeginUndoGroup;
|
|
try
|
|
for i:= NFrom to NTo do
|
|
Strings.Lines[i]:= Utf8Decode(L[i-NFrom]);
|
|
finally
|
|
Strings.EndUndoGroup;
|
|
end;
|
|
finally
|
|
L.Free;
|
|
end;
|
|
|
|
DoEventChange;
|
|
Update(true);
|
|
end;
|
|
|
|
function TATSynEdit.DoCommand_TextTrimSpaces(AMode: TATTrimSpaces
|
|
): TATCommandResults;
|
|
begin
|
|
Result:= [];
|
|
if ModeReadOnly then Exit;
|
|
|
|
if Strings.ActionTrimSpaces(AMode) then
|
|
Result:= [cResultCaretAny, cResultText];
|
|
end;
|
|
|