delphieditordelphi-2007synedit

SynEdit OnPaintTransientDemo


I'm working with Delphi 2007 and SynEdit component.

I'm the main developer of an open source editor (Tinn-R) and I'm trying to switch from the SynEdit ANSI to UNICODE.

After some months of work everything is working fine except OnPaintTransient procedure.

To try to discover the source of the problem I have tried the original demo OnPaintTransientDemo. This works perfectly in the latest ANSI version of SynEdit. However, I'm not getting the same result with the latest UNICODE version.

if the instruction occupies only one line, only one symbol "[] {} or ()" near at the cursor is mistakenly highlighted, which closes not.

In other words, when you click on the first bracket "(" the last bracket ")" doesn't change color. It should color the start and end tag. For example, considering "|" as the cursor position:

(|aaaa) -> only ( is highlighted
(aaaa|) -> only ) is highlighted

However, if the symbols are in different lines both are correctly highlighted:

(|a
a
a
a) -> both () are highlighted

(a
a
a
a|) -> both () are highlighted

This is looking like a bug in the sources of the component!
(Doing debug I could not find the source of the bug.)

Anyone can help please?


Solution

  • The code below (IceMan is the original author) works fine for me:

    procedure TForm1.EditorPaintTransient(Sender: TObject; Canvas: TCanvas; TransientType: TTransientType);
    var
      Editor: TSynEdit;
      OpenChars: array of WideChar;//[0..2] of WideChar=();
      CloseChars: array of WideChar;//[0..2] of WideChar=();
      Attri: TSynHighlighterAttributes;
    
    function IsCharBracket(AChar: WideChar): Boolean;
    begin
      case AChar of
        '{',
        '[',
        '(',
        '<',
        '}',
        ']',
        ')',
        '>':
        Result:= True;
      else
        Result:= False;
      end;
    end;
    
    function CharToPixels(P: TBufferCoord): TPoint;
    begin
      Result:=Editor.RowColumnToPixels(Editor.BufferToDisplayPos(P));
    end;
    
    procedure SetCanvasStyle;
    begin
      Editor.Canvas.Brush.Style:= bsSolid; //Clear;
      Editor.Canvas.Font.Assign(Editor.Font);
      Editor.Canvas.Font.Style:= Attri.Style;
      if (TransientType = ttAfter) then begin
        Editor.Canvas.Font.Color:= FBracketFG;
        Editor.Canvas.Brush.Color:= FBracketBG;
      end
      else begin
        Editor.Canvas.Font.Color:= Attri.Foreground;
        Editor.Canvas.Brush.Color:= Attri.Background;
      end;
    
      if (Editor.Canvas.Font.Color = clNone) then
        Editor.Canvas.Font.Color:= Editor.Font.Color;
      if (Editor.Canvas.Brush.Color = clNone) then
        Editor.Canvas.Brush.Color:= Editor.Color;
    end;
    
    var
    P  : TBufferCoord;
    Pix: TPoint;
    D  : TDisplayCoord;
    S  : WideString;
    I,
     ArrayLength,
     start: Integer;
    TmpCharA,
     TmpCharB: WideChar;
    
    begin
      try
        // if Memo1.InReplaceStatus = False then
        // begin
        (*
        if fMain.SyntaxHEnabled = False then exit;
        if Memo1.Highlighter = nil then exit;
        if fMain.BracketMatching = False then exit;
        if TSynEdit(Sender).SelAvail then exit;
        *)
        Editor:= TSynEdit(Sender);
        ArrayLength:= 3;
        (*
        if (Editor.Highlighter = SynHTMLSyn1) or (Editor.Highlighter = SynXMLSyn1) then
        inc(ArrayLength);
        *)
        SetLength(OpenChars,
                  ArrayLength);
        SetLength(CloseChars,
                  ArrayLength);
    
        for i:= 0 to ArrayLength - 1 do
          Case i of
            0: begin
                 OpenChars[i]:= '(';
                 CloseChars[i]:= ')';
               end;
            1: begin
                 OpenChars[i]:= '{';
                 CloseChars[i]:= '}';
               end;
            2: begin
                 OpenChars[i]:= '[';
                 CloseChars[i]:= ']';
               end;
            3: begin
                 OpenChars[i]:= '<';
                 CloseChars[i]:= '>';
               end;
          end;
    
        P:= Editor.CaretXY;
        D:= Editor.DisplayXY;
        Start:= Editor.SelStart;
    
        if (Start > 0) and
           (Start <= length(Editor.Text)) then
          TmpCharA:= Editor.Text[Start]
        else
          TmpCharA:= #0;
    
        if (Start < length(Editor.Text)) then
          TmpCharB:= Editor.Text[Start + 1]
        else
          TmpCharB:= #0;
    
        if not IsCharBracket(TmpCharA) and
           not IsCharBracket(TmpCharB) then
          Exit;
    
        S:= TmpCharB;
        if not IsCharBracket(TmpCharB) then begin
          P.Char:= P.Char - 1;
          S:= TmpCharA;
        end;
    
        Editor.GetHighlighterAttriAtRowCol(P,
                                           S,
                                           Attri);
    
        if (Editor.Highlighter.SymbolAttribute = Attri) then begin
          for i:= low(OpenChars) to High(OpenChars) do begin
            if (S = OpenChars[i]) or
               (S = CloseChars[i]) then begin
              Pix:= CharToPixels(P);
              SetCanvasStyle;
              Editor.Canvas.TextOut(Pix.X,
                                    Pix.Y,
                                    S);
              P := Editor.GetMatchingBracketEx(P);
    
              if (P.Char > 0) and
                 (P.Line > 0) then begin
                Pix:= CharToPixels(P);
                if Pix.X > Editor.Gutter.Width then begin
                  SetCanvasStyle;
                  if S = OpenChars[i] then
                    Editor.Canvas.TextOut(Pix.X,
                                          Pix.Y,
                                          CloseChars[i])
                  else
                    Editor.Canvas.TextOut(Pix.X,
                                          Pix.Y,
                                          OpenChars[i]);
                end; //if Pix.X >
              end; //if (P.Char > 0)
            end; //if (S = OpenChars[i])
          end; //for i:= low(OpenChars)
          Editor.Canvas.Brush.Style := bsSolid;
        end; //if (Editor.Highlighter.SymbolAttribute = Attri)
      except
      // TODO
      end; //try
    end;