📄 jvunicodeeditor.pas
字号:
try
inherited Assign(Source);
JvEditor.NotUndoable;
JvEditor.TextAllChanged;
finally
JvEditor.EndUpdate;
end;
end;
procedure TJvEditorWideStrings.AddStrings(Strings: TWStrings);
begin
JvEditor.BeginUpdate;
try
inherited AddStrings(Strings);
JvEditor.NotUndoable;
finally
JvEditor.EndUpdate;
end;
end;
procedure TJvEditorWideStrings.SetTextStr(const Value: WideString);
begin
inherited SetTextStr(JvEditor.ExpandTabs(Value));
if JvEditor.UpdateLock = 0 then
JvEditor.NotUndoable;
JvEditor.TextAllChanged;
end;
procedure TJvEditorWideStrings.StringsChanged(Sender: TObject);
begin
if JvEditor.UpdateLock = 0 then
JvEditor.TextAllChanged;
end;
procedure TJvEditorWideStrings.SetLockText(const Text: WideString);
begin
JvEditor.LockUpdate;
try
inherited SetTextStr(Text)
finally
JvEditor.UnlockUpdate;
end;
end;
procedure TJvEditorWideStrings.SetInternal(Index: Integer; const Value: WideString);
begin
JvEditor.LockUpdate;
try
InternalPut(Index, Value);
finally
JvEditor.UnlockUpdate;
end;
end;
function TJvEditorWideStrings.Add(const S: WideString): Integer;
begin
Result := inherited Add(JvEditor.ExpandTabs(S));
end;
procedure TJvEditorWideStrings.Insert(Index: Integer; const S: WideString);
begin
inherited Insert(Index, JvEditor.ExpandTabs(S));
end;
procedure TJvEditorWideStrings.Put(Index: Integer; const S: WideString);
var
L: Integer;
begin
if JvEditor.KeepTrailingBlanks then
inherited Put(Index, S)
else
begin
L := Length(S) - TrimRightLengthW(S);
if L = 0 then
inherited Put(Index, S)
else
begin
{--- UNDO ---}
TJvDeleteTrailUndo.Create(JvEditor, Length(S), Index, SpacesW(L));
{--- /UNDO ---}
inherited Put(Index, TrimRightW(S));
end;
end;
end;
procedure TJvEditorWideStrings.ReLine;
var
L: Integer;
S: WideString;
begin
JvEditor.LockUpdate;
try
if Count = 0 then
L := JvEditor.CaretX
else
L := Length(Strings[Count - 1]);
while JvEditor.CaretY > Count - 1 do
begin
{--- UNDO ---}
TJvReLineUndo.Create(JvEditor, L, JvEditor.CaretY, sLineBreak);
{--- /UNDO ---}
L := 0;
Add('');
end;
S := Strings[JvEditor.CaretY];
if JvEditor.CaretX > Length(S) then
begin
L := JvEditor.CaretX - Length(S);
{--- UNDO ---}
{ TJvReLineUndo.Create(JvEditor, Length(S),
JvEditor.CaretY, SpacesW(L)); } {disabled: moves the caret to wrong undo position }
{--- /UNDO ---}
inherited Put(JvEditor.CaretY, S + SpacesW(L));
end;
finally
JvEditor.UnlockUpdate;
end;
end;
procedure TJvEditorWideStrings.InternalPut(Index: Integer; const Value: WideString);
begin
if JvEditor.KeepTrailingBlanks then
inherited Put(Index, JvEditor.ExpandTabs(Value))
else
inherited Put(Index, TrimRightW(JvEditor.ExpandTabs(Value)));
end;
procedure TJvEditorWideStrings.DeleteText(BegX, BegY, EndX, EndY: Integer);
{ delete text from [BegX..EndY] [BegY..EndY] all inclusive.
BegX,EndX: [0..Max_X] }
var
BegLine, EndLine: WideString;
I, L: Integer;
begin
if BegY < 0 then
begin
BegY := 0;
BegX := 0;
end;
if BegY >= Count then
Exit; // nothing to delete
if EndY >= Count then
begin
EndY := Count - 1;
EndX := MaxInt - 1;
end;
if BegX < 0 then
BegX := 0;
JvEditor.LockUpdate;
BeginUpdate;
try
BegLine := Strings[BegY];
// expand BegLine if necessary
L := (BegX + 1) - Length(BegLine) - 1;
if L > 0 then
BegLine := BegLine + SpacesW(L);
EndLine := Strings[EndY];
// delete lines between and end line
for I := EndY downto BegY + 1 do
Delete(I);
System.Delete(BegLine, BegX + 1, MaxInt);
System.Delete(EndLine, 1, EndX + 1);
Internal[BegY] := BegLine + EndLine;
finally
EndUpdate;
JvEditor.UnlockUpdate;
end;
end;
procedure TJvEditorWideStrings.InsertText(X, Y: Integer; const Text: WideString);
{ insert text on X:[0..Max_X], Y }
var
BegLine, EndLine: WideString;
YStart: Integer;
F, P: PWideChar;
S, FirstLine: WideString;
Len: Integer;
begin
Inc(X); // increment for WideString functions
if Y < 0 then
Y := 0;
while Y >= Count do
Add('');
BegLine := Strings[Y];
EndLine := System.Copy(BegLine, X, MaxInt);
System.Delete(BegLine, X, MaxInt);
// line is too small -> expand it with spaces
Len := Length(BegLine);
if Len < X then
begin
SetLength(BegLine, X - 1);
FillChar(BegLine[Len + 1], X - Len - 1, ' ');
end;
JvEditor.LockUpdate;
BeginUpdate;
try
P := PWideChar(Text);
F := P;
while (P[0] <> #0) and (P[0] <> Lf) and (P[0] <> Cr) do
Inc(P);
SetString(S, F, P - F);
YStart := Y;
FirstLine := BegLine + S; // set Internal[YStart] later so we keep the trailing spaces for concat EndLine
while P[0] <> #0 do
begin
if P[0] = Cr then
Inc(P);
if P[0] = Lf then
Inc(P);
F := P;
while (P[0] <> #0) and (P[0] <> Lf) and (P[0] <> Cr) do
Inc(P);
SetString(S, F, P - F);
Inc(Y);
Insert(Y, S);
end;
if Y = YStart then
Internal[YStart] := FirstLine + EndLine
else
begin
Internal[YStart] := FirstLine;
Internal[Y] := Strings[Y] + EndLine;
end;
finally
EndUpdate;
JvEditor.UnlockUpdate;
end;
end;
procedure TJvEditorWideStrings.DeleteColumnText(BegX, BegY, EndX, EndY: Integer);
{ delete column text from [BegX..EndY] [BegY..EndY] all inclusive.
BegX,EndX: [0..Max_X] }
var
S: WideString;
I: Integer;
begin
if BegY < 0 then
begin
BegY := 0;
BegX := 0;
end;
if BegY >= Count then
Exit; // nothing to delete
if EndY >= Count then
begin
EndY := Count - 1;
EndX := MaxInt - 1;
end;
if BegX < 0 then
BegX := 0;
JvEditor.LockUpdate;
BeginUpdate;
try
for I := BegY to EndY do
begin
S := JvEditor.FLines[I];
System.Delete(S, BegX + 1, EndX - BegX + 1);
JvEditor.FLines.Internal[I] := S;
end;
finally
EndUpdate;
JvEditor.UnlockUpdate;
end;
end;
procedure TJvEditorWideStrings.InsertColumnText(X, Y: Integer; const Text: WideString);
{ insert column text on X:[0..Max_X], Y }
var
S, Line: WideString;
P, F: PWideChar;
L: Integer;
begin
Inc(X); // increment for WideString functions
if Y < 0 then
Y := 0;
JvEditor.LockUpdate;
BeginUpdate;
try
P := PWideChar(Text);
F := P;
while P[0] <> #0 do
begin
while (P[0] <> #0) and (P[0] <> Lf) and (P[0] <> Cr) do
Inc(P);
SetString(S, F, P - F);
while Y >= Count do
Add('');
Line := Strings[Y];
L := (X - 1) - Length(Line);
if L > 0 then
Line := Line + SpacesW(L);
System.Insert(S, Line, X);
Internal[Y] := Line;
if P[0] = Cr then
Inc(P);
if P[0] = Lf then
Inc(P);
F := P;
Inc(Y);
end;
finally
EndUpdate;
JvEditor.UnlockUpdate;
end;
end;
//=== { TJvCustomWideEditor } ================================================
constructor TJvCustomWideEditor.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLines := TJvEditorWideStrings.Create;
FLines.FJvEditor := Self;
FLines.OnChange := DoLinesChange;
Completion := TJvWideCompletion.Create(Self);
end;
destructor TJvCustomWideEditor.Destroy;
begin
FLines.Free;
Completion.Free;
inherited Destroy;
end;
procedure TJvCustomWideEditor.PaintLineText(Line: Integer; ColBeg, ColEnd: Integer;
var ColPainted: Integer);
var
Ch: WideString;
iC, jC, SL, MX: Integer;
R: TRect;
S: WideString;
LA: TLineAttr;
jCStart, Len: Integer;
MyDi: TDynIntArray;
begin
with EditorClient do
begin
S := FLines[Line];
Len := Max(Length(S), Max_X) + 1;
if Len > Length(LineAttrs) then
SetLength(LineAttrs, Len)
else if Len + 128 < Length(LineAttrs) then
SetLength(LineAttrs, Len);
GetLineAttr(S, Line, ColBeg, ColEnd);
{left line}
if Canvas.Brush.Color <> LineAttrs[LeftCol + 1].BC then // change GDI object only if necessary
Canvas.Brush.Color := LineAttrs[LeftCol + 1].BC;
Canvas.FillRect(Bounds(EditorClient.Left, (Line - TopRow) *
CellRect.Height, 1, CellRect.Height));
{optimized, paint group of chars with identical attributes}
SL := Length(S);
MX := ColEnd;
if Length(FMyDi) < MX then
begin
SetLength(MyDi, MX);
for iC := 0 to High(MyDi) do
MyDi[iC] := CellRect.Width;
end
else
MyDi := FMyDi;
while ColPainted < MX do
begin
with Canvas do
begin
iC := ColPainted + 1;
LA := LineAttrs[iC];
jC := iC + 1;
if iC <= SL then
Ch := S[iC]
else
Ch := ' ';
jCStart := jC;
while (jC <= MX + 1) and
CompareMem(@LA, @LineAttrs[jC], SizeOf(LineAttrs[1])) do
Inc(jC);
Ch := Copy(S, jCStart - 1, jC - jCStart + 1);
if jC > SL + 1 then
Ch := Ch + Spaces(jC - SL - 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -