Page 1 of 1

Multiple word and syntax highlighting

Posted: Mon Jun 28, 2021 1:13 pm
by standay
With TRichViewEdit, I'd like to be able to have multiple occurrences of a given word highlighted, as well as some basic syntax highlighting too. On both of these, I only need and want it marked within the displayed (visible) text, not the entire text. Unmarking either multiple words or syntax would have to be done for the entire text. I'm doing this right now with the Scintilla edit component but Scintilla does not handle images.

I've had limited success using the RectMarks and MarkSubString calls. MarkSubString does the marking more like I want (i.e., different backcolor), but it affects all the text and slows down with a big file, and I can't figure out how to un-mark what it marks. Syntax would mostly be bold keywords and color on keywords.

If it's possible, I'd like to mark and un-mark text without using actual text selections. I have some basic marking working now using text selections, but I have to save and restore the initial selection as well as VScrollPos and HScrollPos to keep it all from jumping around. And the only way I've found to un-mark it all is by brute force: I select all and then apply a normal text style. There must be a better way...

My questions are:

- Is there a way to work with just the displayed part of the text?

- Is there a fast way to "un-mark" everything that was previously marked while leaving other text formatting alone?

- Is there a way to add setting font styles (bold, italic etc.) to MarkSubString? Color and BackColor work but I want font style as well.

Thanks. I hope this all makes sense. I'll attach a screenshot of the effects I'm after.

Re: Multiple word and syntax highlighting

Posted: Wed Jun 30, 2021 10:31 pm
by standay
Here's what I have at this point. It works, but needs more development. Maybe this will give someone else some ideas. I set up the textstyle in my RVStyle1. The commented code was what I used to do it on the fly as well. Just thought putting it into the RVStyle1 made more sense.

test trichview screencap
test trichview screencap
Image2.png (6.4 KiB) Viewed 5570 times

Code: Select all

procedure TForm1.btnMarkSelClick(Sender: TObject);
var
  i, k, FStart, FEnd, VScroll, HScroll : integer;
  ItemNo1, ItemNo2: Integer;
  selText: string;
  KeyWords: TStringList;
begin

  //store positioning (uses RVLinear):
  RVGetSelection(RichViewEdit1, FStart, FEnd );
  VScroll := RichViewEdit1.VScrollPos;
  HScroll := RichViewEdit1.HScrollPos;

  RichViewEdit1.BeginUpdate;

  for i := 0 to RichViewEdit1.ItemCount-1 do
  begin
    k := RichViewEdit1.RvData.GetItemStyle(i);
    if RVStyle1.TextStyles[k].StyleName = 'MarkWord' then
    begin
      RichViewEdit1.GetItem(i).StyleNo := RVStyle1.TextStyles[0].Index;
      RichViewEdit1.Format; //returns spacing between words to normal
      RichViewEdit1.ClearUndo;
    end;
  end;

  //restore positioning:
  RVSetSelection(RichViewEdit1, FStart, FEnd);
  RichViewEdit1.VScrollPos := VScroll;
  RichViewEdit1.HScrollPos := HScroll;

  //store positioning:
  RVGetSelection(RichViewEdit1, FStart, FEnd );
  VScroll := RichViewEdit1.VScrollPos;
  HScroll := RichViewEdit1.HScrollPos;

  //store surrent selected text:
  selText := RichViewEdit1.GetSelText;

  if RichViewEdit1.RVData.SearchText(true, false,
                           true, true, true, true, selText ) then
  begin
    ItemNo1 := RichViewEdit1.RVData.GetFirstItemVisible;
    ItemNo2 := RichViewEdit1.RVData.GetLastItemVisible;

    if (RichViewEdit1.CurItemNo >= ItemNo1) and
    (RichViewEdit1.CurItemNo <= ItemNo2) then
    begin
      {if RichViewEdit1.Style.TextStyles.Count = 6 then
      RichViewEdit1.Style.TextStyles.Add;
      RichViewEdit1.Style.TextStyles[RichViewEdit1.Style.TextStyles.Count].Style := [fsBold];
      RichViewEdit1.Style.TextStyles[RichViewEdit1.Style.TextStyles.Count].Color := clWebOrange ;
      RichViewEdit1.Style.TextStyles[RichViewEdit1.Style.TextStyles.Count].BackColor := clMaroon ;
      RichViewEdit1.ApplyTextStyle(RichViewEdit1.Style.TextStyles.Count);}
      RichViewEdit1.ApplyTextStyle( RVStyle1.TextStyles[6].Index );
    end;

    while RichViewEdit1.RVData.SearchText(true, false,
                               true, false, true, true, selText ) do
    begin
      if (RichViewEdit1.CurItemNo >= ItemNo1) and
      (RichViewEdit1.CurItemNo <= ItemNo2) then
      begin
        {RichViewEdit1.Style.TextStyles[RichViewEdit1.Style.TextStyles.Count].Style := [fsBold];
        RichViewEdit1.Style.TextStyles[RichViewEdit1.Style.TextStyles.Count].Color := clWebOrange ;
        RichViewEdit1.ApplyTextStyle(RichViewEdit1.Style.TextStyles.Count);}
        RichViewEdit1.ApplyTextStyle( RVStyle1.TextStyles[6].Index );
      end;
    end;


  end;

  //keyword test:

  KeyWords := TStringList.Create;
  KeyWords.Add('begin');
  KeyWords.Add('var');
  KeyWords.Add('try');

  for i := 0 to KeyWords.Count-1 do
  begin

    if RichViewEdit1.RVData.SearchText(true, false,
                             true, true, true, true, KeyWords.Strings[i] ) then
    begin
      ItemNo1 := RichViewEdit1.RVData.GetFirstItemVisible;
      ItemNo2 := RichViewEdit1.RVData.GetLastItemVisible;

      if (RichViewEdit1.CurItemNo >= ItemNo1) and
      (RichViewEdit1.CurItemNo <= ItemNo2) then
      begin
        RichViewEdit1.ApplyTextStyle( RVStyle1.TextStyles[3].Index );
      end;

      while RichViewEdit1.RVData.SearchText(true, false,
                                 true, false, true, true, KeyWords.Strings[i] ) do
      begin
        if (RichViewEdit1.CurItemNo >= ItemNo1) and
        (RichViewEdit1.CurItemNo <= ItemNo2) then
        begin
          RichViewEdit1.ApplyTextStyle( RVStyle1.TextStyles[3].Index );
        end;
      end;

    end;

  end;

  KeyWords.Free;

  //restore positioning:
  RVSetSelection(RichViewEdit1, FStart, FEnd);
  RichViewEdit1.VScrollPos := VScroll;
  RichViewEdit1.HScrollPos := HScroll;
  RichViewEdit1.EndUpdate;

end;