📄 fqbsynmemo.pas
字号:
s: String;
procedure SetAttr(a: TCharAttributes);
begin
with Canvas do
begin
Brush.Color := Color;
if caText in a then
Font.Assign(FTextAttr);
if caComment in a then
Font.Assign(FCommentAttr);
if caKeyword in a then
Font.Assign(FKeywordAttr);
if caString in a then
Font.Assign(FStringAttr);
if caBlock in a then
begin
Brush.Color := FBlockColor;
Font.Color := FBlockFontColor;
end;
Font.Charset := Self.Font.Charset;
end;
end;
procedure MyTextOut(x, y: Integer; const s: String);
var
i: Integer;
begin
if FIsMonoType then
Canvas.TextOut(x, y, s)
else
with Canvas do
begin
FillRect(Rect(x, y, x + Length(s) * FCharWidth, y + FCharHeight));
for i := 1 to Length(s) do
TextOut(x + (i - 1) * FCharWidth, y, s[i]);
MoveTo(x + Length(s) * FCharWidth, y);
end;
end;
begin
with Canvas do
begin
Brush.Color := clBtnFace;
FillRect(Rect(0, 0, FGutterWidth - 2, Height - FFooterHeight));
FillRect(Rect(0, Height - FFooterHeight, Width, Height));
Pen.Color := clBtnHighlight;
MoveTo(FGutterWidth - 4, 0);
LineTo(FGutterWidth - 4, Height - FFooterHeight + 1);
if FFooterHeight > 0 then
LineTo(Width, Height - FFooterHeight + 1);
if FUpdatingSyntax then Exit;
for i := FOffset.Y to FOffset.Y + FWindowSize.Y - 1 do
begin
if i >= FText.Count then break;
s := FText[i];
PenPos := Point(FGutterWidth, (i - FOffset.Y) * FCharHeight);
j1 := FOffset.X + 1;
a := GetCharAttr(Point(j1, i + 1));
a1 := a;
for j := j1 to FOffset.X + FWindowSize.X do
begin
if j > Length(s) then break;
a1 := GetCharAttr(Point(j, i + 1));
if a1 <> a then
begin
SetAttr(a);
MyTextOut(PenPos.X, PenPos.Y, Copy(FText[i], j1, j - j1));
a := a1;
j1 := j;
end;
end;
SetAttr(a);
MyTextOut(PenPos.X, PenPos.Y, Copy(s, j1, FMaxLength));
if caBlock in GetCharAttr(Point(1, i + 1)) then
MyTextOut(PenPos.X, PenPos.Y, Pad(FWindowSize.X - Length(s) - FOffset.X + 3));
BookmarkDraw(PenPos.Y, i);
ActiveLineDraw(PenPos.Y, i);
end;
if FMessage <> '' then
begin
Font.Name := 'Tahoma';
Font.Color := clWhite;
Font.Style := [fsBold];
Font.Size := 8;
Brush.Color := clMaroon;
FillRect(Rect(0, Height - TextHeight('|') - 6, Width, Height));
TextOut(6, Height - TextHeight('|') - 5, FMessage);
end
else
ShowPos;
end;
end;
procedure TfqbSyntaxMemo.CreateSynArray;
var
i, n, Pos: Integer;
ch: Char;
FSyn: String;
procedure SkipSpaces;
begin
while (Pos <= Length(FSyn)) and
((FSyn[Pos] in [#1..#32]) or
not (FSyn[Pos] in ['_', 'A'..'Z', 'a'..'z', '''', '"', '/', '{', '(', '-'])) do
Inc(Pos);
end;
function IsKeyWord(const s: String): Boolean;
begin
Result := False;
if FKeywords = '' then exit;
if FKeywords[1] <> ',' then
FKeywords := ',' + FKeywords;
if FKeywords[Length(FKeywords)] <> ',' then
FKeywords := FKeywords + ',';
Result := System.Pos(',' + AnsiLowerCase(s) + ',', FKeywords) <> 0;
end;
function GetIdent: TCharAttr;
var
i: Integer;
cm1, cm2, cm3, cm4, st1: Char;
begin
i := Pos;
Result := caText;
if FSyntaxType = stPascal then
begin
cm1 := '/';
cm2 := '{';
cm3 := '(';
cm4 := ')';
st1 := '''';
end
else if FSyntaxType = stCpp then
begin
cm1 := '/';
cm2 := ' ';
cm3 := '/';
cm4 := '/';
st1 := '"';
end
else if FSyntaxType = stSQL then
begin
cm1 := '-';
cm2 := ' ';
cm3 := '/';
cm4 := '/';
st1 := '"';
end
else
begin
cm1 := ' ';
cm2 := ' ';
cm3 := ' ';
cm4 := ' ';
st1 := ' ';
end;
if FSyn[Pos] in ['_', 'A'..'Z', 'a'..'z'] then
begin
while FSyn[Pos] in ['_', 'A'..'Z', 'a'..'z', '0'..'9'] do
Inc(Pos);
if IsKeyWord(Copy(FSyn, i, Pos - i)) then
Result := caKeyword;
Dec(Pos);
end
else if (FSyn[Pos] = cm1) and (FSyn[Pos + 1] = cm1) then
begin
while (Pos <= Length(FSyn)) and not (FSyn[Pos] in [#10, #13]) do
Inc(Pos);
Result := caComment;
end
else if FSyn[Pos] = cm2 then
begin
while (Pos <= Length(FSyn)) and (FSyn[Pos] <> '}') do
Inc(Pos);
Result := caComment;
end
else if (FSyn[Pos] = cm3) and (FSyn[Pos + 1] = '*') then
begin
while (Pos < Length(FSyn)) and not ((FSyn[Pos] = '*') and (FSyn[Pos + 1] = cm4)) do
Inc(Pos);
Inc(Pos, 2);
Result := caComment;
end
else if FSyn[Pos] = st1 then
begin
Inc(Pos);
while (Pos < Length(FSyn)) and (FSyn[Pos] <> st1) and not (FSyn[Pos] in [#10, #13]) do
Inc(Pos);
Result := caString;
end;
Inc(Pos);
end;
begin
FSyn := FText.Text + #0#0#0#0#0#0#0#0#0#0#0;
FAllowLinesChange := False;
Pos := 1;
while Pos < Length(FSyn) do
begin
n := Pos;
SkipSpaces;
for i := n to Pos - 1 do
if FSyn[i] > #31 then
FSyn[i] := Chr(Ord(caText));
n := Pos;
ch := Chr(Ord(GetIdent));
for i := n to Pos - 1 do
if FSyn[i] > #31 then
FSyn[i] := ch;
end;
FUpdatingSyntax := True;
FSynStrings.Text := FSyn;
FSynStrings.Add(' ');
FUpdatingSyntax := False;
end;
procedure TfqbSyntaxMemo.UpdateView;
begin
UpdateSyntax;
Invalidate;
end;
procedure TfqbSyntaxMemo.CopyPopup(Sender: TObject);
begin
CopyToClipboard;
end;
procedure TfqbSyntaxMemo.PastePopup(Sender: TObject);
begin
PasteFromClipboard;
end;
procedure TfqbSyntaxMemo.CutPopup(Sender: TObject);
begin
CutToClipboard;
end;
{$IFDEF Delphi4}
procedure TfqbSyntaxMemo.MouseWheelUp(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
FVScroll.Position := FVScroll.Position - FVScroll.SmallChange * KWheel;
end;
procedure TfqbSyntaxMemo.MouseWheelDown(Sender: TObject;
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
begin
FVScroll.Position := FVScroll.Position + FVScroll.SmallChange * KWheel;
end;
{$ENDIF}
procedure TfqbSyntaxMemo.SetShowGutter(Value: boolean);
begin
FShowGutter := Value;
if Value then
FGutterWidth := 20
else
FGutterWidth := 0;
Repaint;
end;
procedure TfqbSyntaxMemo.SetShowFooter(Value: boolean);
begin
FShowFooter := Value;
if Value then
FFooterHeight := 20
else
FFooterHeight := 0;
Repaint;
end;
function TfqbSyntaxMemo.FMemoFind(Text: String; var Position : TPoint): boolean;
var
i, j : integer;
begin
j := 0;
result := False;
if FText.Count > 1 then
begin
Text := UpperCase(Text);
for i := Position.Y to FText.Count - 1 do
begin
j := Pos( Text, UpperCase(FText[i]));
if j > 0 then
begin
Result := True;
break;
end
end;
Position.X := j;
Position.Y := i + 1;
end;
end;
function TfqbSyntaxMemo.Find(Text: String): boolean;
var
Position: TPoint;
begin
Position := FPos;
if FMemoFind(Text, Position) then
begin
SetPos(Position.X, Position.Y);
result := true;
end
else
begin
ShowMessage('Text "'+Text+'" not found.');
result := false;
end;
end;
procedure TfqbSyntaxMemo.ActiveLineDraw(Y : integer; line : integer);
begin
if ShowGutter then
with Canvas do
if line = FActiveLine then
begin
Brush.Color := clRed;
Pen.Color := clBlack;
Ellipse(4, Y+4, 11, Y+11);
end;
end;
procedure TfqbSyntaxMemo.BookmarkDraw(Y : integer; line : integer);
var
bm : integer;
begin
if ShowGutter then
with Canvas do
begin
bm := IsBookmark(Line);
if bm >= 0 then
begin
Brush.Color := clBlack;
FillRect(Rect(3, Y + 1, 13, Y + 12));
Brush.Color := clGreen;
FillRect(Rect(2, Y + 2, 12, Y + 13));
Font.Name := 'Tahoma';
Font.Color := clWhite;
Font.Style := [fsBold];
Font.Size := 7;
TextOut(4, Y + 2, IntToStr(bm));
end
else
begin
Brush.Color := clBtnFace;
FillRect(Rect(2, Y + 2, 13, Y + 13));
end;
end;
end;
function TfqbSyntaxMemo.IsBookmark(Line : integer): integer;
var
Pos : integer;
begin
Result := -1;
{$IFDEF Delphi4}
for Pos := 0 to Length(Bookmarks) - 1 do
{$ELSE}
for Pos := 0 to 9 do
{$ENDIF}
if Bookmarks[Pos] = Line then
begin
Result := Pos;
break;
end;
end;
procedure TfqbSyntaxMemo.AddBookmark(Line, Number : integer);
begin
{$IFDEF Delphi4}
if Number < Length(Bookmarks) then
{$ELSE}
if Number < 10 then
{$ENDIF}
begin
Bookmarks[Number] := Line;
Repaint;
end;
end;
procedure TfqbSyntaxMemo.DeleteBookmark(Number : integer);
begin
{$IFDEF Delphi4}
if Number < Length(Bookmarks) then
{$ELSE}
if Number < 10 then
{$ENDIF}
begin
Bookmarks[Number] := -1;
Repaint;
end;
end;
procedure TfqbSyntaxMemo.CorrectBookmark(Line : integer; delta : integer);
var
i : integer;
begin
{$IFDEF Delphi4}
for i := 0 to Length(Bookmarks) - 1 do
{$ELSE}
for i := 0 to 9 do
{$ENDIF}
if Bookmarks[i] >= Line then
Inc(Bookmarks[i], Delta);
end;
procedure TfqbSyntaxMemo.GotoBookmark(Number : integer);
begin
{$IFDEF Delphi4}
if Number < Length(Bookmarks) then
{$ELSE}
if Number < 10 then
{$ENDIF}
if Bookmarks[Number] >= 0 then
SetPos(0, Bookmarks[Number] + 1);
end;
procedure TfqbSyntaxMemo.DOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Accept := Source is TTreeView;
end;
procedure TfqbSyntaxMemo.DDrop(Sender, Source: TObject; X, Y: Integer);
begin
if Source is TTreeView then
begin
SetPos((X - FGutterWidth) div FCharWidth + 1 + FOffset.X,
Y div FCharHeight + 1 + FOffset.Y);
SetSelText(TTreeView(Source).Selected.Text);
end;
end;
procedure TfqbSyntaxMemo.SetKeywordAttr(Value: TFont);
begin
FKeywordAttr.Assign(Value);
UpdateSyntax;
end;
procedure TfqbSyntaxMemo.SetStringAttr(Value: TFont);
begin
FStringAttr.Assign(Value);
UpdateSyntax;
end;
procedure TfqbSyntaxMemo.SetTextAttr(Value: TFont);
begin
FTextAttr.Assign(Value);
UpdateSyntax;
end;
procedure TfqbSyntaxMemo.SetCommentAttr(Value: TFont);
begin
FCommentAttr.Assign(Value);
UpdateSyntax;
end;
procedure TfqbSyntaxMemo.SetActiveLine(Line : Integer);
begin
FActiveLine := Line;
Repaint;
end;
function TfqbSyntaxMemo.GetActiveLine: Integer;
begin
Result := FActiveLine;
end;
//
procedure TfqbSynMemoSearch.FormKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then
ModalResult := mrOk;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -