Lazarus

Programming => LCL => Topic started by: madref on March 24, 2019, 11:21:32 pm

Title: [SOLVED] TMemo & Line Index
Post by: madref on March 24, 2019, 11:21:32 pm
I am doing a search in a Tmemo with the following code
Code: Pascal  [Select][+][-]
  1. function TForm_Test.FindInMemo(AMemo: TMemo; AString: String; StartPos: Integer): Integer;
  2. begin
  3.   Result := PosEx(AString, AMemo.Text, StartPos);
  4.   if Result > 0 then begin
  5.     AMemo.SelStart := UTF8Length(PChar(AMemo.Text), Result - 1);
  6.     AMemo.SelLength := Length(AString);
  7.     AMemo.SetFocus;
  8.   end;  // if
  9. end;     // FindInMemo
This gives me a number which is from the start of the Tmemo.


But how can I determine the linenumber from this?
I found this but this is for Delphi and not Lazarus.
Code: Pascal  [Select][+][-]
  1. mi := Memo_Test.Perform(EM_LINEFROMCHAR, i, 0);
Title: Re: TMemo & Line Index
Post by: lucamar on March 25, 2019, 12:27:37 am
Only way I know of is to read CaretPos after you set SelStart but before setting SelLength.

It may or may not work for all platforms: In GTK, for example, setting selections sometimes works ... "funny". :)
Title: Re: TMemo & Line Index
Post by: engkin on March 25, 2019, 01:14:03 am
I am doing a search in a Tmemo with the following code
Code: Pascal  [Select][+][-]
  1. function TForm_Test.FindInMemo(AMemo: TMemo; AString: String; StartPos: Integer): Integer;
  2. begin
  3.   Result := PosEx(AString, AMemo.Text, StartPos);
  4.   if Result > 0 then begin
  5.     AMemo.SelStart := UTF8Length(PChar(AMemo.Text), Result - 1);
  6.     AMemo.SelLength := Length(AString);
  7.     AMemo.SetFocus;
  8.   end;  // if
  9. end;     // FindInMemo
This gives me a number which is from the start of the Tmemo.
FindInMemo has a little bug:
Code: Pascal  [Select][+][-]
  1.     AMemo.SelLength := UTF8Length(AString);

But how can I determine the linenumber from this?
I found this but this is for Delphi and not Lazarus.
Code: Pascal  [Select][+][-]
  1. mi := Memo_Test.Perform(EM_LINEFROMCHAR, i, 0);
For Windows, use SendMessage:
Code: Pascal  [Select][+][-]
  1.   mi := SendMessage(Memo_Test.Handle, EM_LINEFROMCHAR, i, 0);
i has to be for UTF16, but if you pass -1 instead of i, you get the line that has the caret/selection, without caring about UTF16.
Title: Re: TMemo & Line Index
Post by: madref on March 25, 2019, 05:21:42 am
But unfortunately I don't have a windows version.
I am using a Mac on OSx Mojave


Therefor EM_LINEFROMCHAR is not defined anywhere
Title: Re: TMemo & Line Index
Post by: sstvmaster on March 25, 2019, 10:15:30 am
Something like that?

Code: Pascal  [Select][+][-]
  1. function TForm_Test.FindInMemo(AMemo: TMemo; AString: String; StartPos: Integer): Integer;
  2. var
  3.   vPos: integer;
  4. begin
  5.   AMemo.HideSelection := false; // no focus needed to show selected
  6.   vPos := PosEx(AString, AMemo.Text, StartPos);
  7.   if vPos > 0 then begin
  8.     AMemo.SelStart := UTF8Length(PChar(AMemo.Text), vPos - 1);
  9.     AMemo.SelLength := UTF8Length(AString);
  10.     Result := AMemo.CaretPos.Y; // !!! It starts from 0 (zero) !!!
  11.   end;
  12. end;

Greetings Maik
Title: Re: TMemo & Line Index
Post by: howardpc on March 25, 2019, 10:59:05 am
I think better would be
Code: Pascal  [Select][+][-]
  1. function FindMemoLineNumber(AMemo: TMemo; const AString: String; StartPos: Integer): Integer;
  2. begin
  3.   AMemo.HideSelection := False;
  4.   Result := PosEx(AString, AMemo.Text, StartPos);
  5.   case Result of
  6.     0: Exit(-1);
  7.     else
  8.       begin
  9.         AMemo.SelStart := UTF8Length(PChar(AMemo.Text), Pred(Result));
  10.         AMemo.SelLength := UTF8Length(AString);
  11.         Result := Succ(AMemo.CaretPos.Y); // indexed from 1
  12.       end;
  13.     end;
  14. end;
Note that this is dependent on the setting of AMemo.WordWrap. WordWrap should be False for reliable results.
Title: Re: TMemo & Line Index
Post by: madref on March 25, 2019, 10:45:50 pm
Thanks everyone.... it works
TinyPortal © 2005-2018