maybe it's a Linux thing?
No, it's a Windows-only problem.
Long ago, when going unicode, Linux did the sensible thing by adopting utf-8. Microsoft though they know better, plus they had to uphold backward compatibility. Thus, all the *A/*W fuss and stuff. And this is the roor of Free Pascal's problems. While Linux making AnsiString encoding-aware was pretty enough, in Windows you have to switch all classes to using UnicodeString because that's what Windows uses natively.
90% of the time, completely avoidable/preventable...
This case falls into these pesky 10%.
Free Pascal's class library is *horribly* out of date with regards to Unicode file names on the Windows platform. If you develop a Windows application in pure FP, without using Lazarus-specific fixes, your application will be stomped by competition because it could fail where any sensible Windows applications have no problems since 15 years ago.
And while fpc 3 *did* fix the RTL, it *DID NOT* fix the classes. So good luck if you are using TStream *or* any third-party library that uses streams to read from files.
It's a glaring flaw that should have been addressed a decade ago.
P.S. So I have to use hacks in fpc 3 to make my application Unicode.
And I am *lucky* I don't have to deal with third-party libraries because they have no such hack...
Oh, wait, I do. I use Vampyre Imaging and I cannou use its functions of loading image from file. I have to load files into memory buffer myself then call vampyre function that loads images from memory. I'm lucky Vampyre *does* have such functions.
Code:
TFileStream = class(classes.THandleStream)
Private
FFileName : UnicodeString;
public
constructor Create(const AFileName: UnicodeString; Mode: Word);
constructor Create(const AFileName: UnicodeString; Mode: Word; Rights: Cardinal);
destructor Destroy; override;
property FileName : UnicodeString Read FFilename;
end;
...
constructor TFileStream.Create(const AFileName: UnicodeString; Mode: Word);
begin
Create(AFileName, Mode, 438);
end;
constructor TFileStream.Create(const AFileName: UnicodeString; Mode: Word; Rights: Cardinal);
var
h: THandle;
begin
FFileName:= AFileName;
If (Mode and fmCreate) > 0 then
h:= FileCreate(AFileName,Mode,Rights) // it IS already unicode in 3.0.0
else
h:= FileOpen(AFileName,Mode);
If (h = feInvalidHandle) then
If Mode = fmcreate then
Die(RuEn('Не удалось создать файл "%0"','Failed to create file "%0"'),[AFileName])
else
Die(RuEn('Не удалось открыть файл "%0"','Failed to open file "%0"'),[AFileName]);
inherited Create(h);
end;
destructor TFileStream.Destroy;
begin
FileClose(Handle);
end;
P.P.S. I'd call it "dick move" if didn't know the devs are mostly focused on Linux. This probably slipped their mind. And that Lazarus patch and everyone using it probably didn't help as it negated the problem somehow.
Still, this one great pitfall marginalizes Free Pascal by making it harder to write serious business applications for Windows.
P.P.P.S Worst case scenario: you write an application, going to great pains to make 100% sure it works. Like 90% people out there you are unaware that fpc is not unicode.
Finally it's time to show it to your boss. You launch it on his machine... Which coincidentally has user name like "фañ"... And your application flops with a weird error. Why? What? You lost your face.
You try fixing the problem ASAP pulling all-nighter to be ready try the next day, but... The problem is not easily fixable, you miss some instances of non-unicodeness in your tired state. Your application flops again in the face of your boss.
"What it is written in?" he asks. "Free Pascal...? Forget that crap and learn proper coding tools. You're fired."
Bookmarks