Speeding up

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

Speeding up

Post by jgkoehn »

I use this function many many times in building resources.
Basically it runs down through TRichViewEdit looking for markers like <:> and </:>, <link> and </link> etc then information is pulled out and brought into another TRichViewEdit. Ideas on how to speed this up since it is very core to the whole operation?
I am already using

Code: Select all

  RVAControlPanel1.ActionsEnabled := False;
  rvActionStyleInspector1.Control := nil;
  cmbFont.Editor := nil;
  cmbFontSize.Editor := nil;
  cmbStyles.Editor := nil;
    for i := 0 to ActionList1.ActionCount - 1 do
      ActionList1.Actions[i].Update;
      RichViewEdit.BeginUpdate;


Code: Select all

function TConvertBook.FindSelIndic(indic:String; rve: TRichViewEdit;
                    var startNo, startOffs,//Not always used but sometimes so keep
                        endNo, endOffs,  //Use var because we don't change unless we have to
                        endendNo, endendOffs: Integer;
                        toplink_i: Integer = 0; topid: Integer = 5 {<:>}): Boolean;
var
 endstartNo, endstartOffs: Integer;
 TopBool: Boolean;
begin
     rve.TopLevelEditor.GetSelectionBounds(startNo, startOffs, endNo, endOffs, TRUE);

      Result := rve.SearchTextW(indic, [rvseoMatchCase, rvseoDown, rvseoMultiItem]);

     //If we are testing toplink_i then do this
     TopBool := True;
     if toplink_i = topid {<:>} then
         TopBool := False;

     if Result AND TopBool then
       begin
        //Get the position before and after this here
        rve.TopLevelEditor.GetSelectionBounds(endstartNo, endstartOffs,endendNo, endendOffs, TRUE);
        //Select then Get Content between. //eNo, endOffs, endstartNo, endstartOffs
        rve.TopLevelEditor.SetSelectionBounds(endNo, endOffs, endstartNo, endstartOffs);
      end;
end;
Sergey Tkachenko
Site Admin
Posts: 17566
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Speeding up

Post by Sergey Tkachenko »

I do not see the full code, only the part that selects text, so I do not have enough information to give suggestions.
I do not know how text fragments are copied, and how they are inserted in another editor.

However, as for copying part,.. If you need to get only text between opening and closing substrings, the fastest way is to enumerate all items in the document, getting text string from text items using GetItemText method. In this string, search for necessary substrings (like <link> and </link>) and get a substring between them.
This is how all "text" mail merge demos work, see the topic https://www.trichview.com/forums/viewtopic.php?t=8
These demos get text between '{' and '}' characters. They assume that both opening and closing substrings are in the same text item. This assumptions simplifies code a lot.
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Speeding up

Post by jgkoehn »

This is the code used to get the Text at present.

Code: Select all

WStrText := trim(RichViewEdit.GetSelTextW);
(I wish I could assume it is in the same text item but quite often it will not be)

I can see how going down through text items.

To convert all text items to a string and then run down through the string probably would slow it down?
Because at times I will also need to go from the text Position back to the RVF position and copy the formatting.

In the past you have helped me do this with my Regex Find/Replace though in this case not sure if it would be faster.
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Speeding up

Post by jgkoehn »

I tried but I am having trouble with the startOffs, and endOffs: Are these AnsiString? UTF-16, UTF8 ? Character count?

Code: Select all

function TConvertBook.GetTextFromNosOffs(rve: TRichViewEdit; startNo, startOffs, endNo, endOffs:Integer; CharsPerLineBreak: Integer = 2): String;
var
 ItemNo, OldItemNo: Integer;
 LineBreak, NewLine: String;
