Search through characters looking for a format match

General TRichView support forum. Please post your questions here
Post Reply
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Search through characters looking for a format match

Post by jgkoehn »

Greetings,
I have a format tester that works on a per item basis.
Which loops through the items until a series of items has the same format and selects them. I am using GetItem and then it's font style.
However, I would like to increase its precision to per character if the user requires it. Since at times a word may be partially bold for example.
Is there a way that works through characters in an item?
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Search through characters looking for a format match

Post by Sergey Tkachenko »

Sorry, I do not understand the question.
For each item, you can get its style and its text, so you can process characters as you want.
If it's difficult to find match that is located in different items, you can use SearchText method and OnTextFound event.
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Search through characters looking for a format match

Post by jgkoehn »

Oops duplicate post
Last edited by jgkoehn on Mon Jul 27, 2020 6:21 pm, edited 3 times in total.
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Search through characters looking for a format match

Post by jgkoehn »

Thanks Sergey. Tomorrow or maybe later today I will post an example of my code for searching format.

Can you explain to me or point me in the direction of what an item is for example in SetSelectionBounds.
0. Is it a line?
1. Is it a text word, graphic, etc
2. Is it when every formatting changes on text so an actual word may have different items?
3. Is a space considered an item?
Also a question on Offs are they unique per item thst is start over each time at 1 or 1 for the first character or is this based on per line, paragraph or overall document?
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Search through characters looking for a format match

Post by jgkoehn »

Here is my format checking code.

Code: Select all

function TMainForm.FindFormatCheckerBool: Boolean;
var
  i, j,k: Integer;
  PsiNo, PsiOffs, PeiNo, PeiOffs: Integer;
  siGrp, eiGrp: Integer;
  GrpBoolStart, GrpBoolEnd: Boolean;
