Remove useless FIXMEs since there is nothing to do in BeginScene and
[wine] / dlls / msvcrt / console.c
1 /*
2  * msvcrt.dll console functions
3  *
4  * Copyright 2000 Jon Griffiths
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
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
22  */
23 #include "msvcrt.h"
24 #include "wincon.h"
25
26 #include "msvcrt/conio.h"
27 #include "msvcrt/malloc.h"
28 #include "msvcrt/stdio.h"
29 #include "mtdll.h"
30
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
34
35
36
37 /* MT */
38 #define LOCK_CONSOLE   _mlock(_CONIO_LOCK)
39 #define UNLOCK_CONSOLE _munlock(_CONIO_LOCK)
40
41 static HANDLE MSVCRT_console_in = INVALID_HANDLE_VALUE;
42 static HANDLE MSVCRT_console_out= INVALID_HANDLE_VALUE;
43 static int __MSVCRT_console_buffer = MSVCRT_EOF;
44
45 /* INTERNAL: Initialise console handles */
46 void msvcrt_init_console(void)
47 {
48   TRACE(":Opening console handles\n");
49
50   MSVCRT_console_in = GetStdHandle(STD_INPUT_HANDLE);
51
52   /* FIXME: Should be initialised with:
53    * CreateFileA("CONIN$", GENERIC_READ, FILE_SHARE_READ,
54    * NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
55    */
56
57   MSVCRT_console_out= CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE,
58                                     NULL, OPEN_EXISTING, 0, (HANDLE)NULL);
59
60   if ((MSVCRT_console_in == INVALID_HANDLE_VALUE) ||
61       (MSVCRT_console_out== INVALID_HANDLE_VALUE))
62     WARN(":Console handle Initialisation FAILED!\n");
63 }
64
65 /* INTERNAL: Free console handles */
66 void msvcrt_free_console(void)
67 {
68   TRACE(":Closing console handles\n");
69   CloseHandle(MSVCRT_console_in);
70   CloseHandle(MSVCRT_console_out);
71 }
72
73 /*********************************************************************
74  *              _cputs (MSVCRT.@)
75  */
76 int _cputs(const char* str)
77 {
78   DWORD count;
79   int retval = MSVCRT_EOF;
80
81   LOCK_CONSOLE;
82   if (WriteConsoleA(MSVCRT_console_out, str, strlen(str), &count, NULL)
83       && count == 1)
84     retval = 0;
85   UNLOCK_CONSOLE;
86   return retval;
87 }
88
89 /*********************************************************************
90  *              _getch (MSVCRT.@)
91  */
92 int _getch(void)
93 {
94   int retval = MSVCRT_EOF;
95
96   LOCK_CONSOLE;
97   if (__MSVCRT_console_buffer != MSVCRT_EOF)
98   {
99     retval = __MSVCRT_console_buffer;
100     __MSVCRT_console_buffer = MSVCRT_EOF;
101   }
102   else
103   {
104     INPUT_RECORD ir;
105     DWORD count;
106     DWORD mode = 0;
107
108     GetConsoleMode(MSVCRT_console_in, &mode);
109     if(mode)
110       SetConsoleMode(MSVCRT_console_in, 0);
111
112     do {
113       if (ReadConsoleInputA(MSVCRT_console_in, &ir, 1, &count))
114       {
115         /* Only interested in ASCII chars */
116         if (ir.EventType == KEY_EVENT &&
117             ir.Event.KeyEvent.bKeyDown &&
118             ir.Event.KeyEvent.uChar.AsciiChar)
119         {
120           retval = ir.Event.KeyEvent.uChar.AsciiChar;
121           break;
122         }
123       }
124       else
125         break;
126     } while(1);
127     if (mode)
128       SetConsoleMode(MSVCRT_console_in, mode);
129   }
130   UNLOCK_CONSOLE;
131   return retval;
132 }
133
134 /*********************************************************************
135  *              _putch (MSVCRT.@)
136  */
137 int _putch(int c)
138 {
139   int retval = MSVCRT_EOF;
140   DWORD count;
141   LOCK_CONSOLE;
142   if (WriteConsoleA(MSVCRT_console_out, &c, 1, &count, NULL) && count == 1)
143     retval = c;
144   UNLOCK_CONSOLE;
145   return retval;
146 }
147
148 /*********************************************************************
149  *              _getche (MSVCRT.@)
150  */
151 int _getche(void)
152 {
153   int retval;
154   LOCK_CONSOLE;
155   retval = _getch();
156   if (retval != MSVCRT_EOF)
157     retval = _putch(retval);
158   UNLOCK_CONSOLE;
159   return retval;
160 }
161
162 /*********************************************************************
163  *              _cgets (MSVCRT.@)
164  */
165 char* _cgets(char* str)
166 {
167   char *buf = str + 2;
168   int c;
169   str[1] = 0; /* Length */
170   /* FIXME: No editing of string supported */
171   LOCK_CONSOLE;
172   do
173   {
174     if (str[1] >= str[0] || (str[1]++, c = _getche()) == MSVCRT_EOF || c == '\n')
175       break;
176     *buf++ = c & 0xff;
177   } while (1);
178   UNLOCK_CONSOLE;
179   *buf = '\0';
180   return str + 2;
181 }
182
183 /*********************************************************************
184  *              _ungetch (MSVCRT.@)
185  */
186 int _ungetch(int c)
187 {
188   int retval = MSVCRT_EOF;
189   LOCK_CONSOLE;
190   if (c != MSVCRT_EOF && __MSVCRT_console_buffer == MSVCRT_EOF)
191     retval = __MSVCRT_console_buffer = c;
192   UNLOCK_CONSOLE;
193   return retval;
194 }
195
196 /*********************************************************************
197  *              _kbhit (MSVCRT.@)
198  */
199 int _kbhit(void)
200 {
201   int retval = 0;
202
203   LOCK_CONSOLE;
204   if (__MSVCRT_console_buffer != MSVCRT_EOF)
205     retval = 1;
206   else
207   {
208     /* FIXME: There has to be a faster way than this in Win32.. */
209     INPUT_RECORD *ir = NULL;
210     DWORD count = 0, i;
211
212     GetNumberOfConsoleInputEvents(MSVCRT_console_in, &count);
213
214     if (count && (ir = MSVCRT_malloc(count * sizeof(INPUT_RECORD))) &&
215         PeekConsoleInputA(MSVCRT_console_in, ir, count, &count))
216       for(i = 0; i < count - 1; i++)
217       {
218         if (ir[i].EventType == KEY_EVENT &&
219             ir[i].Event.KeyEvent.bKeyDown &&
220             ir[i].Event.KeyEvent.uChar.AsciiChar)
221         {
222           retval = 1;
223           break;
224         }
225       }
226     if (ir)
227       MSVCRT_free(ir);
228   }
229   UNLOCK_CONSOLE;
230   return retval;
231 }
232
233
234 /*********************************************************************
235  *              _cprintf (MSVCRT.@)
236  */
237 int _cprintf(const char* format, ...)
238 {
239   char buf[2048], *mem = buf;
240   int written, resize = sizeof(buf), retval;
241   va_list valist;
242
243   va_start( valist, format );
244   /* There are two conventions for snprintf failing:
245    * Return -1 if we truncated, or
246    * Return the number of bytes that would have been written
247    * The code below handles both cases
248    */
249   while ((written = _snprintf( mem, resize, format, valist )) == -1 ||
250           written > resize)
251   {
252     resize = (written == -1 ? resize * 2 : written + 1);
253     if (mem != buf)
254       MSVCRT_free (mem);
255     if (!(mem = (char *)MSVCRT_malloc(resize)))
256       return MSVCRT_EOF;
257     va_start( valist, format );
258   }
259   va_end(valist);
260   LOCK_CONSOLE;
261   retval = _cputs( mem );
262   UNLOCK_CONSOLE;
263   if (mem != buf)
264     MSVCRT_free (mem);
265   return retval;
266 }