📄 fqbsynmemo.pas
字号:
begin
with FVScroll do
begin
// prevent OnScroll event
FUpdating := True;
Position := 0;
{$IFDEF Delphi4}
PageSize := 0;
{$ENDIF}
if Assigned(FText) then
Max := FText.Count
else
Max := 0;
SmallChange := 1;
if FWindowSize.Y < Max then
begin
Visible := True;
{$IFDEF Delphi4}
PageSize := FWindowSize.Y;
{$ENDIF}
end
else
Visible := False;
LargeChange := FWindowSize.Y;
Position := FOffset.Y;
// need to do this due to bug in the VCL
// THackScrollBar(FVScroll).RecreateWnd;
FUpdating := False;
end;
end;
function TfqbSyntaxMemo.GetText: TStrings;
var
i: Integer;
begin
for i := 0 to FText.Count - 1 do
FText[i] := LineAt(i);
Result := FText;
FAllowLinesChange := True;
end;
procedure TfqbSyntaxMemo.SetText(Value: TStrings);
begin
FAllowLinesChange := True;
FText.Assign(Value);
end;
procedure TfqbSyntaxMemo.SetSyntaxType(Value: TSyntaxType);
begin
FSyntaxType := Value;
if Value = stPascal then
FKeywords := PasKeywords
else if Value = stCpp then
FKeywords := CppKeywords
else if Value = stSQL then
FKeywords := SQLKeywords
else
FKeywords := '';
UpdateSyntax;
end;
function TfqbSyntaxMemo.GetPos: TPoint;
begin
Result := FPos;
end;
procedure TfqbSyntaxMemo.DoChange;
begin
FModified := True;
end;
procedure TfqbSyntaxMemo.LinesChange(Sender: TObject);
begin
if FAllowLinesChange then
begin
UpdateSyntax;
FAllowLinesChange := False;
if FText.Count = 0 then
FText.Add('');
FMoved := True;
FUndo.Clear;
FPos := Point(1, 1);
FOffset := Point(0, 0);
ClearSel;
ShowCaretPos;
UpdateScrollBar;
end;
end;
procedure TfqbSyntaxMemo.ShowMessage(s: String);
begin
FMessage := s;
Repaint;
end;
procedure TfqbSyntaxMemo.CopyToClipboard;
begin
if FSelStart.X <> 0 then
Clipboard.AsText := SelText;
end;
procedure TfqbSyntaxMemo.CutToClipboard;
begin
if not FReadOnly then
begin
if FSelStart.X <> 0 then
begin
Clipboard.AsText := SelText;
SelText := '';
end;
CorrectBookmark(FSelStart.Y, FSelStart.Y - FSelEnd.Y);
Repaint;
end;
end;
procedure TfqbSyntaxMemo.PasteFromClipboard;
begin
if not FReadOnly then
SelText := Clipboard.AsText;
end;
function TfqbSyntaxMemo.LineAt(Index: Integer): String;
begin
if Index < FText.Count then
Result := TrimRight(FText[Index])
else
Result := '';
end;
function TfqbSyntaxMemo.LineLength(Index: Integer): Integer;
begin
Result := Length(LineAt(Index));
end;
function TfqbSyntaxMemo.Pad(n: Integer): String;
{$IFDEF Delphi12}
var
i: Integer;
{$ENDIF}
begin
result := '';
SetLength(result, n);
{$IFDEF Delphi12}
for i:= 1 to n do result[i] := ' ';
{$ELSE}
FillChar(result[1], n, ' ');
{$ENDIF}
end;
procedure TfqbSyntaxMemo.AddUndo;
begin
if not FMoved then exit;
FUndo.Add(Format('%5d%5d', [FPos.X, FPos.Y]) + FText.Text);
if FUndo.Count > 32 then
FUndo.Delete(0);
end;
procedure TfqbSyntaxMemo.Undo;
var
s: String;
begin
FMoved := True;
if FUndo.Count = 0 then exit;
s := FUndo[FUndo.Count - 1];
FPos.X := StrToInt(Copy(s, 1, 5));
FPos.Y := StrToInt(Copy(s, 6, 5));
FText.Text := Copy(s, 11, Length(s) - 10);
FUndo.Delete(FUndo.Count - 1);
SetPos(FPos.X, FPos.Y);
UpdateSyntax;
DoChange;
end;
function TfqbSyntaxMemo.GetPlainTextPos(Pos: TPoint): Integer;
var
i: Integer;
begin
Result := 0;
for i := 0 to Pos.Y - 2 do
Result := Result + Length(FText[i]) + 2;
Result := Result + Pos.X;
end;
function TfqbSyntaxMemo.GetPosPlainText(Pos: Integer): TPoint;
var
i: Integer;
s: String;
begin
Result := Point(0, 1);
s := FText.Text;
i := 1;
while i <= Pos do
if s[i] = #13 then
begin
Inc(i, 2);
if i <= Pos then
begin
Inc(Result.Y);
Result.X := 0;
end
else
Inc(Result.X);
end
else
begin
Inc(i);
Inc(Result.X);
end;
end;
function TfqbSyntaxMemo.GetLineBegin(Index: Integer): Integer;
var
s: String;
begin
s := FText[Index];
Result := 1;
if Trim(s) <> '' then
for Result := 1 to Length(s) do
if s[Result] <> ' ' then
break;
end;
procedure TfqbSyntaxMemo.TabIndent;
var
i, n, res: Integer;
s: String;
begin
res := FPos.X;
i := FPos.Y - 2;
while i >= 0 do
begin
res := FPos.X;
s := FText[i];
n := LineLength(i);
if res > n then
Dec(i)
else
begin
if s[res] = ' ' then
begin
while s[res] = ' ' do
Inc(res);
end
else
begin
while (res <= n) and (s[res] <> ' ') do
Inc(res);
while (res <= n) and (s[res] = ' ') do
Inc(res);
end;
break;
end;
end;
SelText := Pad(res - FPos.X);
end;
procedure TfqbSyntaxMemo.EnterIndent;
var
res: Integer;
begin
if Trim(FText[FPos.Y - 1]) = '' then
res := FPos.X else
res := GetLineBegin(FPos.Y - 1);
CorrectBookmark(FPos.Y, 1);
FPos := Point(1, FPos.Y + 1);
SelText := Pad(res - 1);
end;
procedure TfqbSyntaxMemo.UnIndent;
var
i, res: Integer;
begin
i := FPos.Y - 2;
res := FPos.X - 1;
CorrectBookmark(FPos.Y, -1);
while i >= 0 do
begin
res := GetLineBegin(i);
if (res < FPos.X) and (Trim(FText[i]) <> '') then
break else
Dec(i);
end;
FSelStart := FPos;
FSelEnd := FPos;
Dec(FSelEnd.X, FPos.X - res);
SelText := '';
end;
procedure TfqbSyntaxMemo.ShiftSelected(ShiftRight: Boolean);
var
i, ib, ie: Integer;
s: String;
Shift: Integer;
begin
if FReadOnly then exit;
AddUndo;
if FSelStart.X + FSelStart.Y * FMaxLength < FSelEnd.X + FSelEnd.Y * FMaxLength then
begin
ib := FSelStart.Y - 1;
ie := FSelEnd.Y - 1;
end
else
begin
ib := FSelEnd.Y - 1;
ie := FSelStart.Y - 1;
end;
if FSelEnd.X = 1 then
Dec(ie);
Shift := 2;
if not ShiftRight then
for i := ib to ie do
begin
s := FText[i];
if (Trim(s) <> '') and (GetLineBegin(i) - 1 < Shift) then
Shift := GetLineBegin(i) - 1;
end;
for i := ib to ie do
begin
s := FText[i];
if ShiftRight then
s := Pad(Shift) + s
else if Trim(s) <> '' then
Delete(s, 1, Shift);
FText[i] := s;
end;
UpdateSyntax;
DoChange;
end;
function TfqbSyntaxMemo.GetSelText: String;
var
p1, p2: TPoint;
i: Integer;
begin
if FSelStart.X + FSelStart.Y * FMaxLength < FSelEnd.X + FSelEnd.Y * FMaxLength then
begin
p1 := FSelStart;
p2 := FSelEnd;
Dec(p2.X);
end
else
begin
p1 := FSelEnd;
p2 := FSelStart;
Dec(p2.X);
end;
if LineLength(p1.Y - 1) < p1.X then
begin
Inc(p1.Y);
p1.X := 1;
end;
if LineLength(p2.Y - 1) < p2.X then
p2.X := LineLength(p2.Y - 1);
i := GetPlainTextPos(p1);
Result := Copy(FText.Text, i, GetPlainTextPos(p2) - i + 1);
end;
procedure TfqbSyntaxMemo.SetSelText(Value: String);
var
p1, p2, p3: TPoint;
i: Integer;
s: String;
begin
if FReadOnly then exit;
AddUndo;
if FSelStart.X = 0 then
begin
p1 := FPos;
p2 := p1;
Dec(p2.X);
end
else if FSelStart.X + FSelStart.Y * FMaxLength < FSelEnd.X + FSelEnd.Y * FMaxLength then
begin
p1 := FSelStart;
p2 := FSelEnd;
Dec(p2.X);
end
else
begin
p1 := FSelEnd;
p2 := FSelStart;
Dec(p2.X);
end;
if LineLength(p1.Y - 1) < p1.X then
FText[p1.Y - 1] := FText[p1.Y - 1] + Pad(p1.X - LineLength(p1.Y - 1) + 1);
if LineLength(p2.Y - 1) < p2.X then
p2.X := LineLength(p2.Y - 1);
i := GetPlainTextPos(p1);
s := FText.Text;
Delete(s, i, GetPlainTextPos(p2) - i + 1);
Insert(Value, s, i);
FText.Text := s;
p3 := GetPosPlainText(i + Length(Value));
CorrectBookmark(FPos.Y, p3.y-FPos.Y);
SetPos(p3.X, p3.Y);
FSelStart.X := 0;
DoChange;
UpdateSyntax;
end;
procedure TfqbSyntaxMemo.ClearSel;
begin
if FSelStart.X <> 0 then
begin
FSelStart := Point(0, 0);
Repaint;
end;
end;
procedure TfqbSyntaxMemo.AddSel;
begin
if FSelStart.X = 0 then
FSelStart := FTempPos;
FSelEnd := FPos;
Repaint;
end;
procedure TfqbSyntaxMemo.SetPos(x, y: Integer);
begin
if FMessage <> '' then
begin
FMessage := '';
Repaint;
end;
if x > FMaxLength then x := FMaxLength;
if x < 1 then x := 1;
if y > FText.Count then y := FText.Count;
if y < 1 then y := 1;
FPos := Point(x, y);
if (FWindowSize.X = 0) or (FWindowSize.Y = 0) then exit;
if FOffset.Y >= FText.Count then
FOffset.Y := FText.Count - 1;
if FPos.X > FOffset.X + FWindowSize.X then
begin
Inc(FOffset.X, FPos.X - (FOffset.X + FWindowSize.X));
Repaint;
end
else if FPos.X <= FOffset.X then
begin
Dec(FOffset.X, FOffset.X - FPos.X + 1);
Repaint;
end
else if FPos.Y > FOffset.Y + FWindowSize.Y then
begin
Inc(FOffset.Y, FPos.Y - (FOffset.Y + FWindowSize.Y));
Repaint;
end
else if FPos.Y <= FOffset.Y then
begin
Dec(FOffset.Y, FOffset.Y - FPos.Y + 1);
Repaint;
end;
ShowCaretPos;
UpdateScrollBar;
end;
procedure TfqbSyntaxMemo.ScrollClick(Sender: TObject);
begin
if FUpdating then exit;
FOffset.Y := FVScroll.Position;
if FOffset.Y > FText.Count then
FOffset.Y := FText.Count;
ShowCaretPos;
Repaint;
end;
procedure TfqbSyntaxMemo.ScrollEnter(Sender: TObject);
begin
SetFocus;
end;
procedure TfqbSyntaxMemo.DblClick;
var
s: String;
begin
FDoubleClicked := True;
DoCtrlL;
FSelStart := FPos;
s := LineAt(FPos.Y - 1);
if s <> '' then
while s[FPos.X] in WordChars do
Inc(FPos.X);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -