Author Topic: Microexamples  (Read 7476 times)


  • Jr. Member
  • **
  • Posts: 78
Re: Microexamples
« Reply #15 on: June 16, 2021, 12:40:12 pm »
So, on to the memos, TMemo and TRichMemo. As TRichMemo was designed to mimic TMemo (AND VERY NEARLY DOES BUT SEE WARNING BELOW) we can just talk about TMemo for now and it'll carry over.

The data in a TMemo can be accessed in two ways:

(1) The Lines stringlist. This contains the lines as they appear on the screen. It will change when the TMemo is resized, or when word wrap is turned on and off.

(2) The Text field in which the data is all one big string in which the paragraphs (not the Lines, but the paragraphs of text) are separated by a carriage return character and a line feed character (#13 and #10).

These characters do not appear in the Lines, and so do not affect the length of a Line that they terminate.

So, the TMemo has two ways to address the cursor position.

(1) There is CaretPos, of type TPoint (that is, having two fields, CaretPos.X and CaretPos.Y).

CaretPos.Y is a (zero-indexed) count of which Line of the TMemo the cursor is in.

And then CaretPos.X measures the distance between the start of the Line and the cursor in the same old UTF16 metric we're familiar with from TEdit (see above).

(2) There is SelStart and SelLength, like in a TEdit, which give the position in the Text. While you can use both CaretPos and SelStart to change the position of the cursor, so far as I know you can only use SelLength to choose the length of a selection, there's no equivalent to CaretPos for that. (If you find one, let me know.) These also use the UTF16 metric.

And these do include the #13 and #10 characters in their count.

IMPORTANT WARNING ABOUT TRichMemo. TRichMemo is usually designed to work the same as TMemo, but there are some infuriating discrepancies and one is that everything above applies except that there is only one character (#13) between paragraphs and not two. All code must be adapted accordingly.

So if we want to convert from one metric to the other, we need to take the paragraph breaks into account. But how do we find the paragraph breaks? If we have word wrap turned off it's easy enough. Each line then corresponds to one paragraph, so we can do this (this is the TMemo version with two characters per paragraph break). You hardly need me to tell you:

Code: Pascal  [Select][+][-]
  1. function xytox(M: TMemo): integer;
  2. var i:integer;
  3. begin
  4. xytox:=0;
  5. for i:=0 to M.CaretPos.Y-1 do
  6.     xytox:=xytox+utf16length(M.Lines[i])+2;
  7. xytox:=xytox+M.CaretPos.X;
  8. end;

But what if we have word wrap turned on? We need to look at the underlying Text. The end of a Line in the memo either does or does have a newline after it in the Text and by measuring off distances in the Text corresponding to those in the Line we can look and see if they're there. (I haven't implemented this because everything I myself need to do has word wrap turned off and if I do do it I don't think I'm going to fit it in tonight but there's no reason why that wouldn't work, is there?)
« Last Edit: June 17, 2021, 09:31:51 am by Spoonhorse »


  • Jr. Member
  • **
  • Posts: 78
Re: Microexamples
« Reply #16 on: June 20, 2021, 09:19:11 am »
Going to post something longer later. Just wanted to register my bafflement, 'cos I just found out ... working with TRichMemo (don't know about TMemo), changing the Text from an empty string to anything else or vice-versa triggers a resize event.


TinyPortal © 2005-2018