Quote from: bstewart on Today at 07:46:59 pm [[https://forum.lazarus.freepascal.org/index.php/topic,73290.msg574592.html#msg574592](https://forum.lazarus.freepascal.org/index.php/topic,73290.msg574592.html#msg574592)]How do we fix ReadLn without a manifest so it runs on older platforms? Or is it not possible?
Unfortunately, **it's not possible to reliably fix `ReadLn` for UTF-8 input on older Windows versions without a manifest**. Here’s why:
The issue stems from how the Windows console (cmd.exe) handles Unicode input/output before Windows 10 version 1903. Prior to this, the console was fundamentally designed around ANSI codepages, and even when you set `chcp 65001`, the underlying I/O functions used by the RTL often encounter bugs or limitations with multi-byte sequences.
### Why the Manifest Works
The manifest enables the "ANSI codepage is UTF-8" feature introduced in Windows 10 1903. This tells the OS to treat all ANSI APIs (like those used by FPC’s `ReadLn`) as UTF-8, effectively making them work correctly with Unicode strings. Without this, the console’s internal handling of UTF-8 sequences breaks, leading to garbled output like `de??µa`.
### Alternatives for Older Platforms
If you need compatibility with older Windows versions (7/8/early 10), here are some workarounds:
1. **Use Windows API (`ReadConsoleW`)**
Standard `ReadLn` relies on ANSI system calls. To properly read Unicode on older Windows, you must bypass the standard input mechanism and use `ReadConsoleW`, which reads UTF-16 (WideString) directly from the console buffer. You can then convert the result to UTF-8.
```pascal
program test;
{$MODE OBJFPC}{$H+}
uses Windows, SysUtils;
var
hStdIn: THandle;
dwRead: DWORD;
Buffer: array[0..1023] of WideChar;
WStr: WideString;
S: String;
begin
// Set output to UTF-8 so we can print the result correctly
SetConsoleOutputCP(CP_UTF8);
Write('Enter δείγμα: ');
hStdIn := GetStdHandle(STD_INPUT_HANDLE);
// Read WideChars directly to avoid ANSI conversion issues
if ReadConsoleW(hStdIn, @Buffer, Length(Buffer), dwRead, nil) then
begin
SetString(WStr, Buffer, dwRead);
// Trim CR/LF from the end manually
while (Length(WStr) > 0) and (WStr[Length(WStr)] < #32) do
Delete(WStr, Length(WStr), 1);
S := UTF8Encode(WStr); // Convert safely to UTF-8
end;
WriteLn('S := ' + S);
end.
```
2. **Use a Different Console Emulator**
Tools like ConEmu or Windows Terminal provide better Unicode support than the default cmd.exe, even on older Windows versions. However, this shifts the burden to the user rather than solving it programmatically.
3. **Switch to GUI Applications**
If feasible, consider building a GUI application using Lazarus or another framework. GUI controls handle Unicode input much more reliably across different Windows versions.
### Conclusion
While there are workarounds, none are as seamless as using the manifest approach. For legacy support on older Windows, using `ReadConsoleW` is the most robust programmatic solution, as the standard `ReadKey` or `ReadLn` functions are prone to encoding errors with multi-byte characters in those environments.
Hope this helps! 😊