Recent

Author Topic: Length of text in a RichMemo  (Read 4244 times)

simsee

  • Full Member
  • ***
  • Posts: 184
Length of text in a RichMemo
« on: October 19, 2022, 04:40:58 pm »
Consider the following code. A TStringList is created and a content is assigned to it

 
Code: Pascal  [Select][+][-]
  1. Code.Text: = '123456';

The same content is then assigned to a TRichMemo

Code: Pascal  [Select][+][-]
  1. RichMemo1.Lines.Text: = Code.Text;

Why

Code: Pascal  [Select][+][-]
  1. ShowMessage (Length (Code.Text) .ToString + ':' + Length (RichMemo1.Lines.Text) .ToString);

shows two different values (8 and 7)?

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, RichMemo;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     RichMemo1: TRichMemo;
  16.     procedure FormCreate(Sender: TObject);
  17.     procedure FormDestroy(Sender: TObject);
  18.     procedure RichMemo1Click(Sender: TObject);
  19.   private
  20.     Code : TStringList;
  21.   public
  22.  
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. procedure TForm1.FormCreate(Sender: TObject);
  35. begin
  36.   Code:=TStringList.Create;
  37.   Code.Text:='123456';
  38.   RichMemo1.Lines.Text:=Code.Text;
  39. end;
  40.  
  41. procedure TForm1.FormDestroy(Sender: TObject);
  42. begin
  43.   Code.Free;
  44. end;
  45.  
  46. procedure TForm1.RichMemo1Click(Sender: TObject);
  47. begin
  48.   ShowMessage(Length(Code.Text).ToString+':'+Length(RichMemo1.Lines.Text).ToString);
  49. end;
  50.  
  51. end.

Thanks.

KodeZwerg

  • Hero Member
  • *****
  • Posts: 2007
  • Fifty shades of code.
    • Delphi & FreePascal
Re: Length of text in a RichMemo
« Reply #1 on: October 19, 2022, 04:52:00 pm »
I have not tested but does that also happen when you do the same but limit it for the current string?
".text" gives back everyting inside object, stringlists use #00 at end of each element AFAIK, richtext can contain invisible data like settings.
« Last Edit: Tomorrow at 31:76:97 xm by KodeZwerg »

simsee

  • Full Member
  • ***
  • Posts: 184
Re: Length of text in a RichMemo
« Reply #2 on: October 19, 2022, 05:18:52 pm »
Under Windows, It seems that TStringList uses CR+LF as a line terminator, while TRichMemo only uses CR.

I'm not sure if this behavior is correct. Let's say I didn't expect it.

dsiders

  • Hero Member
  • *****
  • Posts: 1052
Re: Length of text in a RichMemo
« Reply #3 on: October 19, 2022, 07:37:02 pm »
Under Windows, It seems that TStringList uses CR+LF as a line terminator, while TRichMemo only uses CR.

I'm not sure if this behavior is correct. Let's say I didn't expect it.

It uses the native EOL sequence for the platform or OS. You can use the LineBreak property to change it if desired..
Preview Lazarus 3.99 documentation at: https://dsiders.gitlab.io/lazdocsnext

simsee

  • Full Member
  • ***
  • Posts: 184
Re: Length of text in a RichMemo
« Reply #4 on: October 19, 2022, 08:08:50 pm »
Under Windows TRichMemo.Lines.Text uses CR as EOL. It not use CR+LF as it should be.

dsiders

  • Hero Member
  • *****
  • Posts: 1052
Re: Length of text in a RichMemo
« Reply #5 on: October 19, 2022, 08:12:12 pm »
Under Windows TRichMemo.Lines.Text uses CR as EOL. It not use CR+LF as it should be.

TRichMemo is not maintained by the Lazarus folks. File a bug report with that project if you feel it is wrong.

I was speakinkg of TStringList,
Preview Lazarus 3.99 documentation at: https://dsiders.gitlab.io/lazdocsnext

vladimirr

  • New Member
  • *
  • Posts: 29
Re: Length of text in a RichMemo
« Reply #6 on: October 24, 2022, 08:20:30 am »
procedure TForm1.RichMemo1Click(Sender: TObject);
begin
  ShowMessage(Length(Code[0]).ToString+':'+Length(RichMemo1.Lines[0]).ToString);
end;

Shows 6:6

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Length of text in a RichMemo
« Reply #7 on: October 24, 2022, 08:30:51 am »
procedure TForm1.RichMemo1Click(Sender: TObject);
begin
  ShowMessage(Length(Code[0]).ToString+':'+Length(RichMemo1.Lines[0]).ToString);
end;

Shows 6:6
Yes, but this is about when there are line breaks.
Set one extra linebreak in TRichMemo manually and it shows 7 while a linebreak should be two characters and thus show 8.

Same goes for if you add more returns.

