Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2007-11

More help with unicode

5 messages · 2 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

I still have some issues with unicode support =) I am trying to implement unicode support for TMemo, but somehow the solution isn't simple. TMemo will throw a WM_SETTEXT message to when it's text is set, like this:

    SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(TheText));

Which I tryed to convert to:

    if UnicodeEnabledOS then
      SendMessage(fHandle, WM_SETTEXT, 0,

LPARAM(PWideChar(Utf8Decode(TheText))))
else

      SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(PChar(Utf8ToAnsi(TheText))));

But this doesn't seam to work, and the text is shown scrambled.

I would think that the control wasn't create with unicode functions, but this is impossible because handle creating is centralized and all other controls work normally, setting the same text to them.

I already debugged and execution flow does go throught that part.

There is just something about using WM_SETTEXT to set the text of a control which escapes me.

Any ideas?

thanks,

Felipe Monteiro de Carvalho

Reply by email

Jonas Maebe
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 10 lines
Which I tryed to convert to: if UnicodeEnabledOS then SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(PWideChar(Utf8Decode(TheText)))) else SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(PChar(Utf8ToAnsi(TheText)))); But this doesn't seam to work, and the text is shown scrambled.

You're making the same error which Marco pointed out earlier: Utf8Decode returns a (reference counted) widestring, but you are not assigning it to anything so it ends up in a (reusable) temp location. As soon as the next temporary widestring has to be created, the previous one is destroyed and the pwidechar will point to a random memory block.

The same goes for the Utf8ToAnsi() call, except that here it is an ansistring instead of a widestring.

Jonas

Reply by email

Felipe Monteiro de Carvalho
to Jonas Maebe
Jonas Maebe wrote 6 lines
You're making the same error which Marco pointed out earlier: Utf8Decode returns a (reference counted) widestring, but you are not assigning it to anything so it ends up in a (reusable) temp location. As soon as the next temporary widestring has to be created, the previous one is destroyed and the pwidechar will point to a random memory block.

Ummm, but there is nothing else on that function, so I don't see how can the temporary string be destroyed before I call SETTEXT, unless SETTEXT expects that I give it a storage that is at all times available...

procedure TWin32MemoStrings.SetText(TheText: PChar);
begin
    SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(TheText));
end;

Which I currently converted into (but still doesn't work):

procedure TWin32MemoStrings.SetText(TheText: PChar);
var
  AnsiBuffer: ansistring;
  WideBuffer: widestring;
begin
  {$ifdef WindowsUnicodeSupport}
    if UnicodeEnabledOS then
    begin
      WideBuffer := Utf8Decode(TheText);
      SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(PWideChar(WideBuffer)));
    end
    else
    begin
      AnsiBuffer := Utf8ToAnsi(TheText);
      SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(PChar(AnsiBuffer)));
    end;
  {$else}
    SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(TheText));
  {$endif}
end;

Alternatively I moved AnsiBuffer and WideBuffer to the class declaration, so they are always available, which also didn't solve the problem of showing wrong characters.

It shows the string ééé as if it was Ã(c)Ã(c)Ã(c)

Which is what I would expect if I use ansi routines to show a utf-8 string.

thanks,

Felipe Monteiro de Carvalho

Reply by email

Jonas Maebe
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 11 lines
On Nov 10, 2007 4:30 PM, Jonas Maebe wrote: > You're making the same error which Marco pointed out earlier: > Utf8Decode returns a (reference counted) widestring, but you are not > assigning it to anything so it ends up in a (reusable) temp location. > As soon as the next temporary widestring has to be created, the > previous one is destroyed and the pwidechar will point to a random > memory block. Ummm, but there is nothing else on that function, so I don't see how can the temporary string be destroyed before I call SETTEXT,

You should never make assumptions about when compiler-managed types are destroyed when you don't hold an explicit reference to them anymore (it may happen immediately, or a long time in the future, and anywhere in between).

Show quoted text 41 lines
unless SETTEXT expects that I give it a storage that is at all times available... procedure TWin32MemoStrings.SetText(TheText: PChar); begin SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(TheText)); end; Which I currently converted into (but still doesn't work): procedure TWin32MemoStrings.SetText(TheText: PChar); var AnsiBuffer: ansistring; WideBuffer: widestring; begin {$ifdef WindowsUnicodeSupport} if UnicodeEnabledOS then begin WideBuffer := Utf8Decode(TheText); SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(PWideChar(WideBuffer))); end else begin AnsiBuffer := Utf8ToAnsi(TheText); SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(PChar(AnsiBuffer))); end; {$else} SendMessage(fHandle, WM_SETTEXT, 0, LPARAM(TheText)); {$endif} end; Alternatively I moved AnsiBuffer and WideBuffer to the class declaration, so they are always available, which also didn't solve the problem of showing wrong characters. It shows the string ééé as if it was Ã(c)Ã(c)Ã(c) Which is what I would expect if I use ansi routines to show a utf-8 string.

The above code looks correct as far as managing the data is concerned. I don't know anything about the win32 api though, so I can't help further.

Jonas

Reply by email