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