Page 1 of 1

Search and Highlight in TRVTableCellData

Posted: Mon Nov 20, 2006 3:45 pm
by mamouri
I want highlights searched words in a RichView cell. I write a function for this purpose and get content of cell using TRVItemFormattedData.
When I want search for a text to highlight it, it raise a List Bound exception.
Here is my code:

Code: Select all

Procedure TfStory.HighLighting(Cell: TRVTableCellData; Words: Array of String);
var
  I: Integer;
  D: TRVItemFormattedData;
Begin
  D := TRVItemFormattedData(Cell.GetRVData);
  for I := Low(Words) to High(Words) do
    while D.SearchText(True, False, True, Words[I]) do
      TRVEditRVData(Cell.Edit).ApplyStyleConversion_(tsHighLight, rvscTextStyle, False);
end;
I'm not sure about ths ApplyStyleConversation_ too. And I'm not sure does entered parameter are correct or not?
How is it possible to Search a cell of table and change selected text style?

Thank you

Posted: Tue Nov 21, 2006 11:58 am
by Sergey Tkachenko
Please use this code instead (assuming that this table is in RichViewEdit1):

Code: Select all

var I: Integer;
  rve: TCustomRichViewEdit;

  Cell.Edit;
  for I := Low(Words) to High(Words) do 
  begin
    with CustomRVFormattedData(Cell.GetRVData) do
      SetSelectionBounds(0, GetOffsBeforeItem(0). 0, GetOffsBeforeItem(0));
    rve := RichViewEdit1.TopLevelEditor;
    while rve.SearchText(Words[I], [rvseoDown, rvseoWholeWord]) do 
      rve.ApplyStyleConversion(tsHighLight); 
  end;

Posted: Tue Nov 21, 2006 12:35 pm
by mamouri
Thank you very much. This work only if RichView is formatted. I have lot's of Cells that are written from database and want to highlight some keywords in every of them each time I insert a new row.

In fact I want to access to TRVFormattedData and highlight my keywords there. so it doesn't need a formatted Cell.

Also is it possible to do such with RichView and not RichViewEdit. I mean accesing directly to RichView cell data and highlight some words on that.
Because RichView is much more faster in rendering text than RichViewEdit.

Thank you

Posted: Tue Nov 21, 2006 12:37 pm
by mamouri
Here is what I currently am doing:

Code: Select all

  //Printing Answer.
  RowNo := FixedTopRow;
  while not DS.Eof do
    with T.Cells[RowNo,1] do begin

      if RowNo mod 2 <> 0 then Color := clCream;
      AddNLWTag(DS.FindField('Text').AsString,tsNormal,-1,-1);

      SetItemExtraStrProperty(0, rvespHint, DS.FindField('QAID').AsString);
      HighLighting(T.Cells[RowNo, 1], [Words]);

      DS.Next;
      RowNo := RowNo + 1;
    end; // with
Words is an array of words that must highlighted.

Posted: Tue Nov 21, 2006 6:52 pm
by Sergey Tkachenko
If document is not formatted, use the following code (the second example in the topic):
http://www.trichview.com/forums/viewtop ... =2485#2485

MarkSubString(Cell, Word)

Note: this code converts strings to ANSI

Posted: Tue Nov 21, 2006 7:21 pm
by mamouri
Does it work if I remove following line of code:

Code: Select all

          if rvioUnicode in item.ItemOptions then
            s3 := RVU_AnsiToUnicode(RVData.GetStyleCodePage(item.StyleNo), s3); 
And convert String variable into WideString?

Is there special reason that you convert unicode to ansi here?

Posted: Tue Nov 21, 2006 7:41 pm
by Sergey Tkachenko
No, it's not enogh.

Give me WideString analog of LastPos function from that demo, and I'll create Unicode version of that procedure :)

Posted: Wed Nov 22, 2006 4:51 am
by mamouri
Hi,
Yeah. I was forgot about that LastPos function :roll: Here is a minimal LastPos function that support widestrings. It use of anothor function named InternalPosW grabbed carefully :D from DIUtils unit of DIHtmlParser
http://www.zeitungsjunge.de/delphi/htmlparser/

Code: Select all

function InternalPosW(Search: PWideChar; lSearch: Cardinal; const Source: PWideChar; LSource: Cardinal; const StartPos: Cardinal): Cardinal;

label
  Zero, One, Two, Three, Match, Fail, Success;
var
  PSource, pSearchTemp, PSourceTemp: PWideChar;
  lSearchTemp: Cardinal;
  c: WideChar;
begin
  if lSearch > LSource then goto Fail;

  Dec(lSearch);
  Dec(LSource, lSearch);
  if LSource <= StartPos then goto Fail;

  Dec(LSource, StartPos);

  PSource := Source;
  Inc(PSource, StartPos);

  c := Search^;
  Inc(Search);

  while LSource > 0 do
    begin

      while LSource >= 4 do
        begin
          if PSource^ = c then goto Zero;
          if PSource[1] = c then goto One;
          if PSource[2] = c then goto Two;
          if PSource[3] = c then goto Three;
          Inc(PSource, 4);
          Dec(LSource, 4);
        end;

      if LSource = 0 then Break;
      if PSource^ = c then goto Zero;
      if LSource = 1 then Break;
      if PSource[1] = c then goto One;
      if LSource = 2 then Break;
      if PSource[2] = c then goto Two;
      Break;

      Three:
      Inc(PSource, 4);
      Dec(LSource, 3);
      goto Match;

      Two:
      Inc(PSource, 3);
      Dec(LSource, 2);
      goto Match;

      One:
      Inc(PSource, 2);
      Dec(LSource, 1);
      goto Match;

      Zero:
      Inc(PSource);

      Match:

      PSourceTemp := PSource;
      pSearchTemp := Search;
      lSearchTemp := lSearch;

      while (lSearchTemp >= 4) and
        (PCardinal(PSourceTemp)^ = PCardinal(pSearchTemp)^) and
        (PCardinal(@PSourceTemp[2])^ = PCardinal(@pSearchTemp[2])^) do
        begin
          Inc(PSourceTemp, 4);
          Inc(pSearchTemp, 4);
          Dec(lSearchTemp, 4);
        end;

      if lSearchTemp = 0 then goto Success;
      if PSourceTemp^ = pSearchTemp^ then
        begin
          if lSearchTemp = 1 then goto Success;
          if PSourceTemp[1] = pSearchTemp[1] then
            begin
              if lSearchTemp = 2 then goto Success;
              if PSourceTemp[2] = pSearchTemp[2] then
                begin
                  if lSearchTemp = 3 then goto Success;
                end;
            end;
        end;

      Dec(LSource);
    end;

  Fail:
  Result := 0;
  Exit;

  Success:
  Result := (Cardinal(PSource) - Cardinal(Source)) shr 1;
end;

function LastPosW(const Substr, Str: PWideChar): Integer;
var
  P: Integer;
begin
  Result := 0;

  P := 1;
  while P > 0 do begin
    P := InternalPosW(SubStr, Length(SubStr), Str, Length(Str), P);
    if P > 0 then
      Result := P;
  end;
end;

Posted: Thu Nov 23, 2006 1:49 pm
by Sergey Tkachenko
What's an overcomplicated function :)

I created functions supporting Unicode both in RichView and as a substring to search.

http://www.trichview.com/forums/viewtop ... =5184#5184

Posted: Thu Nov 23, 2006 5:17 pm
by mamouri
Thank you man. I'm not even a good grabber 8)