unit main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, ecSyntAnal, ecSyntMemo, StdCtrls, ExtCtrls;

type
  TForm2 = class(TForm)
    SyntaxMemo1: TSyntaxMemo;
    SyntAnalyzer1: TSyntAnalyzer;
    SyntStyles1: TSyntStyles;
    Panel1: TPanel;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    Button1: TButton;
    procedure SyntaxMemo1GetStyleEntry(Sender: TObject; CurPos: Integer;
      StyleList: TStyleEntries; var NextPos: Integer);
    procedure SyntaxMemo1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure SyntaxMemo1MouseEnter(Sender: TObject);
    procedure Form2KeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Form2KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure Button1Click(Sender: TObject);
    procedure SyntAnalyzer1TokenRules0MouseClick(Editor: TObject; TokenIndex: Integer;
      Button: TMouseButton; Shift: TShiftState);
    procedure SyntaxMemo1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    FHltToken: integer;
    procedure SetHltToken(Value: integer);
  public
    property HltToken: integer read FHltToken write SetHltToken;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.FormCreate(Sender: TObject);
begin
  FHltToken := -1;
end;

procedure TForm2.SyntaxMemo1GetStyleEntry(Sender: TObject; CurPos: Integer;
  StyleList: TStyleEntries; var NextPos: Integer);
begin
  NextPos := -1;
  if (FHltToken <> -1) and (SyntStyles1.Styles.Count > 0) then
   with SyntaxMemo1.SyntObj do

    if (FHltToken < TagCount) and (Tags[FHltToken].StartPos <= CurPos)
       and (Tags[FHltToken].EndPos > CurPos) then
     begin
      StyleList.Add(TStyleEntry.Create(SyntStyles1.Styles[0],
                                       Tags[FHltToken].StartPos,
                                       Tags[FHltToken].EndPos));
      NextPos := Tags[FHltToken].EndPos;
     end else
    if CurPos < Tags[FHltToken].StartPos then
      NextPos := Tags[FHltToken].StartPos;
end;

procedure TForm2.SetHltToken(Value: integer);
var Upd: TPoint; // updating range
begin
  if Value <> -1 then
   if SyntaxMemo1.SyntObj.Tags[Value].TokenType <> 2 {Identifier} then
    Value := -1;

  Upd.X := -1;
  if FHltToken <> Value then
   begin
    if (FHltToken >= 0) and (FHltToken < SyntaxMemo1.SyntObj.TagCount) then
     with SyntaxMemo1.SyntObj.Tags[FHltToken] do
      Upd := Point(StartPos, EndPos);

    FHltToken := Value;

    if (FHltToken >= 0) and (FHltToken < SyntaxMemo1.SyntObj.TagCount) then
     with SyntaxMemo1.SyntObj.Tags[FHltToken] do
      if Upd.X = -1 then Upd := Point(StartPos, EndPos) else
       begin
        if Upd.X > StartPos then Upd.X := StartPos;
        if Upd.Y < EndPos then Upd.Y := EndPos;
       end;
    SyntaxMemo1.InvalidateTextRange(Upd.X, Upd.Y, not CheckBox2.Checked);
   end;
end;

procedure TForm2.SyntaxMemo1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
  if not CheckBox1.Checked or (ssCtrl in Shift) then
    HltToken := SyntaxMemo1.TokenAtPos(Point(X, Y))
  else HltToken := -1;
end;

procedure TForm2.SyntaxMemo1MouseEnter(Sender: TObject);
begin
  HltToken := -1;
end;

// This handlers for Control key processing
//    Form2.KeyPreview := True
procedure TForm2.Form2KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if CheckBox1.Checked and (Key = VK_CONTROL) then
   HltToken := -1;
end;

procedure TForm2.Form2KeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if CheckBox1.Checked and (Key = VK_CONTROL) then
   with SyntaxMemo1 do
    HltToken := TokenAtPos(ScreenToClient(Mouse.CursorPos));
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  SyntStyles1.Customize;
end;

// mouse click on token
procedure TForm2.SyntAnalyzer1TokenRules0MouseClick(Editor: TObject; TokenIndex: Integer;
  Button: TMouseButton; Shift: TShiftState);
begin
{  if ssCtrl in Shift then
   begin
     MessageBox(Handle, PChar('You click token: ' + SyntaxMemo1.SyntObj.TagStr[TokenIndex]),
      'TTokenRule.OnMouseClick', MB_ICONINFORMATION or MB_OK);
     // You need to call Abort to skip mouse processing
     Abort;
   end;}
end;

procedure TForm2.SyntaxMemo1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
const IdentifierTokenIndex = 2;
var TokIdx: Integer;
begin
  if (ssCtrl in Shift) and (Button = mbLeft) then
   begin
     TokIdx := SyntaxMemo1.SyntObj.TokenAtPos(SyntaxMemo1.CaretPosToStrPos(SyntaxMemo1.MouseToCaret(X,Y)));
     if (TokIdx <> -1) and (SyntaxMemo1.SyntObj.Tags[TokIdx].TokenType = IdentifierTokenIndex) then
       MessageBox(Handle, PChar('You click token: ' + SyntaxMemo1.SyntObj.TagStr[TokIdx]),
        'TTokenRule.OnMouseClick', MB_ICONINFORMATION or MB_OK);
     // You need to call Abort to skip mouse processing
     Abort;
   end;
end;

end.
