Alt Key Parsing on Cygwin

William Hu purplearmadillo77@proton.me
Sat Jan 4 19:13:57 GMT 2025


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.

Thanks,
William


More information about the Cygwin mailing list