views:

1672

answers:

6

How can I create unicode console application with Delphi 2009?

If I do like this:

{$APPTYPE CONSOLE}
uses
  SysUtils;
begin
  writeln('öüğşç سيمانتت');
end.

I get the following:

ougsc ???????
+4  A: 

You can't (At least not with the standard library). The console functions are the only non Unicode functions in Delphi 2009.

Gamecat
If Delphi 2009 really is full-unicode there must be a way to do it.
Nope, the console is the only part not unicode. I have that information directly from a codegear speaker at a conference.
Gamecat
Thanks for this information.
A: 

Windows console cannot display unicode charactes, so try to send output to file with:

my_app.exe > unicode_file.txt

and try viewing unicode_file.txt with good text editor.

Michał Niklas
Window console can display unicode characters. There are several programs that use unicode console. Redirecting output to a file gives the same corrupted ansi text.
+5  A: 

I'm not sure that is what you're after, but you can create Unicode console applications in all 32-bit Delphi versions by using the Windows API functions. I just tried with Delphi 4:

program test;

{$APPTYPE CONSOLE}

uses
  Windows;

var
  s: WideString;
  i: integer;
  Written: Cardinal;
begin
  SetLength(s, 80);
  for i := 1 to 80 do
    s[i] := WideChar(48 + i);
  WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), PWideChar(s), 80, Written,
    nil);
end.

I don't have Delphi 2009 to try how entering Unicode strings in the editor works...

mghie
I tried your code. It doesn't work. Have you tested it for non-ANSI Unicode characters (e.g. widechar($416) - "Ж", widechar($11f) - "ğ", widechar($633) - "س") ?
Sorry, I forgot about console font (I ran it in debug mode). Thanks, it work's with vector font (I changed my console vector font to "Courier New").
WriteConsole will not work for redirected output (like app.exe > file.txt), so you better check if WriteConsole returns False then use WriteFile instead. With WriteFile you can write either unicode or ansi. Usual most applications uses ansi in that case.
Alexander
+1  A: 

@Kabrol: With the raster font set I don't see either of the chars, but with Lucida Console I see at least widechar($11f) - "ğ".

Please see "SetConsoleOutputCP Only Effective with Unicode Fonts" and in general the description of console API functions at "Console Reference".

mghie
Sorry, I forgot about console font (I ran it in debug mode). Thanks, it work's with vector font (I changed my console vector font to "Courier New").
+3  A: 

Writeln in Delphi 2009 still uses ANSI (see System TTextRec) but you can use UTF8Encode and change the console's output code page to UTF8 by calling SetConsoleOutputCP(CP_UTF8). You will also need a good font to actually display Unicode characters.

TOndrej
Unbelievable! Thanks, It works. I didn't know that windows console supports multibyte character set such as UTF-8.
A: 

Actually, there is a way to do this with standard WriteLn() calls, but it involves patching a bug in the Delphi 2009 RTL. The thing is, Delphi does some compiler magic for WriteLn. For UnicodeString arguments, this results in a call to _WriteUString. That method can be seen in System.pas, although you can't call it directly. In it you'll see a call to _WriteLString, but that method receives a AnsiString argument. So when this call is taking place, your UnicodeString is being downcasted to AnsiString.

The solution is, to change this UnicodeString->AnsiString cast into a UnicodeString->UTF8String cast.

Now, when you set the console to UTF8, all your characters will go through untouched (and yes, ofcourse you'll need a font with support for the characters you want to show) :

SetConsoleOutputCP(CP_UTF8)

For this RTL fix, you'll need to do some nifty code-hooking. I've done this already, and a collegue of mine is busy writing an article about this. I'll post a link once it's available online.

Cheers!

PatrickvL
This sounds like reinventing the wheel since there is already a article which reads like "Homer's Odyssey": http://edn.embarcadero.com/article/39022
mjustin
Maybe you didn't notice, but this is exactly the article I meant - the one that my collegue Marjan Venema wrote (if you look closely, my name _does_ appear in there a few times).Anyway, thanks for adding the link - I forget those things sometimes. And yes, it rather reads like an odyssey indeed!
PatrickvL