Somehow the conversion from rtf to .Text property only uses one character linebreak.

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Length of text in a RichMemo
« Reply #8 on: October 24, 2022, 09:58:03 am »
I am not sure if its deliberate or not but I suggest using a single character for a line break on ALL platforms is quite possibly a very good thing.

I use KMemo for similar functionality and you often want to find some text element without any markup, maybe a word while spell checking for example, you grab the richmemo1.text property and count the number of characters from the start, the number you get is the char index into the richmemo.

But to use that index into your richmemo in Windows, you have to count the number of two character newlines in the text and subtract one for each. Having a uniform one character (probably #10) makes it easier and faster.

So, maybe don't report it as a bug ?  There will be code out there relying on the existing behavior ....

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Length of text in a RichMemo
« Reply #9 on: October 24, 2022, 10:03:47 am »
I am not sure if its deliberate or not but I suggest using a single character for a line break on ALL platforms is quite possibly a very good thing.
So the #13#10 in a TStringList should also be changed to one character???
(Then you should add a bug report for that, which I imagine will never be implemented.)

TRichMemo.Lines is a TStringList and should behave accordingly.
If you want TRichMemo.Text (different from TRichMemo.Lines.Text) to behave differently that's no problem.
But TRichMemo.Lines and TRichMemo.Lines.Text should be the same as TStringList.

Also note that the TRichEdit on Delphi always uses #13#10 (which is standard for both TRichEdit and TStringList).

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Length of text in a RichMemo
« Reply #10 on: October 24, 2022, 10:35:22 am »
It's arguable whether any class which has a .Text property should permit EOL sequences in the stored text. However it's difficult to know how far this should be taken: exclude the current EOL sequence, exclude all non-printables or what?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Length of text in a RichMemo
« Reply #11 on: October 24, 2022, 10:47:19 am »
It's arguable whether any class which has a .Text property should permit EOL sequences in the stored text. However it's difficult to know how far this should be taken: exclude the current EOL sequence, exclude all non-printables or what?
It's also debatable if EOL is a printable sequence. It does instruct the print-head to move  :D
That said... it's also debatable if all other characters are printable, in any selected font (because it depends on the chosen font). For example char(#1) could be printable in some strange font.

Does the EOL in TStringList in a Linux environment contain 1 or two character?

TRichMemo should follow TStringList, so two character EOL on Windows but could be 1 on Linux.

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Length of text in a RichMemo
« Reply #12 on: October 24, 2022, 11:03:05 am »
EOL isn't printable, it's the break between lines. When multiple lines are expressed as a single string it may contain positioning characters inserted due to the presence of EOL.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

dbannon

  • Hero Member
  • *****
  • Posts: 2786
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Length of text in a RichMemo
« Reply #13 on: October 25, 2022, 12:49:35 am »
[So the #13#10 in a TStringList should also be changed to one character???
(Then you should add a bug report for that, which I imagine will never be implemented.)
No, of course not. And I am quite sure you are not seriously suggestion I think it should.

Quote
TRichMemo.Lines is a TStringList and should behave accordingly.
If you want TRichMemo.Text (different from TRichMemo.Lines.Text) to behave differently that's no problem.
But TRichMemo.Lines and TRichMemo.Lines.Text should be the same as TStringList.
Also note that the TRichEdit on Delphi always uses #13#10 (which is standard for both TRichEdit and TStringList).
I have no idea how Lines is implemented in RichMemo, I don't use it. My comment was addressing the effect of how it works. Apparently its already different from a standard implementation of TStringList, if thats the case, as reported, I suggest there might be a good reason for it.

As for Delphi, Delphi was, and effectively still is a Windows application. The issue, if you want to delve back, is that Windows, and DOS before that uses a two character line ending. And no, before you ask, I am not planning to put in a bug report about that either.

Gee !

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

rvk

  • Hero Member
  • *****
  • Posts: 6110
Re: Length of text in a RichMemo
« Reply #14 on: October 25, 2022, 06:30:21 pm »
I have looked into this problem and found the cause.
Although the TRichMemo.Lines is a TStrings it gets its .Text property from another class.
It uses TRichEditManager.GetTextW() to retrieve the complete .Text.

There a EM_GETTEXTEX is issued to get the text from the RichEdit (Windows) component.
There is a flag setting possible for getting the text with #13#10 instead of the default #13 (GTL_USECRLF).
But it isn't used (and that's the reason .Text has #13 instead of #13#10).

I find this very confusing and is definitely not like it is in the TRichEdit in Delphi.

If TStringList has only #13 on Linux systems (I don't know) then this could also be for TRichMemo.Lines.
But the TRichMemo.Lines should give #13#10 on Windows systems (and be the same as TStringList and Delphi).

As a test I edited TRichEditManager.GetTextW to include GTL_USECRLF (and that works) but I see that it must be implemented in a lot of other places in win32richmemoproc.pas too (everywhere where the TGETTEXTEX.flag is used).

I not sure why TRichMemo.Text doesn't just use TStrings.GetTextStr like Delphi does.

 

TinyPortal © 2005-2018