Therefore, I'd speculate that TMemo implicitly converts a string to UTF8.
Don't speculate, look at the sources.
By default LCL treats all strings as having a UTF8 encoding.
It does not check this.
It's how it was designed (before cp aware strings).
If you supply strings to the LCL that are nor UTF8 you'll have te encode them to UTF8 first.
This is why we have SysToUtf8 (and other conversion routines).
When reading text from a file (LoadFromFile), the LCL does not know what encoding is used.
It's your responsibiity to make sure it'll be handled correctly.
You can happily do a TStrings.LoadFromFile on a binary file.
The contents will make no sense of course, but still you can.
When dealing with the OS/WidgetSet (e.g. when putting the text in a Memo and showing it on a from) the LCL will offer strings to the Windows API as WideStrings.
It therefore explicitely converts the strings (which, as I pointed out earlier, are treated as UTF8) to WideString using Utf8ToUTF16 or Utf8Decode.
And this will give unexpected results if the strings you provide (read from the file) are not UTF8.
In the sources of TMemo, I see that its Lines are type TTextStrings which use a TFileStreamUtf8 for reading and writing - but I thought that the "utf8" in this stream name refers to the file name only, not to the contents.
That is correct.
Could somebody please explain?
Hope I did.
Bart