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

--
Problem reports:      https://cygwin.com/problems.html
FAQ:                  https://cygwin.com/faq/
Documentation:        https://cygwin.com/docs.html
Unsubscribe info:     https://cygwin.com/ml/#unsubscribe-simple

Reply via email to