[SOLVED] macOS: TMemo.Lines vs TMemo.Text and PosEx() lazarus / 68-Other OS ---------------------------------------------------------------------- trev · 2019-07-10 12:36 In the never-ending saga that is my application, I have discovered that my text search fails (ie using PosEx fails to correctly locate the search characters in the TMemo) if I assign lines read from a file to a TMemo using TMemo.Lines := strList rather than TMemo.Text := strList.Text. It appears to me to be related to the number of lines and therefore likely the LineEndings are causing the issue. macOS 10.14.5, Lazarus v2.10 (trunk), FPC 3.0.4 or FPC 3.3.1 (trunk). Curiously it works fine under: o  Ubuntu 18.04 64 bit with Lazarus v1.8.2; FPC v3.0.4; o  FreeBSD 12.0 64 bit with Lazarus v2.00;  FPC v3.0.4; and o  Windows 10 64 bit cross-compiled under macOS for 32 bit using either method. Easy enough to work around now that I figured out what is going on, but... I doubt it should be happening. ---------------------------------------------------------------------- skalogryz · 2019-07-10 13:15 Quote from: trev on July 10, 2019, 02:36:44 pmIn the never-ending saga that is my application, I have discovered that my text search fails (ie using PosEx fails to correctly locate the search characters in the TMemo) if I assign lines read from a file to a TMemo using TMemo.Lines := strList rather than TMemo.Text := strList.Text. It appears to me to be related to the number of lines and therefore likely the LineEndings are causing the issue. where do you search at Memo.Text or Memo.Lines.Text? (something else?) ---------------------------------------------------------------------- marcov · 2019-07-10 14:24 Did you use posex(substr,wholestr,value) and not  (wholestr,substr). Show more code. ---------------------------------------------------------------------- lucamar · 2019-07-10 15:40 Note also that for memos it's best to use UTF8Pos() and UTF8RPos(). Pos(), PosEx(), RPos(), etc. tend to fail for anything other than single-byte character strings. Another thing to take into account: The string functions return a 1-based position but SelStart, etc. are 0-based. And that's not counting the problems with UTF8-BOM, ZWJs, etc. ---------------------------------------------------------------------- trev · 2019-07-11 06:33 Quote from: skalogryz on July 10, 2019, 03:15:27 pmQuote from: trev on July 10, 2019, 02:36:44 pmIn the never-ending saga that is my application, I have discovered that my text search fails (ie using PosEx fails to correctly locate the search characters in the TMemo) if I assign lines read from a file to a TMemo using TMemo.Lines := strList rather than TMemo.Text := strList.Text. It appears to me to be related to the number of lines and therefore likely the LineEndings are causing the issue. where do you search at Memo.Text or Memo.Lines.Text? (something else?) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   // we have a match...  else    begin      // select characters to highlight      Memo.SelStart := PosEx(UpperCase(Edit.Text), UpperCase(Memo.Text), searchOFS) - 1;      Memo.SelLength := Length(Edit.Text);      searchOFS := Memo.SelStart + 1;    end; ---------------------------------------------------------------------- trev · 2019-07-11 06:34 Quote from: marcov on July 10, 2019, 04:24:54 pmDid you use posex(substr,wholestr,value) and not  (wholestr,substr). Show more code. Yes, see above. ---------------------------------------------------------------------- trev · 2019-07-11 06:38 Quote from: lucamar on July 10, 2019, 05:40:40 pmNote also that for memos it's best to use UTF8Pos() and UTF8RPos(). Pos(), PosEx(), RPos(), etc. tend to fail for anything other than single-byte character strings. The files contain PIC microcontroller config word settings, registers, interrupts etc and are definitely always going to be single byte characters... yeah, I know, famous last words QuoteAnother thing to take into account: The string functions return a 1-based position but SelStart, etc. are 0-based. Aware and accounted for. ---------------------------------------------------------------------- lucamar · 2019-07-11 12:25 Try using: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Memo.Lines.AddStrings(StringList, True);or even Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Memo.Lines.Assign(StringList); Any of those should work right everywhere. Also, I'm assuming (because your "we have a match") that you test that PosEx > 0 somewhere? If not your search should be more lke: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   // we have a match...  else    begin      searchOFS := PosEx(UpperCase(Edit.Text), UpperCase(Memo.Text), searchOFS);      if searchOFS > 0 then begin        Memo.SelStart := searchOFS - 1;      Memo.SelLength := Length(Edit.Text);      end else        ShowMessage('Not found');    end; ---------------------------------------------------------------------- skalogryz · 2019-07-11 13:26 Quote from: trev on July 11, 2019, 08:33:24 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i       Memo.SelStart := PosEx(UpperCase(Edit.Text), UpperCase(Memo.Text), searchOFS) - 1;try r61567 please ---------------------------------------------------------------------- trev · 2019-07-12 01:11 Quote from: lucamar on July 11, 2019, 02:25:18 pmTry using: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Memo.Lines.AddStrings(StringList, True); The assignment with the above takes approx 10s vs 1ms for: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Memo.Text := strList.Text; Quoteor even Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Memo.Lines.Assign(StringList); Any of those should work right everywhere. Only at the cost of a huge performance hit (28s): see https://forum.lazarus.freepascal.org/index.php/topic,45733.0.html QuoteAlso, I'm assuming (because your "we have a match") that you test that PosEx > 0 somewhere? If not your search should be more like: You assumed right. ---------------------------------------------------------------------- trev · 2019-07-12 01:12 Quote from: skalogryz on July 11, 2019, 03:26:16 pmtry r61567 please Thanks Dmitry - yes, that fixed the text location issue. ---------------------------------------------------------------------- skalogryz · 2019-07-12 02:37 Quote from: trev on July 12, 2019, 03:12:36 amThanks Dmitry - yes, that fixed the text location issue. Keep that in mind: https://wiki.lazarus.freepascal.org/Cocoa_Internals /Text_Controls#Forcing_Lines_Breaks (in case you need to load/save files across systems)