begin
   Result := '';
   //Get items text into a string and then adjust with offs
   //Test for in range
   if (startNo < rve.ItemCount) AND (endNo < rve.ItemCount) then begin
      ItemNo := startNo;
      //NewLine
      if CharsPerLineBreak < 0 then
       CharsPerLineBreak := 2;
      case CharsPerLineBreak of
        0: LineBreak := '';
        1: LineBreak := #13;
        else LineBreak := #13#10;
      end;
      NewLine := #10;

      //Get the start paragraph number
      OldItemNo := ItemNo;
      while ItemNo <= endNo do begin
        //Check first
        if (ItemNo <> OldItemNo) then
          //Add a linebreak since we crossed a paragraph
         if  rve.IsParaStart(ItemNo) then
           Result := Result + LineBreak
         //Add a newline since we crossed a newline
         else if rve.IsFromNewLine(ItemNo) then
           Result := Result + NewLine;

        //Add Next Item text
        Result := Result + rve.GetItemText(ItemNo);

        //We are checking if we are on a different item
        OldItemNo := ItemNo;
        Inc(ItemNo);
      end;//end while

      //Trim using Offs
      Delete(Result, 1, startOffs-1);
      Delete(Result, Length(Result)-(endOffs-1), endOffs+1);
   end;
end;
jgkoehn
Posts: 303
Joined: Thu Feb 20, 2020 9:32 pm

Re: Speeding up

Post by jgkoehn »

I see that I needed to do a few things differently

Code: Select all

function TConvertBook.GetTextFromNosOffs(rve: TRichViewEdit; startNo, startOffs, endNo, endOffs:Integer; CharsPerLineBreak: Integer = 2): String;
var
 ItemNo, OldItemNo, hsNo, hsOffs, heNo, heOffs : Integer;
 LineBreak, NewLine, AddText: String;
begin
   Result := '';
   //Get items text into a string and then adjust with offs
   //Test for in range
   if (startNo < rve.ItemCount) AND (endNo < rve.ItemCount) then begin
      //NewLine
      if CharsPerLineBreak < 0 then
       CharsPerLineBreak := 2;
      case CharsPerLineBreak of
        0: LineBreak := '';
        1: LineBreak := #13;
        else LineBreak := #13#10;
      end;
      NewLine := #10;

      hsNo := startNo;
      hsOffs := startOffs;
      heNo := endNo;
      heOffs := endOffs;
      //Make sure order is correct
      if StartNo>endNo then begin
        hsNo := endNo;
        hsOffs := endOffs;
        heNo := startNo;
        heOffs := startOffs;
      end;

      //Get the end ItemNo
      ItemNo := heNo;
      OldItemNo := ItemNo;
      //Build in reverse
      //start----------------end <<
      while ItemNo >= hsNo do begin
        //Check first
        if (ItemNo <> OldItemNo) then
          //Add a linebreak since we crossed a paragraph
         if  rve.IsParaStart(ItemNo) then
           Result := LineBreak + Result
         //Add a newline since we crossed a newline
         else if rve.IsFromNewLine(ItemNo) then
           Result := NewLine + Result;

        AddText := rve.GetItemText(ItemNo);
        //Offs are from the start of the Item to that position

        //Remove end first.
        if ItemNo = heNo then
           Delete(AddText, heOffs, Length(AddText)-(heOffs-1));

        //Remove from start text
        if ItemNo = hsNo then
           Delete(AddText, 1, hsOffs-1);

        //Add Next Item text
        Result := AddText + Result;

        //We are checking if we are on a different item
        OldItemNo := ItemNo;
        Dec(ItemNo);
      end;//end while

      //Trim using Offs
      {<:>Title
      <link>l</link>logo
      <link>λ</link>λογo}
   end;
end;
Sergey Tkachenko
Site Admin
Posts: 17566
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Speeding up

Post by Sergey Tkachenko »

GetItemText returns AnsiString in Delphi 5-2007, UnicodeString (UTF-16) in new versions of Delphi, and UTF-8 string in Lazarus.

You can use GetItemTextW that always returns UnicodeString (UTF-16).
Post Reply