📄 rm_jveditor.pas
字号:
end
else
begin
Text := '';
Result := False;
end;
end;
function TJvCustomEditor.GetAnsiWordOnCaret: AnsiString;
begin
Result := GetWordOnCaret;
end;
procedure TJvCustomEditor.ReLine;
begin
FLines.ReLine;
end;
procedure TJvCustomEditor.InsertChar(const Value: Word);
var
S: string;
X, Y, iBeg: Integer;
WasSelected: Boolean;
Key: Char;
begin
Key := Char(Value);
WasSelected := (FSelection.IsSelected) and (not PersistentBlocks);
if Key in [#32..#255] then
begin
if not HasChar(Key, JvEditorCompletionChars) then
Completion.DoKeyPress(Key);
RemoveSelectedBlock;
ReLine; // need ReLine after DeleteSelection
S := FLines[CaretY];
if InsertMode then
begin
{--- UNDO ---}
TJvInsertUndo.Create(Self, CaretX, CaretY, Key);
{--- /UNDO ---}
Insert(Key, S, CaretX + 1);
AdjustPersistentBlockSelection(CaretX, CaretY, amInsert, [1]);
end
else
begin
{--- UNDO ---}
if CaretX + 1 <= Length(S) then
TJvOverwriteUndo.Create(Self, CaretX, CaretY, S[CaretX + 1], Key)
else
TJvOverwriteUndo.Create(Self, CaretX, CaretY, '', Key);
{--- /UNDO ---}
if CaretX + 1 <= Length(S) then
S[CaretX + 1] := Key
else
S := S + Key
end;
FLines.Internal[CaretY] := S;
SetCaretInternal(CaretX + 1, CaretY);
TextModified(CaretX, CaretY, maInsert, Key);
PaintLine(CaretY, -1, -1);
Changed;
if HasChar(Key, JvEditorCompletionChars) then
Completion.DoKeyPress(Key);
end
else
case Key of
Cr:
begin
if InsertMode then
begin
if WasSelected then // compound only on selection deletion
BeginCompound;
LockUpdate;
try
RemoveSelectedBlock; // adjusts CaretX, CaretY
X := CaretX;
Y := CaretY;
{ --- UNDO --- }
TJvInsertUndo.Create(Self, CaretX, CaretY, sLineBreak);
{ --- /UNDO --- }
if FLines.Count = 0 then
FLines.Add('');
ReLine;
S := Copy(FLines[Y], X + 1, MaxInt);
FLines.Insert(Y + 1, S);
FLines.Internal[Y] := Copy(FLines[Y], 1, X);
Inc(Y);
{ auto indent }
if AutoIndent and
(((Length(FLines[CaretY]) > 0) and
(FLines[CaretY][1] = ' ')) or
((Trim(FLines[CaretY]) = '') and (X > 0))) then
begin
X := GetAutoIndentStop(Y);
if X > 0 then
begin
{ --- UNDO --- }
TJvInsertUndo.Create(Self, 0, Y, Spaces(X));
{ --- /UNDO --- }
FLines.Internal[Y] := Spaces(X) + FLines[Y];
end;
end
else
X := 0;
// persistent blocks: adjust selection
AdjustPersistentBlockSelection(CaretX, CaretY, amLineBreak, []);
UpdateEditorSize;
TextModified(CaretX - 1, CaretY, maInsert, sLineBreak);
finally
UnlockUpdate;
if WasSelected then
EndCompound;
end;
Invalidate;
Changed;
end
else // Overwrite-mode
begin
if WasSelected then // compound only on selection deletion
BeginCompound;
try
RemoveSelectedBlock;
X := CaretX;
Y := CaretY;
Inc(Y);
if Y >= FLines.Count then
begin
LockUpdate;
try
{ --- UNDO --- }
TJvInsertUndo.Create(Self, CaretX, CaretY, sLineBreak);
{ --- /UNDO --- }
FLines.Add('');
finally
UnlockUpdate;
end;
TextModified(0, Y - 1, maInsert, sLineBreak);
UpdateEditorSize;
Invalidate;
Changed;
end;
if Y < FLines.Count then
begin
S := FLines[Y];
if Length(S) > 0 then
begin
iBeg := FindNotBlankCharPos(S) - 1;
if iBeg < X then
X := iBeg;
end;
end;
finally
if WasSelected then
EndCompound;
end;
end;
SetCaretInternal(X, Y);
end;
end;
end;
procedure TJvCustomEditor.SelectWordOnCaret;
var
iBeg, iEnd: Integer;
begin
if (CaretY >= 0) and (CaretY < LineCount) and (Trim(FLines[CaretY]) <> '') then
begin
iEnd := Length(TrimRight(FLines[CaretY]));
if FCaretX < iEnd then
while FLines[FCaretY][FCaretX + 1] <= ' ' do
Inc(FCaretX)
else
begin
FCaretX := iEnd - 1;
while FLines[FCaretY][FCaretX + 1] <= ' ' do
Dec(FCaretX);
end;
if GetWordOnPosEx(FLines[FCaretY] + ' ', FCaretX + 1, iBeg, iEnd) <> '' then
begin
PaintCaret(False);
SetSel(iBeg - 1, FCaretY);
SetSel(iEnd - 1, FCaretY);
SetCaret(iEnd - 1, FCaretY);
PaintCaret(True);
end;
end;
end;
function TJvCustomEditor.DoCommand(ACommand: TEditCommand; var X, Y: Integer;
var CaretUndo: Boolean): Boolean;
type
TPr = procedure of object;
procedure DoAndCorrectXY(Pr: TPr);
begin
Pr;
X := CaretX;
Y := CaretY;
CaretUndo := False;
end;
procedure SetSel1(X, Y: Integer);
begin
SetSel(X, Y);
CaretUndo := False;
end;
procedure SetSelText1(const S: string);
begin
SelText := S;
CaretUndo := False;
end;
var
F: Integer;
S, S2: string;
B: Boolean;
iBeg, iEnd: Integer;
begin
Result := True;
X := CaretX;
Y := CaretY;
case ACommand of
{ caret movements }
ecPrevWord, ecSelPrevWord, ecBackspaceWord:
begin
if (ACommand = ecSelPrevWord) and IsNewSelection then
SetSel1(CaretX, CaretY);
if Y >= FLines.Count then
Exit;
S := FLines[Y];
B := False;
if CaretX > Length(S) then
begin
X := Length(S);
SetSel1(X, Y);
end
else
begin
for F := X - 1 downto 0 do
begin
if B then
begin
if CharInSet(S[F + 1], Separators) then
begin
X := F + 1;
Break;
end;
end
else
if not CharInSet(S[F + 1], Separators) then
B := True;
end;
if X = CaretX then
X := 0;
if ACommand <> ecBackspaceWord then
begin
{ Jump to previous line and last word ending }
if (X = 0) and (Y > 0) then
begin
if (Y > FLines.Count) or (CaretX = 0) or (FLines[Y] = '') or
CharInSet(FLines[Y][1], Separators) then
begin
Y := Y - 1;
X := Length(FLines[Y]);
end;
end;
end;
if ACommand = ecSelPrevWord then
SetSel1(X, Y)
else
PersistentBlocksSetUnSelected;
if (ACommand = ecBackspaceWord) and (Y >= 0) and (X <> CaretX) then
begin
if not ReadOnly then
begin
BeginCompound;
try
SelectRange(X, CaretY, CaretX, CaretY);
DeleteSelected;
finally
EndCompound;
end;
ReLine;
end;
end;
end;
end;
ecNextWord, ecSelNextWord:
begin
if (ACommand = ecSelNextWord) and IsNewSelection then
SetSel1(CaretX, CaretY);
if Y >= FLines.Count then
begin
Y := FLines.Count - 1;
if Y < 0 then
Exit;
X := Length(FLines[Y]);
end;
S := FLines[Y];
B := False;
if CaretX >= Length(S) then
begin
if Y < FLines.Count - 1 then
begin
Y := CaretY + 1;
X := 0;
if Y < FLines.Count then
while (X < Length(FLines[Y])) and (CharInSet(FLines[Y][X + 1], Separators)) do
Inc(X);
if ACommand = ecSelNextWord then // this code is copied from [ecPrevWord, ecSelPrevWord]
SetSel1(X, Y)
else
PersistentBlocksSetUnSelected;
end;
end
else
begin
for F := X to Length(S) - 1 do
if B then
begin
if not CharInSet(S[F + 1], Separators) then
begin
X := F;
Break;
end
end
else
if CharInSet(S[F + 1], Separators) then
B := True;
if X = CaretX then
X := Length(S);
if ACommand = ecSelNextWord then
SetSel1(X, Y)
else
PersistentBlocksSetUnSelected;
end;
end;
ecSelWord:
if IsNewSelection and (GetWordOnPosEx(FLines[Y] + ' ', X + 1, iBeg,
iEnd) <> '') then
begin
SetSel1(iBeg - 1, Y);
SetSel1(iEnd - 1, Y);
X := iEnd - 1;
end;
ecBackspace:
if not ReadOnly then
if X > 0 then
begin
// in the middle of line
if not PersistentBlocks and FSelection.IsSelected then
DoAndCorrectXY(RemoveSelectedBlock)
else
begin
ReLine;
if BackSpaceUnindents then
X := GetBackStop(CaretX, CaretY)
else
X := CaretX - 1;
S := Copy(FLines[CaretY], X + 1, CaretX - X);
{ --- UNDO --- }
if X = CaretX - 1 then
TJvBackspaceUndo.Create(Self, CaretX, CaretY, S)
else
TJvBackspaceUnindentUndo.Create(Self, CaretX, CaretY, S);
CaretUndo := False;
{ --- /UNDO --- }
// persistent blocks: adjust selection
AdjustPersistentBlockSelection(CaretX, CaretY, amDelete, [1]);
FLines.DeleteText(X, Y, CaretX - 1, Y);
TextModified(CaretX, CaretY, maDelete, S);
PaintLine(Y, -1, -1);
end;
Changed;
end
else
if Y > 0 then
begin
// at the start of line
if FSelection.IsSelected then
begin
BeginCompound;
try
DoAndCorrectXY(RemoveSelectedBlock);
ReLine;
finally
EndCompound;
end;
end
else
begin
LockUpdate;
try
X := Length(FLines[Y - 1]);
{ --- UNDO --- }
TJvBackspaceUndo.Create(Self, X + 1, CaretY - 1, Lf);
CaretUndo := False;
{ --- /UNDO --- }
// persistent blocks: adjust selection
AdjustPersistentBlockSelection(CaretX, CaretY, amLineConcat, [X, CaretY - 1]);
FLines.DeleteText(X, Y - 1, -1, Y);
Dec(Y);
finally
UnlockUpdate;
end;
UpdateEditorSize;
TextModified(X, Y, maDelete, sLineBreak);
Invalidate;
Changed;
end;
end;
ecDelete:
if not ReadOnly then
begin
LockUpdate;
try
if FLines.Count = 0 then
FLines.Add('');
finally
UnlockUpdate;
end;
if not PersistentBlocks and FSelection.IsSelected then
DoAndCorrectXY(RemoveSelectedBlock)
else
if X < Length(FLines[Y]) then
begin
//{ inside line -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -