ReactOS 0.4.16-dev-853-g88d9285
getwch.cpp
Go to the documentation of this file.
1//
2// getwch.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines _getwch(), _getwche(), and _ungetwch(), which get and unget
7// characters directly from the console.
8//
9#include <conio.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <wchar.h>
15
16
17
18namespace
19{
20 struct CharPair
21 {
22 unsigned char LeadChar;
23 unsigned char SecondChar;
24 };
25}
26
27
28static wint_t wchbuf = WEOF; // The push-back buffer
29
31
32extern "C" CharPair const* __cdecl _getextendedkeycode(KEY_EVENT_RECORD*);
33
34
35
36// Reads one character directly from the console. The _getwche() form also
37// echoes the character back to the console. If the push-back buffer is
38// nonempty, then its value is returned and the push-back buffer is marked as
39// empty.
40//
41// Returns the character that is read on success; returns WEOF on failure.
43{
45 wint_t result = 0;
46 __try
47 {
49 }
51 {
53 }
55 return result;
56}
57
58
60{
62 wint_t result = 0;
63 __try
64 {
66 }
68 {
70 }
72 return result;
73}
74
75
76
78{
79 // First check the pushback buffer for a character. If it has one, return
80 // it without echoing and reset the buffer:
81 if (wchbuf != WEOF)
82 {
83 wchar_t const buffered_wchar = static_cast<wchar_t>(wchbuf & 0xFFFF);
84 wchbuf = WEOF;
85 return buffered_wchar;
86 }
87
88 // The console input handle is created the first time that _getwch(),
89 // _cgetws(), or _kbhit() is called:
91 return WEOF;
92
93 // Switch to raw mode (no line input, no echo input):
94 DWORD old_console_mode;
95 __dcrt_get_input_console_mode(&old_console_mode);
97 wint_t result = 0;
98 __try
99 {
100 for ( ; ; )
101 {
102 // Get a console input event:
103 INPUT_RECORD input_record;
104 DWORD num_read;
105 if (__dcrt_read_console_input(&input_record, 1, &num_read) == FALSE)
106 {
107 result = WEOF;
108 __leave;
109 }
110
111 if (num_read == 0)
112 {
113 result = WEOF;
114 __leave;
115 }
116
117 // Look for, and decipher, key events.
118 if (input_record.EventType == KEY_EVENT && input_record.Event.KeyEvent.bKeyDown)
119 {
120 // Easy case: if UnicodeChar is non-zero, we can just return it:
121 wchar_t const c = static_cast<wchar_t>(input_record.Event.KeyEvent.uChar.UnicodeChar);
122 if (c != 0)
123 {
124 result = c;
125 __leave;
126 }
127
128 // Hard case: either it is an extended code or an event which
129 // should not be recognized. Let _getextendedkeycode do the work:
130 CharPair const* const cp = _getextendedkeycode(&input_record.Event.KeyEvent);
131 if (cp != nullptr)
132 {
133 wchbuf = cp->SecondChar;
134 result = cp->LeadChar;
135 __leave;
136 }
137 }
138 }
139 }
141 {
142 // Restore the previous console mode:
143 __dcrt_set_input_console_mode(old_console_mode);
144 }
146 return result;
147}
148
149
150
152{
153 // First check the pushback buffer for a character. If it has one, return
154 // it without echoing and reset the buffer:
155 if (wchbuf != WEOF)
156 {
157 wchar_t const buffered_wchar = static_cast<wchar_t>(wchbuf & 0xFFFF);
158 wchbuf = WEOF;
159 return buffered_wchar;
160 }
161
162 // Othwrwise, read the character, echo it, and return it. If anything fails,
163 // we immediately return WEOF.
164 wchar_t const gotten_wchar = _getwch_nolock();
165 if (gotten_wchar == WEOF)
166 return WEOF;
167
168 if (_putwch_nolock(gotten_wchar) == WEOF)
169 return WEOF;
170
171 return gotten_wchar;
172}
173
174
175
176// Pushes back ("ungets") one character to be read next by _getwch() or
177// _getwche(). On success, returns the character that was pushed back; on
178// failure, returns EOF.
179extern "C" wint_t __cdecl _ungetwch(wint_t const c)
180{
182 wint_t result = 0;
183 __try
184 {
186 }
188 {
190 }
192 return result;
193}
194
195
196
198{
199 // Fail if the char is EOF or the pushback buffer is non-empty:
200 if (c == WEOF || wchbuf != WEOF)
201 return static_cast<wint_t>(EOF);
202
203 wchbuf = (c & 0xFF);
204 return wchbuf;
205}
int wint_t
Definition: _apple.h:38
#define __cdecl
Definition: accygwin.h:79
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
@ __acrt_conio_lock
__acrt_lock(__acrt_heap_lock)
#define FALSE
Definition: types.h:117
unsigned long DWORD
Definition: ntddk_ex.h:95
wint_t __cdecl _ungetwch_nolock(wint_t const c)
Definition: getwch.cpp:197
wint_t __cdecl _getwch()
Definition: getwch.cpp:42
static wint_t wchbuf
Definition: getwch.cpp:28
intptr_t __dcrt_lowio_console_input_handle
Definition: getwch.cpp:30
CharPair const *__cdecl _getextendedkeycode(KEY_EVENT_RECORD *)
Definition: getch.cpp:506
wint_t __cdecl _getwche_nolock()
Definition: getwch.cpp:151
wint_t __cdecl _getwche()
Definition: getwch.cpp:59
wint_t __cdecl _getwch_nolock()
Definition: getwch.cpp:77
const GLubyte * c
Definition: glext.h:8905
GLuint64EXT * result
Definition: glext.h:11304
#define EOF
Definition: stdio.h:24
BOOL __cdecl __dcrt_read_console_input(_Out_ PINPUT_RECORD lpBuffer, _In_ DWORD nLength, _Out_ LPDWORD lpNumberOfEventsRead)
Definition: initconin.cpp:67
BOOL __cdecl __dcrt_get_input_console_mode(_Out_ LPDWORD lpMode)
Definition: initconin.cpp:136
BOOL __cdecl __dcrt_lowio_ensure_console_input_initialized()
Definition: initconin.cpp:31
BOOL __cdecl __dcrt_set_input_console_mode(_In_ DWORD dwMode)
Definition: initconin.cpp:150
#define c
Definition: ke_i.h:80
POINT cp
Definition: magnifier.c:59
#define __try
Definition: pseh2_64.h:172
#define __leave
Definition: pseh2_64.h:176
#define __endtry
Definition: pseh2_64.h:175
#define __finally
Definition: pseh2_64.h:174
#define WEOF
Definition: conio.h:185
_Check_return_opt_ _CRTIMP wint_t __cdecl _putwch_nolock(wchar_t _WCh)
Definition: putwch.cpp:22
#define _ungetwch()
Definition: conio.h:341
union _INPUT_RECORD::@3339 Event
WORD EventType
Definition: wincon.h:273
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:275
union _KEY_EVENT_RECORD::@3338 uChar
WCHAR UnicodeChar
Definition: wincon.h:245
int intptr_t
Definition: vcruntime.h:134
#define KEY_EVENT
Definition: wincon.h:128