With Delphi “Tiburon” CodeGear wants to introduce Unicode-support for the Win32 personality. Unlike C++ Builder which has a preprocessor and thus can at least switch between ANSI and Unicode via a simple preprocessor define, Delphi didn’t have such a (globally available) mechanism in previous versions. And even in C++ Builder you wouldn’t get far with the preprocessor defines, since the (ANSI-only) VCL is merely Delphi code compiled and linked into your C++ Builder projects. Several free and commercial alternatives like the well-renowned “TNT Unicode Controls” have been created throughout the years, to keep developers happy with some support for Unicode. In fact some of those controls offered a support that reached beyond what a conditional build in other development environments would yield: the ability to run on Windows 9x and the NT-platform seamlessly with one binary.
To recount known facts, Unicode exists quite a while already and NT4 (released in 1996, i.e. about 12 years ago) supported UCS-2 (two-byte wide characters) which has now been superseded by UTF-16. Now let’s get to the Delphi-specific part and put aside the fact that CodeGear (under its various names) was apparently not following up on the developments in the Windows development community very well.
The migration of existing Delphi-code is going to be a PITA for many many projects, since CodeGear took the strange – and IMO wrong – decision of defaulting the aptly named
PWideChar starting with Delphi “Tiburon” – read here. Quote from this very link:
Now that PChar is an alias to PWideChar, things started falling over because the element type is now 2 bytes.
Here is how
PCHAR is declared in the Windows SDK inside
typedef CHAR *PCHAR, *LPCH, *PCH;
For those not literate enough in C, here is what this means in Delphi:
type PCHAR = ^CHAR; type LPCH = ^CHAR; type PCH = ^CHAR;
Since the Delphi language (and Pascal) is case-insensitive, you now have the definition of Delphi’s
PChar as everyone else in the Windows development community understands it.
Do we have a problem here? We sure do. While in the C/C++ world – and remember that this also includes C++ Builder –
TCHAR is the basis for any pointer types that can be used for zero-terminated character strings,
PCHAR was clearly meant to be ANSI only. With the preprocessor symbols
UNICODE, any Windows C/C++ preprocessor that can be used with the Windows SDK will happily replace every occurrence of
WCHAR; … which would be the counterpart to
WideChar in Delphi and is also defined in
Windows.pas, if memory serves me well. On the other hand if those preprocessor symbols are not defined,
TCHAR will resolve to
CHAR which resolves to
char, the intrinsic type used for one-byte characters – read: ASCII/ANSI. So consequently, the widely known naming scheme has been broken by CodeGear in order to break legacy code only partially.
Allen predicted it right in his blog entry (already linked above):
I predict there will be hails of praise from one camp, and sneering and guffaws from another. The largest camp will be the ones ambivalent to this change. To which camp to you belong?
Guess what camp I belong to? Now don’t get me wrong. I am all for breaking backwards compatibility if it serves the purpose. And this certainly would serve the purpose … the purpose of lifting Delphi on par with other Windows development environments again.
However, breaking it half-heartedly is not the way to go, because the rather relaxed type checking in Delphi, compared to C++ (although some claim the opposite) will cause subtle bugs in existing code-bases. Furthermore they decided to change the meaning of a type name which is known and used beyond Delphi and thus breaking widely accepted naming conventions.
The decision whether this is an intentional affront against a “Microsoft convention” or simply a misjudgement is left to the reader’s subjective view. I think it is a wrong decision in any case, because you should play by the rules of the environment for which you create your products. In case of Delphi that’s still Windows.
By the way: JWA and JWSCL can be independently built with
UNICODE defined or not defined. So it’s prepared and the type name (
TJwPChar) follows the CodeGear naming scheme.
PS: Before anyone blames any of the JEDI projects (hosted here or elsewhere) for this post, these are my thoughts. Other members do not necessarily agree with anything or everything said here.