|
6 | 6 | def readchar() -> str: |
7 | 7 | """Reads a single utf8-character from the input stream. |
8 | 8 | Blocks until a character is available.""" |
9 | | - # read the first character. |
10 | | - ch = [msvcrt.getwch()] |
11 | 9 |
|
12 | | - # if the first character indicates a surrogate pair, read the second character. |
13 | | - if 0xD800 <= ord(ch[0]) <= 0xDFFF: |
14 | | - ch.append(msvcrt.getwch()) |
15 | | - |
16 | | - # combine the characters into a single utf-16 encoded string. |
17 | | - # this prevents the character from being treated as a surrogate pair again. |
18 | | - return "".join(ch).encode("utf-16", errors="surrogatepass").decode("utf-16") |
| 10 | + # read a single wide character from the input |
| 11 | + return msvcrt.getwch() |
19 | 12 |
|
20 | 13 |
|
21 | 14 | def readkey() -> str: |
22 | 15 | """Reads the next keypress. If an escaped key is pressed, the full |
23 | 16 | sequence is read and returned as noted in `_win_key.py`.""" |
24 | 17 |
|
| 18 | + # read first character |
25 | 19 | ch = readchar() |
26 | 20 |
|
| 21 | + # keys like CTRL+C should cause a interrupt |
27 | 22 | if ch in config.INTERRUPT_KEYS: |
28 | 23 | raise KeyboardInterrupt |
29 | 24 |
|
30 | | - # if it is a normal character: |
31 | | - if ch not in "\x00\xe0": |
32 | | - return ch |
| 25 | + # parse special multi character keys (see key module) |
| 26 | + # https://learn.microsoft.com/cpp/c-runtime-library/reference/getch-getwch#remarks |
| 27 | + if ch in "\x00\xe0": |
| 28 | + # read the second half |
| 29 | + # we always return the 0x00 prefix, this avoids duplications in the key module |
| 30 | + ch = "\x00" + readchar() |
| 31 | + |
| 32 | + # parse unicode surrogates |
| 33 | + # https://docs.python.org/3/c-api/unicode.html#c.Py_UNICODE_IS_SURROGATE |
| 34 | + if "\uD800" <= ch <= "\uDFFF": |
| 35 | + ch += readchar() |
33 | 36 |
|
34 | | - # if it is a scpeal key, read second half: |
35 | | - ch2 = readchar() |
| 37 | + # combine the characters into a single utf-16 encoded string. |
| 38 | + # this prevents the character from being treated as a surrogate pair again. |
| 39 | + ch = ch.encode("utf-16", errors="surrogatepass").decode("utf-16") |
36 | 40 |
|
37 | | - return "\x00" + ch2 |
| 41 | + return ch |
0 commit comments