In the past I had rarely issues, that writeln() in console programs showed a wrong codepage for ansistrings on Win7. These programs were larger and used Unit CRT. I did not check, if it worked on Win10.
But now I have the same issue, that a console program shows a wrong codepage, without using Unit CRT and it is reproducible in a very simple demo on Win7 and Win10.
This issue occured always in a way, that a function, which returns an ansistring, returned the correct (!) bytes, but - don't know why - caught a wrong codepage, so the next writeln() showed this string in a wrong codepage, although all bytes of the string had the correct value.
On my Win7 console the default codepage is cp850 = DOS with and without Unit CRT (which I assume is the standard on a German Win7).
On my Win10 console the default codepage is cp1252 = WINDOWS with Unit CRT and cp850 = DOS without Unit CRT (which I assume is the standard on a German Win10).
So a console program without Unit CRT needs cp850 = DOS on my Win7 and Win10.
This is my demo code:
{shows wrong codepage in console of Win7 + Win10 without Unit CRT}
{$mode objfpc} {$H+}
// uses crt; {repairs the issue}
{Text 'ÄÖÜ äöü ß' in 2 codepages: }
const Msg_DOS = #$8E#$99#$9A#$20#$84#$94#$81#$20#$E1; {codepage cp850 = DOS}
Msg_WIN = #$C4#$D6#$DC#$20#$E4#$F6#$FC#$20#$DF; {codepage cp1252 = WINDOWS}
type
mystring = ansistring;
// mystring = shortstring; {repairs the issue}
function hexString(s: mystring): mystring;
{returns the content of 's' as hex-bytes}
var z: mystring;
i: longint;
begin
z:='';
for i:=1 to length(s) do z:=z + ' ' + hexStr(ord(s[i]),2);
delete(z,1,1);
exit(z);
end;
procedure setCodePage_CP_NONE(var s: mystring);
{repairs the issue}
begin
{$IF sizeof(s) = sizeof(ansistring)} // does not compile with 'shortstring':
write('<cp=', system.StringCodePage(s), '>'); {returns '0'}
system.SetCodePage(RawByteString(s),CP_NONE,false);
{$ENDIF}
end;
function dummy(s: mystring): mystring;
{should change nothing}
begin
// setCodePage_CP_NONE(s); {repairs the issue}
exit(s);
end;
var s: mystring;
begin {main}
// assign(Output,''); rewrite(Output); {repairs the issue}
writeln('DOS-codepage: ', Msg_DOS);
s:=dummy(Msg_DOS);
writeln('DOS-codepage with dummy: ', s, ' = ', hexString(s));
(* only if you have codepage cp1252 = WINDOWS in your console:
writeln('WIN-codepage: ', Msg_WIN);
s:=dummy(Msg_WIN);
writeln('WIN-codepage with dummy: ', s, ' = ', hexString(s));
*)
end.
I declared const 'Msg_DOS' and 'Msg_WIN' in this way to be independend of the source files codepage.
When I run this program on my Win7 and Win10 console, the output is:
DOS-codepage: ÄÖÜ äöü ß
DOS-codepage with dummy: ZTs ""? á = 8E 99 9A 20 84 94 81 20 E1The 1st line is correct, because 'Msg_DOS' has codepage cp850 = DOS.
The 2nd line is wrong, because function dummy() was called, which returns the correct bytes, but is displayed wrong.
As said, with Unit CRT this issue does not occur!
This issue disappears, when I
- call assign(Output,'') and rewrite(Output) at start
- or call setCodePage_CP_NONE() in those rare functions, which have this issue
- or replace type 'mystring' by 'shortstring'
- or add Unit CRT (but in the past, when this issue rarely occured, it was
always with Unit CRT).
In all 4 cases the output changes to:
DOS-codepage: ÄÖÜ äöü ß
<cp=0>DOS-codepage with dummy: ÄÖÜ äöü ß = 8E 99 9A 20 84 94 81 20 E1This all is with FPC 3.2.2 (but I have the same with 3.2.0 and 3.0.4).
Is there somebody who knows:
(a) why do some functions, e.g. function dummy(), change "something", so that this issue occurs?
(b) but why do they not change this with Unit CRT?
(c) why is calling setCodePage_CP_NONE() neccessary without Unit CRT and not with Unit CRT? - StringCodePage() returns in both cases the same value! ('0')
(d) why does calling before assign(Output,'') and rewrite(Output) solve ths issue?
Thanks in advance.