Search code examples
delphisyntax-highlightinghighlighting

Highlighting delphi code in RAD Studio


I am trying to highlight Delphi code in RAD Studio with a Delphi plugin. I use OpentoolsAPI to get code out of the editor.

EditorServices := BorlandIDEServices as IOTAEditorServices;

Buffer := EditorServices.TopBuffer;
Editblock := EditorServices.TopView.GetBlock;
Buffer.EditPosition.Move(1,1);
Editblock.BeginBlock;
Editblock.Extend(10,5);

After that, the open tools FAQ tells me to use a custom highlighter. I copied a custom highlighter from here : http://www.delphi-central.com/syntax_highlighting.aspx

But still, The documentation is very limited, and I cannot figure a way to use this custom highlighter. What I am currently trying is the following:

HighlightServices := BorlandIDEServices as IOTAHighlightServices;
SimpleHighLight := TSimpleHighlight.Create;
HighlightServices.AddHighlighter(SimpleHighLight);

Text := Editblock.Text; //string
StartClass := 1; //integer
SyntaxByte := SyntaxOff; //byte
SyntaxCode := @SyntaxByte; //POTASyntaxCode

SimpleHighLight.Tokenize(StartClass,Addr(Text),Text.Length, SyntaxCode);

But that results in an access violation error at this line of the demo code:

FillChar(HighlightCodes^, LineBufLen, $E);

Can somebody give me an example of the right implementation? Or help me out with what I am doing wrong?


Solution

  • I stopped looking for a way to use the highlighter. I could not get it working.

    Luckely i found an other solution to my problem, for anyone interested :)

    The OpenToolsAPI makes it possible to add notifiers. an example notifier can be found here: http://www.gexperts.org/examples/IdeNotifier.pas.

    I had to modify the notifier from the example to my own notifier. This is the result:

    unit ViewPaintNotifier;
    
    interface
    
    uses
      ToolsAPI, System.Types, Vcl.Graphics;
    
    type
      TViewPaintNotifier = class(TInterfacedObject, IOTANotifier, INTAEditViewNotifier)
      private
      public
        constructor Create;
        destructor Destroy; override;
      public
        // INTAEditViewNotifier
        procedure BeginPaint(const View: IOTAEditView; var FullRepaint: Boolean);
        procedure EditorIdle(const View: IOTAEditView);
        procedure EndPaint(const View: IOTAEditView);
        procedure PaintLine(const View: IOTAEditView; LineNumber: Integer;
          const LineText: PAnsiChar; const TextWidth: Word;
          const LineAttributes: TOTAAttributeArray; const Canvas: TCanvas;
          const TextRect: TRect; const LineRect: TRect; const CellSize: TSize);
        // IOTANotifier
        procedure AfterSave;
        procedure BeforeSave;
        procedure Destroyed;
        procedure Modified;
      end;
    
      procedure register(View: IOTAEditView);
      procedure RemoveNotifier(View: IOTAEditView);
    
    implementation
    
    uses
      System.SysUtils, Vcl.Dialogs, System.Generics.Collections;
    
    var
      NotifierIndexDictionary : TDictionary<string,Integer>;
    
    procedure Register(View: IOTAEditView);
    var
      Services: IOTAEditorServices;
      NotifierIndexPair : Tpair<string,Integer>;
    begin
      if not Assigned(NotifierIndexDictionary) then
         NotifierIndexDictionary := TDictionary<string,Integer>.create;
      NotifierIndexPair := NotifierIndexDictionary.ExtractPair(View.Buffer.FileName);
    
      if (NotifierIndexDictionary.ExtractPair(View.Buffer.FileName).Value = 0) then
      begin
        NotifierIndexDictionary.Add(View.Buffer.FileName,View.addNotifier(TViewPaintNotifier.Create));
      end;
    end;
    
    procedure RemoveNotifier(View: IOTAEditView);
    var
      Services: IOTAEditorServices;
    begin
      if (NotifierIndexDictionary.ExtractPair(View.Buffer.FileName).Value > 0) then
      begin
        View.RemoveNotifier(NotifierIndexDictionary.ExtractPair(View.Buffer.FileName).Value);
        NotifierIndexDictionary.Add(View.Buffer.FileName,0);
      end;
    end;
    
    
    { TViewPaintNotifier }
    
    constructor TViewPaintNotifier.Create;
    begin
    
    end;
    
    destructor TViewPaintNotifier.Destroy;
    begin
    
      inherited;
    end;
    
    procedure TViewPaintNotifier.EditorIdle(const View: IOTAEditView);
    begin
    
    end;
    
    procedure TViewPaintNotifier.BeginPaint(const View: IOTAEditView;
      var FullRepaint: Boolean);
    begin
    
    end;
    
    procedure TViewPaintNotifier.EndPaint(const View: IOTAEditView);
    begin
    
    end;
    
    procedure TViewPaintNotifier.PaintLine(const View: IOTAEditView;
      LineNumber: Integer; const LineText: PAnsiChar; const TextWidth: Word;
      const LineAttributes: TOTAAttributeArray; const Canvas: TCanvas;
      const TextRect, LineRect: TRect; const CellSize: TSize);
    begin
      //use the canvas to draw something
      //LineRect is the position of the line on the canvas, draw it here for every line
    end;
    
    procedure TViewPaintNotifier.AfterSave;
    begin
    
    end;
    
    procedure TViewPaintNotifier.BeforeSave;
    begin
    
    end;
    
    procedure TViewPaintNotifier.Destroyed;
    begin
    
    end;
    
    procedure TViewPaintNotifier.Modified;
    begin
    
    end;
    

    With this notifier i can draw something with the canvas to get the attention of the user.