Alt Key Parsing on Cygwin
Brian Inglis
Brian.Inglis@SystematicSW.ab.ca
Sat Jan 4 21:01:07 GMT 2025
On 2025-01-04 12:13, William Hu via Cygwin wrote:
> Hi all,
>
> I've noticed that the Alt key parsing of the following program has different behavior across the different compiler chains/shells on Windows. Consider the following program that reads 4 characters from standard input.
> ```
> #include <cstdio>
>
> int main() {
> char x[4] {};
> fgets(reinterpret_cast<char*>(&x), 4, stdin);
> for (int i {0}; i < 4; ++i) {
> printf("%x ", x[i]);
> }
> return 0;
> }
> ```
> Perform these steps:
> 1. compile (g++ test.cc under cygwin, cl test.cc under MSVC)
> 2. execute
> 3. hit "Alt" and "1" at the same time and then hit enter
>
> Here is a table of the output of this program when compiled with different toolchains and executed in various terminals.
>
> +-------------------------------+----------------+--------------+------------+
> | COMPILER | Cygwin Mintty | MSYS2 Mintty | CMD |
> +-------------------------------+----------------+--------------+------------+
> | Cygwin g++ | 1b 31 a 0 | 1b 31 0 0* | 1b 31 0 0* |
> | Cygwin x86_64-w64-mingw32-g++ | 31 a 0 0 | 31 a 0 0 | 31 a 0 0 |
> | MSYS2 UCRT g++ | 31 a 0 0 | 31 a 0 0 | 31 a 0 0 |
> | Visual Studio 2022 | 31 a 0 0 | 31 a 0 0 | 31 a 0 0 |
> +-------------------------------+----------------+--------------+------------+
> -----------------------------------------------------------------------------
> * cygwin1.dll was copied into the current directory in order to run the program within these terminals. I didn't get a chance to hit enter - the application just quits.
>
> I thought different C libraries might be the problem, so I tried a pure-winapi version:
> ```
> #include <cstdio>
> #include <windows.h>
>
> int main() {
> // On Cygwin, apparently these are distinct - stdin points to a pipe rather than a console buffer
> HANDLE hstdin {GetStdHandle(STD_INPUT_HANDLE)};
> HANDLE hconin {CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0)};
> printf("STDIN Handle: %p\n", hstdin);
> printf("CONIN Handle: %p\n", hconin);
>
> DWORD stdtype {GetFileType(hstdin)};
> DWORD contype {GetFileType(hconin)};
> printf("STDIN Filetype: %x\n", stdtype);
> printf("CONIN Filetype: %x\n", contype);
>
> char x[4] {};
> DWORD nread {0};
> // You might ask: Why not read from hconin? The test program will hang
> ReadFile(hstdin, &x, 4, &nread, NULL);
> for (int i {0}; i < 4; ++i) {
> printf("%x ", x[i]);
> }
> printf("\n");
>
> return 0;
> }
> ```
> New matrix:
> +-------------------------------+----------------+--------------+------------+
> | COMPILER | Cygwin Mintty | MSYS2 Mintty | CMD |
> +-------------------------------+----------------+--------------+------------+
> | Cygwin g++ | 1b 31 a 0 | 1b 31 0 0* | 1b 31 0 0* |
> | Cygwin x86_64-w64-mingw32-g++ | 31 d a 0 | 31 d a 0 | 31 d a 0 |
> | MSYS2 UCRT g++ | 31 d a 0 | 31 d a 0 | 31 d a 0 |
> | Visual Studio 2022 | 31 d a 0 | 31 d a 0 | 31 d a 0 |
> +-------------------------------+----------------+--------------+------------+
>
> What does Cygwin do differently that allows it to capture Alt key presses?
> The above tables suggest the presence of cygwin1.dll in the program is relevant.
> I'm guessing that the backend magic (e.g. pipes for standard input, invisible consoles)
> that Cygwin performs plays some role, but thought people on this list would be much more
> familiar with the inner workings and would be able to provide a fuller explanation.
Cygwin console device driver interfaces to Windows conhost, and tries to get out
of the way of non-Cygwin programs; most information about the console is given
in What's New notes:
https://cygwin.com/cygwin-ug-net/ov-new.html
Use the supported POSIX APIs documented in man-pages-posix package:
https://cygwin.com/cygwin-api/
Also cygcheck -k|--keycheck from e.g. cmd allows you to see key processing, for
example <Alt>-1<Enter>q:
> cygcheck -k
This key check works only in a console window, _NOT_ in a terminal session!
Abort with Ctrl+C if in a terminal session.
Press 'q' to exit.
Pressed 1x VK: 0x0012 VS: 0x0038 C: 0x0000 CTRL: -- -- LA -- NL -- -- -- --
Pressed 1x VK: 0x0031 VS: 0x0002 C: 0x0031 CTRL: -- -- LA -- NL -- -- -- --
Released 1x VK: 0x0031 VS: 0x0002 C: 0x0000 CTRL: -- -- LA -- NL -- -- -- --
Released 1x VK: 0x0012 VS: 0x0038 C: 0x0000 CTRL: -- -- -- -- NL -- -- -- --
Pressed 1x VK: 0x000d VS: 0x001c C: 0x000d CTRL: -- -- -- -- NL -- -- -- --
Released 1x VK: 0x000d VS: 0x001c C: 0x000d CTRL: -- -- -- -- NL -- -- -- --
Pressed 1x VK: 0x0051 VS: 0x0010 C: 0x0071 CTRL: -- -- -- -- NL -- -- -- --
Released 1x VK: 0x0051 VS: 0x0010 C: 0x0071 CTRL: -- -- -- -- NL -- -- -- --
--
Take care. Thanks, Brian Inglis Calgary, Alberta, Canada
La perfection est atteinte Perfection is achieved
non pas lorsqu'il n'y a plus rien à ajouter not when there is no more to add
mais lorsqu'il n'y a plus rien à retirer but when there is no more to cut
-- Antoine de Saint-Exupéry
More information about the Cygwin
mailing list