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