2 * msvcrt.dll console functions
4 * Copyright 2000 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Note: init and free don't need MT locking since they are called at DLL
21 * (de)attachment time, which is syncronised for us
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
35 #define LOCK_CONSOLE _mlock(_CONIO_LOCK)
36 #define UNLOCK_CONSOLE _munlock(_CONIO_LOCK)
38 static HANDLE MSVCRT_console_in
= INVALID_HANDLE_VALUE
;
39 static HANDLE MSVCRT_console_out
= INVALID_HANDLE_VALUE
;
40 static int __MSVCRT_console_buffer
= MSVCRT_EOF
;
42 /* INTERNAL: Initialise console handles */
43 void msvcrt_init_console(void)
45 TRACE(":Opening console handles\n");
47 MSVCRT_console_in
= CreateFileA("CONIN$", GENERIC_READ
, FILE_SHARE_READ
,
48 NULL
, OPEN_EXISTING
, 0, NULL
);
49 MSVCRT_console_out
= CreateFileA("CONOUT$", GENERIC_WRITE
, FILE_SHARE_WRITE
,
50 NULL
, OPEN_EXISTING
, 0, NULL
);
52 if ((MSVCRT_console_in
== INVALID_HANDLE_VALUE
) ||
53 (MSVCRT_console_out
== INVALID_HANDLE_VALUE
))
54 WARN(":Console handle Initialisation FAILED!\n");
57 /* INTERNAL: Free console handles */
58 void msvcrt_free_console(void)
60 TRACE(":Closing console handles\n");
61 CloseHandle(MSVCRT_console_in
);
62 CloseHandle(MSVCRT_console_out
);
65 /*********************************************************************
68 int CDECL
_cputs(const char* str
)
71 int retval
= MSVCRT_EOF
;
74 if (WriteConsoleA(MSVCRT_console_out
, str
, strlen(str
), &count
, NULL
)
81 /*********************************************************************
84 int CDECL
_cputws(const MSVCRT_wchar_t
* str
)
87 int retval
= MSVCRT_EOF
;
90 if (WriteConsoleW(MSVCRT_console_out
, str
, lstrlenW(str
), &count
, NULL
)
102 static const struct {unsigned vk
; unsigned ch
[4][2];} enh_map
[] = {
103 {0x47, {{0xE0, 0x47}, {0x00, 0x97}, {0xE0, 0x77}, {0xE0, 0x47}}},
104 {0x48, {{0xE0, 0x48}, {0x00, 0x98}, {0xE0, 0x8D}, {0xE0, 0x48}}},
105 {0x49, {{0xE0, 0x49}, {0x00, 0x99}, {0xE0, 0x86}, {0xE0, 0x49}}},
106 {0x4B, {{0xE0, 0x4B}, {0x00, 0x9B}, {0xE0, 0x73}, {0xE0, 0x4B}}},
107 {0x4D, {{0xE0, 0x4D}, {0x00, 0x9D}, {0xE0, 0x74}, {0xE0, 0x4D}}},
108 {0x4F, {{0xE0, 0x4F}, {0x00, 0x9F}, {0xE0, 0x75}, {0xE0, 0x4F}}},
109 {0x50, {{0xE0, 0x50}, {0x00, 0xA0}, {0xE0, 0x91}, {0xE0, 0x50}}},
110 {0x51, {{0xE0, 0x51}, {0x00, 0xA1}, {0xE0, 0x76}, {0xE0, 0x51}}},
111 {0x52, {{0xE0, 0x52}, {0x00, 0xA2}, {0xE0, 0x92}, {0xE0, 0x52}}},
112 {0x53, {{0xE0, 0x53}, {0x00, 0xA3}, {0xE0, 0x93}, {0xE0, 0x53}}},
115 /*********************************************************************
118 int CDECL
_getch(void)
120 int retval
= MSVCRT_EOF
;
123 if (__MSVCRT_console_buffer
!= MSVCRT_EOF
)
125 retval
= __MSVCRT_console_buffer
;
126 __MSVCRT_console_buffer
= MSVCRT_EOF
;
134 GetConsoleMode(MSVCRT_console_in
, &mode
);
136 SetConsoleMode(MSVCRT_console_in
, 0);
139 if (ReadConsoleInputA(MSVCRT_console_in
, &ir
, 1, &count
))
142 /* Only interested in ASCII chars */
143 if (ir
.EventType
== KEY_EVENT
&&
144 ir
.Event
.KeyEvent
.bKeyDown
)
146 if (ir
.Event
.KeyEvent
.uChar
.AsciiChar
)
148 retval
= ir
.Event
.KeyEvent
.uChar
.AsciiChar
;
151 for (i
= 0; i
< sizeof(enh_map
) / sizeof(enh_map
[0]); i
++)
153 if (ir
.Event
.KeyEvent
.wVirtualScanCode
== enh_map
[i
].vk
) break;
155 if (i
< sizeof(enh_map
) / sizeof(enh_map
[0]))
159 if (ir
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
161 else if (ir
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
) )
163 else if (ir
.Event
.KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
)
168 retval
= enh_map
[i
].ch
[idx
][0];
169 __MSVCRT_console_buffer
= enh_map
[i
].ch
[idx
][1];
172 WARN("Unmapped char keyState=%x vk=%x\n",
173 ir
.Event
.KeyEvent
.dwControlKeyState
, ir
.Event
.KeyEvent
.wVirtualScanCode
);
180 SetConsoleMode(MSVCRT_console_in
, mode
);
186 /*********************************************************************
189 int CDECL
_putch(int c
)
191 int retval
= MSVCRT_EOF
;
194 if (WriteConsoleA(MSVCRT_console_out
, &c
, 1, &count
, NULL
) && count
== 1)
200 /*********************************************************************
203 int CDECL
_getche(void)
208 if (retval
!= MSVCRT_EOF
)
209 retval
= _putch(retval
);
214 /*********************************************************************
217 char* CDECL
_cgets(char* str
)
223 TRACE("(%p)\n", str
);
224 str
[1] = 0; /* Length */
226 GetConsoleMode(MSVCRT_console_in
, &conmode
);
227 SetConsoleMode(MSVCRT_console_in
, ENABLE_LINE_INPUT
|ENABLE_ECHO_INPUT
|ENABLE_PROCESSED_INPUT
);
229 if(ReadConsoleA(MSVCRT_console_in
, buf
, str
[0], &got
, NULL
)) {
230 if(buf
[got
-2] == '\r') {
234 else if(got
== 1 && buf
[got
-1] == '\n') {
238 else if(got
== str
[0] && buf
[got
-1] == '\r') {
247 SetConsoleMode(MSVCRT_console_in
, conmode
);
252 /*********************************************************************
253 * _ungetch (MSVCRT.@)
255 int CDECL
_ungetch(int c
)
257 int retval
= MSVCRT_EOF
;
259 if (c
!= MSVCRT_EOF
&& __MSVCRT_console_buffer
== MSVCRT_EOF
)
260 retval
= __MSVCRT_console_buffer
= c
;
265 /*********************************************************************
268 int CDECL
_kbhit(void)
273 if (__MSVCRT_console_buffer
!= MSVCRT_EOF
)
277 /* FIXME: There has to be a faster way than this in Win32.. */
278 INPUT_RECORD
*ir
= NULL
;
281 GetNumberOfConsoleInputEvents(MSVCRT_console_in
, &count
);
283 if (count
&& (ir
= MSVCRT_malloc(count
* sizeof(INPUT_RECORD
))) &&
284 PeekConsoleInputA(MSVCRT_console_in
, ir
, count
, &count
))
285 for(i
= 0; i
< count
- 1; i
++)
287 if (ir
[i
].EventType
== KEY_EVENT
&&
288 ir
[i
].Event
.KeyEvent
.bKeyDown
&&
289 ir
[i
].Event
.KeyEvent
.uChar
.AsciiChar
)
302 /*********************************************************************
303 * _vcprintf (MSVCRT.@)
305 int CDECL
_vcprintf(const char* format
, __ms_va_list valist
)
308 LPWSTR formatW
= NULL
;
314 out
.buf
.A
= out
.grow
.A
= buf
;
316 out
.len
= sizeof(buf
);
318 sz
= MultiByteToWideChar( CP_ACP
, 0, format
, -1, NULL
, 0 );
319 formatW
= HeapAlloc( GetProcessHeap(), 0, sz
*sizeof(WCHAR
) );
320 MultiByteToWideChar( CP_ACP
, 0, format
, -1, formatW
, sz
);
322 if ((retval
= pf_vsnprintf( &out
, formatW
, NULL
, FALSE
, valist
)) > 0)
325 retval
= _cputs( out
.buf
.A
);
328 HeapFree( GetProcessHeap(), 0, formatW
);
329 if (out
.buf
.A
!= buf
)
330 MSVCRT_free (out
.buf
.A
);
334 /*********************************************************************
335 * _cprintf (MSVCRT.@)
337 int CDECL
_cprintf(const char* format
, ...)
342 __ms_va_start( valist
, format
);
343 retval
= _vcprintf(format
, valist
);
350 /*********************************************************************
351 * _vcwprintf (MSVCRT.@)
353 int CDECL
_vcwprintf(const MSVCRT_wchar_t
* format
, __ms_va_list valist
)
355 MSVCRT_wchar_t buf
[2048];
360 out
.buf
.W
= out
.grow
.W
= buf
;
362 out
.len
= sizeof(buf
) / sizeof(buf
[0]);
364 if ((retval
= pf_vsnprintf( &out
, format
, NULL
, FALSE
, valist
)) >= 0)
367 retval
= _cputws( out
.buf
.W
);
370 if (out
.buf
.W
!= buf
)
371 MSVCRT_free (out
.buf
.W
);
375 /*********************************************************************
376 * _cwprintf (MSVCRT.@)
378 int CDECL
_cwprintf(const MSVCRT_wchar_t
* format
, ...)
383 __ms_va_start( valist
, format
);
384 retval
= _vcwprintf(format
, valist
);