![]() |
( This announcement is a bit non-exciting small improvement around the engine codebase. For something more exciting, that I was working on through September, see the screenshot attached here :), and stay tuned for more news soon. )
Previously, our engine did SetMultiByteConversionCodePage(CP_UTF8) forcing all AnsiStrings (with both FPC and Delphi) to have UTF-8 encoding. This is also consistent with what Lazarus LCL was (and still is) doing.
We have extended our possibilities now, and changed what happens with Delphi by default (with FPC, nothing changes by default):
- Throughout the engine, we use now always
Utf8Stringwhen we want to say “8-bit string with UTF-8 encoding”. Aside from the practical gains (see below), this naturally just looks better: we explicitly express our intention.We use
AnsiStringin code only when (very seldom) we really mean “8-bit string with whatever encoding happens to be the platform default”.We have tested that with Delphi (unfortunately, not so with FPC) the proper implicit conversions are always done when you assign between
AnsiString(even if they have non-UTF-8 content) andUtf8String. See lots of new automatic tests in- testcompiler.pas
- testcastleifc.pas
- testfpjson.pas
- testcastlescenecore.pas
- testcastleclassutils.pas
- testcastledownload.pas
Note: 90% code of the engine still uses just
String(notUtf8StringorAnsiString). That is deliberate and simple: we want to just use default string type, which meansUnicodeString(String=UnicodeStringwith Delphi, or FPC Unicode RTL) orAnsiString(FPC, without FPC Unicode RTL). Nothing changes in this regard. -
We added defines to control whether the engine does
SetMultiByteConversionCodePage(CP_UTF8), forcing allAnsiStringto contain UTF-8. And by default, it is no longer done when compiled with Delphi.CASTLE_ANSISTRING_FORCE_UTF8: This is the previous behavior. And it is still default with FPC.CASTLE_ANSISTRING_UNCHANGED: This is the new possible behavior. It is (since now) the default with Delphi.
Note that
CASTLE_ANSISTRING_UNCHANGEDis not supported with FPC, due to FPC (at least 3.2.2) not doingAnsiStringvsUtf8Stringconversions automatically (but you can force it by defining alsoI_UNDERSTAND_THAT_NON_ASCII_CHARACTERS_ARE_BROKENif you really need it, and understand the consequences).We changed Delphi default to
CASTLE_ANSISTRING_UNCHANGED, because it works flawlessly with Delphi in our tests, and it seems safer — we don’t mess with global settings if we don’t need to. This is nice if you have an existing codebase that assumesAnsiStringdon’t hold UTF-8 encoded data. This is also important when our code is run as part of Delphi IDE, when you install our Delphi packages — this way we don’t mess assumptions that may be made by Delphi IDE or other 3rd-party Delphi packages you have. -
Along the way, we have also fixed and simplified some details around how Unicode characters are handled.
- Reading JSON files (with our
FpJson) with non-ASCII text now works on Delphi reliably. OurFpJsonunit (and friend) useStringorUtf8String, and don’t mess with encoding. -
FPHashCompatibilityunit, complicated compatibility hack for Delphi, is gone. -
A few cases when we used UTF-8 with Delphi are fixed. E.g. with Delphi, one cannot do
S := S + CwhenSisUtf8StringandCisAnsiCharandCmay be only a part of multi-byte character: Delphi will padCto be a valid Unicode character. SeeTTestCompiler.TestAddingIncompleteUtf8test intests/code/testcases/testcompiler.pasfor details. -
CastleReadLinkon Delphi/Linux fixed. -
GetTempFileNamePrefixon Delphi/Windows fixed. -
We cleaned some unused Vampyre Imaging files (like dglOpenGL copy used by Vampyre demos) to not confuse developers what is used by our engine.
- Reading JSON files (with our
For more details about how CASTLE_ANSISTRING_FORCE_UTF8 and CASTLE_ANSISTRING_UNCHANGED work see
- CASTLE_ANSISTRING_xxx symbols, AnsiString vs Utf8String
-
Updated/extended coding conventions about String: https://castle-engine.io/coding_conventions#strings_unicode
-
And for really all details, see all 57 commits of this change on GitHub.
If you like our work, please support us on Patreon!