begin
  Result := False;
  siGrp := -1;
  eiGrp := -1;
     //I need to get each item and go through them. May not work on tables.
     if RegThenFmtChk.Checked = False then
        begin
        GRichViewEdit.GetSelectionBounds(PsiNo, PsiOffs, PeiNo, PeiOffs, True);
        GRichViewEdit.SetSelectionBounds(PsiNo, PsiOffs, GRichViewEdit.ItemCount-1, GRichViewEdit.GetOffsAfterItem(GRichViewEdit.ItemCount-1));
        if FindShowChk.Checked then GRichViewEdit.Refresh;
     end;
       GRichViewEdit.GetSelectionBounds(PsiNo, PsiOffs, PeiNo, PeiOffs, True);
     if FindShowChk.Checked then GRichViewEdit.Refresh;
     i := PsiNo-1;
     GrpBoolStart := False;
     GrpBoolEnd := False;
     while (i < PeiNo) AND (GrpBoolEnd = False) do
       begin
       Inc(i);
       j := i; // GRichViewEdit.GetItemNo(GRichViewEdit.GetCurrentItem);
       if j = -1 then
          begin
          Inc(i);
          continue;
       end;
           k := GRichViewEdit.GetItemStyle(j);
              //Font Style
              //if FontStyleChk.Checked then
                // if cmbStylesFind.Text <> GRichViewEdit.Style.TextStyles[k].GetDisplayName  then
                  //  begin
                  //  Inc(i);
                 // continue;
                // end;
              //Font
              if FontChk.Checked then
                 if cmbFontFind.Text = GRichViewEdit.Style.TextStyles[k].FontName  then
                   begin
                //    Result := True;
                 end else begin
                     if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                     continue;
                 end;
              //Font Size
              if FontSizeChk.Checked then
                 if StrToInt(cmbFontSizeFind.Text) = GRichViewEdit.Style.TextStyles[k].Size then
                    begin
                //    Result := True;
                   end else begin
                     if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                     continue;
                 end;
              //Bold
              if BoldChkFind.ImageIndex <> 99 then
                if BoldChkFind.Down then
                 begin
                 if fsBold in GRichViewEdit.Style.TextStyles[k].Style then
                   begin
                 //   Result := True;
                   end else begin
                     if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                     continue;
                 end;
                end else if fsBold in GRichViewEdit.Style.TextStyles[k].Style then
                     begin
                     if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                     continue;
                   end else begin
                 //    Result := True;
                   end;
              //Italic
              if ItalicChkFind.ImageIndex <> 99 then
                if ItalicChkFind.Down then
                 begin
                 if fsItalic in GRichViewEdit.Style.TextStyles[k].Style then
                    begin
                  //  Result := True;
                 end else begin
                   if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                  end;
                end else if fsItalic in GRichViewEdit.Style.TextStyles[k].Style then
                    begin
                    if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                    continue;
                 end else begin
                  //  Result := True;
                  end;
              //Underline
              if UnderlineChkFind.ImageIndex <> 99 then
                if UnderlineChkFind.Down then
                 begin
                 if fsUnderline in GRichViewEdit.Style.TextStyles[k].Style then
                    begin
                  //  Result := True;
                 end else begin
                   if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                  end;
                end else if fsUnderline in GRichViewEdit.Style.TextStyles[k].Style then
                    begin
                    if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                 end else begin
                //    Result := True;
                  end;
              //StrikeOutChkFind
              if StrikeOutChkFind.ImageIndex <> 99 then
                if StrikeOutChkFind.Down then
                 begin
                 if fsStrikeOut in GRichViewEdit.Style.TextStyles[k].Style then
                     begin
                  //   Result := True;
                  end else begin
                     if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                     continue;
                  end;
                end else if fsStrikeOut in GRichViewEdit.Style.TextStyles[k].Style then
                     begin
                     if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                     continue;
                 end else begin
                  //   Result := True;
                  end;
              //OverlineChkFind
              if OverlineChkFind.ImageIndex <> 99 then
                if OverlineChkFind.Down then
                 begin
                 if rvfsOverline in GRichViewEdit.Style.TextStyles[k].StyleEx then
                    begin
                  //  Result := True;
                 end else begin
                   if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                  end;
                end else if rvfsOverline in GRichViewEdit.Style.TextStyles[k].StyleEx then
                    begin
                    if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                    continue;
                 end else begin
                  // Result := True;
                  end;
              //HyperChkFind
               if HyperChkFind.ImageIndex <> 99 then
                if HyperChkFind.Down then
                 begin
                 if GRichViewEdit.Style.TextStyles[k].Jump = True then
                    begin
                  //  Result := True;
                 end else begin
                   if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                  end;
                end else if GRichViewEdit.Style.TextStyles[k].Jump = False then
                    begin
                    if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                    continue;
                 end else begin
                  //  Result := True;
                  end;
              //SubChkFind
              if SubChkFind.ImageIndex <> 99 then
               if SubChkFind.Down then
                 if rvsssSubscript = GRichViewEdit.Style.TextStyles[k].SubSuperScriptType then
                    begin
                   // Result := True;
                 end else begin
                   if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                  end;
              //SupChkFind
              if SupChkFind.ImageIndex <> 99 then
              if SupChkFind.Down then
                 if rvsssSuperScript = GRichViewEdit.Style.TextStyles[k].SubSuperScriptType then
                    begin
                  //  Result := True;
                 end else begin
                   if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                  end;
              //FontColorChkFind
              if FontColorChkFind.ImageIndex <> 99 then
              if FontColorChkFind.Down then
                 if GRichViewEdit.Style.TextStyles[k].Color = PFindFontColor then
                    begin
                   // Result := True;
                 end else begin
                   if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                  end;
              //FontColorBkChkFind
              if FontColorBkChkFind.ImageIndex <> 99 then
              if FontColorBkChkFind.Down then
                 if GRichViewEdit.Style.TextStyles[k].BackColor = PFindFontColorBk then
                    begin
                    //Result := True;
                 end else begin
                   if GrpBoolStart = True then GrpBoolEnd := True; //Will cause the whole loop to exit.
                   continue;
                  end;

             //Because passed all the format tests
             if siGrp = -1 then
                begin
                siGrp := i;
                eiGrp := i;
                GrpBoolStart := True;
             end else begin
                eiGrp := i;
             end;
             Result := True;
           // Go to next word to see if more.
       end; //End check for formatting
       if (siGrp <> -1) AND (RegThenFmtChk.Checked = False) then
          begin
          if (GAgainBool = True) AND (GTestAgainBool = True) then
              begin
              siGrp := siGrp + 1;
              GAgainBool := False;
              GTestAgainBool := False;
          end;
          if GAgainBool = True then GTestAgainBool := True;
          //Send endGrp Integer and Offs to a Global variable here for testing inside the regex function.
          GeiFmtGrp :=  eiGrp;
          GeiFmtGrpOffsAfter := GRichViewEdit.GetOffsAfterItem(eiGrp);
          if siGrp < GRichViewEdit.ItemCount then
            GRichViewEdit.SetSelectionBounds(siGrp, GRichViewEdit.GetOffsBeforeItem(siGrp), GeiFmtGrp, GeiFmtGrpOffsAfter)
          else GSearchBoolDone := True;
       end;
       if FindShowChk.Checked then GRichViewEdit.Refresh;
       //GAgainBool := False;
