3

I have a TMemo which contains quite a lot of texts, 80M (about 400K lines).

The TMemo is set with WordWrap = FALSE, there is no need to find texts that wrapped in 2 lines.

I need a fast way to find a text, from the beginning, and also find next.

So, I put a TEdit for putting the text to find and a TButton to find the text in the TMemo.

I was thinking to use Pos(), checking line by line, but that will be slow. And I don't know how to determine the TMemo.Lines[index] for current cursor position.

Anyone can come up with solution?

Thanks

UPDATE:

I found a solution from here: Search thru a memo in Delphi?

The SearchText() function works, fast, and very fast. Took couple of seconds to search unique string at the bottom end.

Community
  • 1
  • 1
Kawaii-Hachii
  • 1,017
  • 7
  • 22
  • 36
  • 1
    If you used a rich edit control you could use [`EM_FINDTEXT`](http://msdn.microsoft.com/en-us/library/windows/desktop/bb788009.aspx) which is wrapped in in the [`FindText`](http://docwiki.embarcadero.com/Libraries/en/Vcl.ComCtrls.TCustomRichEdit.FindText) method of `TRichEdit`. – David Heffernan Jan 05 '12 at 10:55
  • 1
    I think using `Pos` function with `TMemo.Lines.Text` property should be faster; though it can possibly find wrapped substring too, I don't think that is a problem. – kludg Jan 05 '12 at 11:01
  • 2
    Similar question on SO : [search-thru-a-memo-in-delphi](http://stackoverflow.com/questions/4232709/search-thru-a-memo-in-delphi). I don't know if it's fast, but the answer has a solution for the index position. – LU RD Jan 05 '12 at 11:39
  • @Serg: You are right. I found a function from here: http://stackoverflow.com/questions/4232709/search-thru-a-memo-in-delphi – Kawaii-Hachii Jan 05 '12 at 11:50
  • Tested the above SearchText() and it was fast, very fast! – Kawaii-Hachii Jan 05 '12 at 11:50

1 Answers1

7

A little addition to the previous answers: you can get the line number without selecting the pattern found, like this:

procedure TForm1.Button3Click(Sender: TObject);
var
  I, L: Integer;

begin
  Memo1.WordWrap:= False;
  Memo1.Lines.LoadFromFile('Windows.pas');
  I:= Pos('finalization', Memo1.Text);
  if I > 0 then begin
    L := SendMessage(Memo1.Handle, EM_LINEFROMCHAR, I - 1, 0);
    ShowMessage('Found at line ' + IntToStr(L));
// if you need to select the text found:
    Memo1.SelStart := I - 1;
    Memo1.SelLength := Length('finalization');
    Memo1.SetFocus;
  end;
end;

Note that line number is zero-based, also you should subtract 1 from Pos result to obtain zero-based offset for SendMessage and TMemo.SelStart.

Community
  • 1
  • 1
kludg
  • 27,213
  • 5
  • 67
  • 118