Lazarus

Installation => Windows (32/64) => Topic started by: tech-pro on November 10, 2007, 09:57:30 am

Title: Appending text to a TMemo
Post by: tech-pro on November 10, 2007, 09:57:30 am
I am using a TMemo to display text that is received from a serial port. It appears that when I add newly received text, like this:

Memo.Text := Memo.Text + newtext;

a newline gets added to the end of the text, so the cursor is on the next line and every chunk of text received is on a new line.

Any ideas for a solution?
Title: RE: Appending text to a TMemo
Post by: Bart on November 10, 2007, 12:33:56 pm
I don't know how other Delphi versions behave, but D3 Pro (Win9x) does not add the newline as opposed to Lazarus.

If this Lazarus behaviour also differs from newer Delphi versions, it may be considered a bug and reported IMHO.

Bart
Title: RE: Appending text to a TMemo
Post by: antonio on November 10, 2007, 12:38:13 pm
Try
memo1.lines.text := trim(memo1.lines.text) + 'text';
Title: RE: Appending text to a TMemo
Post by: tech-pro on November 10, 2007, 01:14:36 pm
I just checked in Delphi 6 and it does not add the new line.

I tried your suggestion, Antonio, and although it does partially solve the problem (except that it removes any trailing spaces, but that could be fixed) the trouble is that the new line is added when the text is written to the control, so the cursor is positioned on the next line. This is a problem because I want it to be like a real terminal window where you can type text as well as have received text printed up.

The original Delphi code didn't use a TMemo. It derived from TCustomEdit and made it multi-line with word-wrap and a scroll bar. Unfortunately the method used to achieve this - by recreating the window after adding some styles - doesn't seem to work with the LCL and despite much studying of the LCL source code I haven't figured out how to do this.
Title: RE: Appending text to a TMemo
Post by: Vincent Snijders on November 10, 2007, 01:39:55 pm
I think the bug already has been reported.
Title: RE: Appending text to a TMemo
Post by: antonio on November 10, 2007, 03:28:44 pm
Should the application run on Windows only?
Title: Re: RE: Appending text to a TMemo
Post by: Bart on November 10, 2007, 04:06:39 pm
Quote from: "Vincent"
I think the bug already has been reported.

Yeah, it's in bugreport #9653 (http://www.freepascal.org/mantis/view.php?id=9653).

It seems that TStrings.SetTextStr adds a LineEnding after the text becaus it uses TSrings.Add, which uses TSrings.Insert, which in fact adds the LineEnding to the string.

Bart
Title: RE: Re: RE: Appending text to a TMemo
Post by: tech-pro on November 10, 2007, 08:51:23 pm
It's going to run on Windows though I wanted to make as little of it Windows-specific as possible.

I checked Delphi adding the text to TStrings.Text and it appeared to add a line ending, the same as Lazarus. Only the memo does it differently.

I have managed to work around it after a fashion using something similar to Antonio's first suggestion.
Title: RE: Re: RE: Appending text to a TMemo
Post by: Bart on November 11, 2007, 11:57:45 am
You might want to consider using SelText for this purpose? It puts the text at the position of the cursor (which might be a problem if the user changes that).

Bart
Title: RE: Re: RE: Appending text to a TMemo
Post by: tech-pro on November 11, 2007, 02:24:02 pm
Yes, I will try to do something like that. As this has been reported as a bug, it will hopefully eventually be fixed.
Title: RE: Re: RE: Appending text to a TMemo
Post by: tech-pro on November 13, 2007, 03:15:30 pm
Further to this, I've managed to work around the problem so the text can be added a character at a time, but has anyone any suggestions as to how I can avoid flicker when the memo is updated? I've tried disabling it before the update and enabling it afterwards, but that hasn't made any difference.
Title: RE: Re: RE: Appending text to a TMemo
Post by: Bart on November 13, 2007, 06:01:00 pm
TMemo.Lines.Beginupdate / Endupdate?
Make your form doublebuffered?
(I only know how to do that in win32) Call windows to lock the the painting of the form entirely?

Just curious: how do you add one character at a time, without using the text property I assume (since this will add the LineEnding).

Does anyone know how to remove in code the last LineEmding from the memo?

