And also, shouldn't Memo1.SelLength = utf8length(Memo1.SelText)? Obviously the code displays different values.
Detail:
string: Length=4, Bytes=$F09D9B81
UnicodeString: Length=2, Bytes=$35D8C1DE
CodePoint: UTF8Length=1, Bytes=$C1D601
The system (my OS is Windows) uses UnicodeChar (2 byte characters). Because UnicodeLength = 2, then Ctrl + A will select two unicode characters (one codepont).
Lazarus Memo1.SelectAll does not use the system message (EM_SETSEL, 0, -1), but explicitly calls SetSelLength(UTF8Length(Text)), which select only the first unicode character (half of the codepoint).