📄 jveditor.pas
字号:
if Brush.Color <> LA.BC then // change GDI object only if necessary
Brush.Color := LA.BC;
Font.Assign(FontCacheFind(LA));
R := CalcCellRect(ColPainted - LeftCol, Line - TopRow);
{bottom line}
FillRect(Bounds(R.Left, R.Bottom - 1, CellRect.Width * Length(Ch), 1));
TJvUnicodeCanvas(Canvas).ExtTextOut(R.Left, R.Top, [etoOpaque, etoClipped], nil, Ch, @MyDi[0]);
if LA.Border <> clNone then
begin
Pen.Color := LA.Border;
R.Right := R.Left + CellRect.Width * Length(Ch);
Dec(R.Left);
Brush.Style := bsClear;
Rectangle(R);
Brush.Style := bsSolid;
end;
ColPainted := jC - 1;
end;
end;
end;
end;
procedure TJvCustomEditor.GetLineAttr(var Str: string; Line, ColBeg, ColEnd: Integer);
var
I: Integer;
begin
if ColBeg < 0 then
ColBeg := 0;
if ColEnd > Max_X then
ColEnd := Max_X;
LineAttrs[ColBeg].Style := Font.Style;
LineAttrs[ColBeg].FC := Font.Color;
LineAttrs[ColBeg].BC := Color;
LineAttrs[ColBeg].Border := clNone;
{ for I := ColBeg + 1 to ColEnd do
Move(LineAttrs[ColBeg], LineAttrs[I], SizeOf(LineAttrs[1]));}
for I := ColBeg + 1 to ColEnd do
LineAttrs[I] := LineAttrs[ColBeg];
GetAttr(Line, ColBeg, ColEnd);
if Assigned(FOnGetLineAttr) then
FOnGetLineAttr(Self, Str, Line, LineAttrs);
ChangeAttr(Line, ColBeg, ColEnd);
end;
function TJvCustomEditor.GetAnsiTextLine(Y: Integer; out Text: AnsiString): Boolean;
begin
if (Y >= 0) and (Y < Lines.Count) then
begin
Text := Lines[Y];
Result := True;
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 = 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 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 -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -