Re: Why doesn't this code wrok?


[ Related Articles and Replies ] [ Post Followup ] [ DelphiLand Discussion Forum ]

Posted by webmaster Guido on July 02, 2002 at 17:18:30:

In Reply to: Why doesn't this code wrok? posted by Rbrrneck on July 01, 2002 at 14:46:44:

:
: I use this code for color syntaxing.
: Just drop a Richedit and button on a form and put this code. Oh yeah, put some of the words in the array in the richedits text.
: Here's the code:

const:
  red: array[0..1] of String = ('var', 'const');

procedure TForm1.Button1Click(Sender: TObject);
var i,i2,i3,i4,i5,i6:integer;
begin
  for i:=0 to Richedit1.lines.count-1 do begin
    for i2:=0 to High(red) do begin
      i3:=0;
      i4:=ansipos(red[i3],Richedit1.lines[i3]);
      i5:=Length(red[i3]);
      Richedit1.selstart:=i4-1;
      Richedit1.sellength:=i5;
      Richedit1.Selattributes.Color:=clred;
      i4:=0;
      i5:=0;
    end;
  end;
end;

-------------

Your code was a bit difficult to follow, with all those i's :) so I took the liberty to slightly rewrite it.
L stands for line counter, K for keyword counter, and P for Position.

const
  KeyWords: array[0..1] of string = ('var', 'const');

procedure TForm1.Button1Click(Sender: TObject);
var
  L, K, P: integer;
  Line, KeyW: string;
begin
  for L := 0 to Richedit1.Lines.Count - 1 do begin
    Line := UpperCase(Richedit1.Lines[L]);
    for K := Low(KeyWords) to High(KeyWords) do begin
      KeyW := UpperCase(KeyWords[K]);
      P := Pos(KeyW, Line);
      if P > 0 then begin
        RichEdit1.SelStart := P - 1;
        RichEdit1.SelLength := Length(KeyW);
        RichEdit1.SelAttributes.Color := clRed;
      end;
    end;
  end;
end;

Problem 1: P gives the position of the keyword in the *line*, whereas RichEdit1.SelStart refers to the beginning of the *entire text* of the RichEdit component (RichEdit1.Text). So, this would be correct for the first line, but not anymore for all the following lines.

To improve on this, you can add an integer "offset" to P for each line. OffSet would start out as 0. After each line is processed, increment OffSet with the length of that line plus 2 (for the invisible line-endings code CR/LF).

procedure TForm1.Button1Click(Sender: TObject);
var
  L, K, P, OffSet: integer;
  Line, KeyW: string;
begin
  OffSet := 0;
  for L := 0 to Richedit1.Lines.Count - 1 do begin
    Line := UpperCase(Richedit1.Lines[L]);
    for K := Low(KeyWords) to High(KeyWords) do begin
      KeyW := UpperCase(KeyWords[K]);
      P := Pos(KeyW, Line);
      if P > 0 then begin
        RichEdit1.Selstart := P - 1 + OffSet;
        RichEdit1.SelLength := Length(KeyW);
        RichEdit1.SelAttributes.Color := clRed;
      end;
    end;
    OffSet := OffSet + Length(Line) + 2;
  end;
end;

Problem 2: this still does not work satisfactory, because only the *first* occurrance of a keyword in each line will be coloured red. You really have to look at *each* word in the text, one after the other, and check if it is a keyword.

Problem 3: keywords that are part of a larger word, also will be coloured (like the VAR in inVARIable, CONST in CONSTantinopel,...)

Syntax highlighting is not a trivial task ;-)


Related Articles and Replies:


[ Related Articles and Replies ] [ Post Followup ] [ DelphiLand Discussion Forum ]