end;    
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Search through characters looking for a format match

Post by Sergey Tkachenko »

This code looks too complicated to analyze it on the forum, sorry.

I can only give some hints.
Let you have RichViewEdit1 and want to check its selection.

First, get the top level editor:

Code: Select all

rve := RichViewEdit1.TopLevelEditor;
It may be RichViewEdit1 itself or a cell editor.

Next, get the selection:

Code: Select all

rve.GetSelectionBounds(ItemNo1, Offs1, ItemNo2, Offs2, True);
You can check if the selection is empty:

Code: Select all

if (ItemNo1 < 0) or ((ItemNo1 = ItemNo2) and (Offs1 = Offs2)) then
  exit;
Then you can check outermost items.
There is a possibility the ItemNo1 is not included in the selection:

Code: Select all

if Offs1 = rve.GetOffsAfterItem(ItemNo1) then
begin
  inc(ItemNo1);
  Offs1 := rve.GetOffsBeforeItem(ItemNo1);
end;
The same for ItemNo2:

Code: Select all

if Offs2 = rve.GetOffsBeforeItem(ItemNo2) then
begin
  dec(ItemNo2);
  Offs2 := rve.GetOffsAfterItem(ItemNo2);
end;
In the code above (for adjusting ItemNo1 and ItemNo2) I do not check the cases if ItemNo1 was the last item, or ItemNo2 was the first item, because we already checked that the selection is not empty.

Now, you can cycle from ItemNo1 to ItemNo2 and check items inside this range.

Code: Select all

for i := ItemNo1 to ItemNo2 do
The further selection analysis depends on what you want to implement.
You can check for item type:

Code: Select all

StyleNo := rve.GetItemStyle(i);
If StyleNo >= 0, this is a text item, and you can get its text using rve.GetItemText(i).
If StyleNo = rvsTab, this is a tab character (they are handled specially, text items never contain tab characters inside).
Other possible values of StyleNo are described here: https://www.trichview.com/help/idh_const_rvsxxx.html
Line break characters are also never included in text items. Instead, you can check rve.IsParaStart(i) and/or rve.IsFromNewLine(i).
rve.IsParaStart(i) returns True if the i-th item starts a paragraph.
rve.IsFromNewLine(i) returns True if the i-th item starts a paragraph or a line inside a paragraphs (line breaks inside paragraphs can be added with Shift+Enter).
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Search through characters looking for a format match

Post by jgkoehn »

Greetings Sergey,
Thank you for the help. I'm cycling through the text ItemsNo. However, I need to go character by character and test if it is the right style is there a way to do this? (Is each character an ItemNo or is it each line? or each word?) or is each item each new style?
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Search through characters looking for a format match

Post by Sergey Tkachenko »

Each characters in the same item have the same style.
For the ItemNo-th item in rve, if rve.GetItemStyle(ItemNo) >= 0 (i.e. if this is a text item), for all text of this item (rve.GetItemText(ItemNo)), text attributes are defined in rve.Style.TextStyles[rve.GetItemStyle(ItemNo)].
So it is not necessary to enumerate text character by character.
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Search through characters looking for a format match

Post by jgkoehn »

Excellent that helps. So I can visually understand

The Word

Code: Select all

[i]The[/i][b] Wo[/b]rd 
"The" would be one item.
"spaceWo" another item
"rd" another item?
Sergey Tkachenko
Site Admin
Posts: 17555
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Search through characters looking for a format match

Post by Sergey Tkachenko »

Yes.
You can use the code from https://www.trichview.com/forums/viewto ... 717#p34717 to view document structure as a tree.
It adds nodes-paragraphs, and nodes-items inside them.
Actually, there are no such objects as paragraphs in TRichView documents. Just some items have a flag "the item starts paragraph". Nodes-paragraphs are added for convenience.
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Search through characters looking for a format match

Post by jgkoehn »

Excellent thank you sir, very helpful
Post Reply