Bart
Title: RE: Re: RE: Appending text to a TMemo
Post by: tech-pro on November 13, 2007, 07:31:37 pm
I'll investigate if those possibilities exist in LCL. Thanks.

At the moment, there's no alternative than to add characters using the Text property. Dealing with the line end is very kludgey. You have to remove CR and LF characters from the end of the string, unless you actually added them yourself and therefore want them.
Title: RE: Re: RE: Appending text to a TMemo
Post by: Leledumbo on November 14, 2007, 05:44:24 am
Quote
Does anyone know how to remove in code the last LineEnding from the memo?

Use Trim;
Code: [Select]
function Trim(const S: widestring): widestring;
Title: RE: Re: RE: Appending text to a TMemo
Post by: tech-pro on November 14, 2007, 11:05:52 am
Unfortunately sometimes you want new lines to appear in the memo text, also Trim will remove spaces (remember, you are adding text character by character.)

You have to store what you added and manually remove line endings only if they were not added by you.
Title: Re: RE: Re: RE: Appending text to a TMemo
Post by: Bart on November 14, 2007, 11:38:36 am
Quote from: "Leledumbo"
Quote
Does anyone know how to remove in code the last LineEnding from the memo?

Use Trim;
Code: [Select]
function Trim(const S: widestring): widestring;

I'm sorry I did not make myself clear.
What I meant was: how do I remove in code the LineEning from the memo that was added by setting the TMemo text property in code (Memo.Text := SomeText). So that it is removed from the memo itself.
If we can do this, then we can modify SetTextStr() to prevent TMemo from adding a LineEnding if we set the textproperty of a TMemo control, thus fixing the bug.

Bart
Title: RE: Re: RE: Re: RE: Appending text to a TMemo
Post by: Marc on November 15, 2007, 11:29:08 am
The last lineend is the result of the used TStrings.text. It contains lines, when the Text is "askes" all lines are concatinated whith a terminating LineEnding
Title: Re: RE: Re: RE: Re: RE: Appending text to a TMemo
Post by: Bart on November 15, 2007, 03:52:55 pm
Quote from: "Marc"
The last lineend is the result of the used TStrings.text. It contains lines, when the Text is "askes" all lines are concatinated whith a terminating LineEnding
Yes, but that is undesired when setting text in a TMemo (and not compatible with Delphi behaviour).

The most logical place to resolve this IMHO is the SetTextStr procedure. This would involve removing the last LineEnding after setting the text.
If that can be done, the bug is fixed.

Bart
Title: RE: Re: RE: Re: RE: Re: RE: Appending text to a TMemo
Post by: tech-pro on November 15, 2007, 07:37:07 pm
You need to be sure that you don't remove the line ending if the string set by the user ended in one. This has been one of the difficulties in producing a workaround.

By the way I still haven't managed to stop the flicker when the memo gets updated. Tried double buffering it, and used BeginUpdateBounds/EndUpdateBounds (admittedly without being able to figure out what they do) to no avail.
Title: Re: RE: Re: RE: Re: RE: Re: RE: Appending text to a TMemo
Post by: Bart on November 15, 2007, 11:18:37 pm
Quote from: "tech-pro"
You need to be sure that you don't remove the line ending if the string set by the user ended in one. This has been one of the difficulties in producing a workaround.

That should not be so hard? If user sets text, we know what text will be, so we know if it ends in LineEnding. If it does not, then we remove last LineEnding after we set text.

It can be done. Delphi does it, so why can't we?

Bart
Title: RE: Re: RE: Re: RE: Re: RE: Re: RE: Appending text to a TMem
Post by: tech-pro on November 16, 2007, 12:44:00 pm
I wasn't suggesting it can't be done, I just wanted to make the point that sometimes a line ending will be the last thing in the text.

A fix for this won't solve the problem of the memo flickering when it is updated. It seems to me that this is happening because it has to be updated in two stages. First the new text is set, and the control displays it starting with the first line. Then I have to set the caret position to the end, so that the last character entered is in view. If the length of the text is greater than can fit in the visible area, it scrolls, and this causes the flickering.

LCL components don't seem to have the BeginUpdate / EndUpdate methods suggested earlier in this thread. There is BeginUpdateBounds and EndUpdateBounds but I don't know what they do, and when I tried them anyway they didn't deem to do anything.