Use FileGetString instead of ReadFile, because ReadFile doesn't return a null termina...
[reactos.git] / reactos / subsys / system / cmd / console.c
1 /*
2 * CONSOLE.C - console input/output functions.
3 *
4 *
5 * History:
6 *
7 * 20-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
8 * started
9 *
10 * 03-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>)
11 * Remove all hardcode string to En.rc
12 *
13 * 01-Jul-2005 (Brandon Turner) <turnerb7@msu.edu>)
14 * Added ConPrintfPaging and ConOutPrintfPaging
15 */
16
17
18
19 #include <precomp.h>
20 #include "resource.h"
21
22
23 #define OUTPUT_BUFFER_SIZE 4096
24
25
26 UINT InputCodePage;
27 UINT OutputCodePage;
28
29
30 VOID ConInDisable (VOID)
31 {
32 HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
33 DWORD dwMode;
34
35 GetConsoleMode (hInput, &dwMode);
36 dwMode &= ~ENABLE_PROCESSED_INPUT;
37 SetConsoleMode (hInput, dwMode);
38 }
39
40
41 VOID ConInEnable (VOID)
42 {
43 HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
44 DWORD dwMode;
45
46 GetConsoleMode (hInput, &dwMode);
47 dwMode |= ENABLE_PROCESSED_INPUT;
48 SetConsoleMode (hInput, dwMode);
49 }
50
51
52 VOID ConInDummy (VOID)
53 {
54 HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
55 INPUT_RECORD dummy;
56 DWORD dwRead;
57
58 #ifdef _DEBUG
59 if (hInput == INVALID_HANDLE_VALUE)
60 DebugPrintf (_T("Invalid input handle!!!\n"));
61 #endif /* _DEBUG */
62 ReadConsoleInput (hInput, &dummy, 1, &dwRead);
63 }
64
65 VOID ConInFlush (VOID)
66 {
67 FlushConsoleInputBuffer (GetStdHandle (STD_INPUT_HANDLE));
68 }
69
70
71 VOID ConInKey (PINPUT_RECORD lpBuffer)
72 {
73 HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
74 DWORD dwRead;
75
76 #ifdef _DEBUG
77 if (hInput == INVALID_HANDLE_VALUE)
78 DebugPrintf (_T("Invalid input handle!!!\n"));
79 #endif /* _DEBUG */
80
81 do
82 {
83 ReadConsoleInput (hInput, lpBuffer, 1, &dwRead);
84 if ((lpBuffer->EventType == KEY_EVENT) &&
85 (lpBuffer->Event.KeyEvent.bKeyDown == TRUE))
86 break;
87 }
88 while (TRUE);
89 }
90
91
92
93 VOID ConInString (LPTSTR lpInput, DWORD dwLength)
94 {
95 DWORD dwOldMode;
96 DWORD dwRead;
97 HANDLE hFile;
98
99 LPTSTR p;
100 DWORD i;
101 PCHAR pBuf;
102
103 #ifdef _UNICODE
104 pBuf = (PCHAR)malloc(dwLength);
105 #else
106 pBuf = lpInput;
107 #endif
108 ZeroMemory (lpInput, dwLength * sizeof(TCHAR));
109 hFile = GetStdHandle (STD_INPUT_HANDLE);
110 GetConsoleMode (hFile, &dwOldMode);
111
112 SetConsoleMode (hFile, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
113
114 ReadFile (hFile, (PVOID)pBuf, dwLength, &dwRead, NULL);
115
116 #ifdef _UNICODE
117 MultiByteToWideChar( InputCodePage, 0, pBuf, dwLength + 1, lpInput, dwLength + 1);
118 #endif
119 p = lpInput;
120 for (i = 0; i < dwRead; i++, p++)
121 {
122 if (*p == _T('\x0d'))
123 {
124 *p = _T('\0');
125 break;
126 }
127 }
128
129 #ifdef _UNICODE
130 free(pBuf);
131 #endif
132
133 SetConsoleMode (hFile, dwOldMode);
134 }
135
136 static VOID ConChar(TCHAR c, DWORD nStdHandle)
137 {
138 DWORD dwWritten;
139 CHAR cc;
140 #ifdef _UNICODE
141 CHAR as[2];
142 WCHAR ws[2];
143 ws[0] = c;
144 ws[1] = 0;
145 WideCharToMultiByte( OutputCodePage, 0, ws, 2, as, 2, NULL, NULL);
146 cc = as[0];
147 #else
148 cc = c;
149 #endif
150 WriteFile (GetStdHandle (nStdHandle),
151 &cc,
152 1,
153 &dwWritten,
154 NULL);
155 }
156
157 VOID ConOutChar (TCHAR c)
158 {
159 ConChar(c, STD_OUTPUT_HANDLE);
160 }
161
162 VOID ConPuts(LPTSTR szText, DWORD nStdHandle)
163 {
164 DWORD dwWritten;
165 PCHAR pBuf;
166 INT len;
167
168 len = _tcslen(szText);
169 #ifdef _UNICODE
170 pBuf = malloc(len + 1);
171 len = WideCharToMultiByte( OutputCodePage, 0, szText, len + 1, pBuf, len + 1, NULL, NULL) - 1;
172 #else
173 pBuf = szText;
174 #endif
175 WriteFile (GetStdHandle (nStdHandle),
176 pBuf,
177 len,
178 &dwWritten,
179 NULL);
180 WriteFile (GetStdHandle (nStdHandle),
181 "\n",
182 1,
183 &dwWritten,
184 NULL);
185 #ifdef UNICODE
186 free(pBuf);
187 #endif
188 }
189
190 VOID ConOutResPaging(BOOL NewPage, UINT resID)
191 {
192 TCHAR szMsg[RC_STRING_MAX_SIZE];
193 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
194 ConOutPrintfPaging(NewPage, szMsg);
195 }
196
197 VOID ConOutResPuts (UINT resID)
198 {
199 TCHAR szMsg[RC_STRING_MAX_SIZE];
200 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
201
202 ConPuts(szMsg, STD_OUTPUT_HANDLE);
203 }
204
205 VOID ConOutPuts (LPTSTR szText)
206 {
207 ConPuts(szText, STD_OUTPUT_HANDLE);
208 }
209
210
211 VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
212 {
213 INT len;
214 PCHAR pBuf;
215 TCHAR szOut[OUTPUT_BUFFER_SIZE];
216 DWORD dwWritten;
217
218 len = _vstprintf (szOut, szFormat, arg_ptr);
219 #ifdef _UNICODE
220 pBuf = malloc(len + 1);
221 len = WideCharToMultiByte( OutputCodePage, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
222 #else
223 pBuf = szOut;
224 #endif
225
226 WriteFile (GetStdHandle (nStdHandle),
227 pBuf,
228 len,
229 &dwWritten,
230 NULL);
231
232
233 #ifdef UNICODE
234 free(pBuf);
235 #endif
236 }
237
238 VOID ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
239 {
240 INT len;
241 PCHAR pBuf;
242 CONSOLE_SCREEN_BUFFER_INFO csbi;
243 TCHAR szOut[OUTPUT_BUFFER_SIZE];
244 DWORD dwWritten;
245
246 /* used to count number of lines since last pause */
247 static int LineCount = 0;
248
249 /* used to see how big the screen is */
250 int ScreenLines = 0;
251
252 /* the number of chars in a roow */
253 int ScreenCol = 0;
254
255 /* chars since end of line */
256 int CharEL = 0;
257
258 int i = 0;
259
260 if(NewPage == TRUE)
261 LineCount = 0;
262
263 /* rest LineCount and return if no string have been given */
264 if (szFormat == NULL)
265 return;
266
267
268 //get the size of the visual screen that can be printed too
269 GetConsoleScreenBufferInfo(hConsole, &csbi);
270 //subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt()
271 ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top) - 4;
272 ScreenCol = (csbi.srWindow.Right - csbi.srWindow.Left) + 1;
273
274 //make sure they didnt make the screen to small
275 if(ScreenLines<4)
276 {
277 ConPrintf(szFormat, arg_ptr, nStdHandle);
278 return ;
279 }
280
281 len = _vstprintf (szOut, szFormat, arg_ptr);
282 #ifdef _UNICODE
283 pBuf = malloc(len + 1);
284 len = WideCharToMultiByte( OutputCodePage, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
285 #else
286 pBuf = szOut;
287 #endif
288
289 for(i = 0; i < len; i++)
290 {
291
292 if(szOut[i] == _T('\n'))
293 {
294 LineCount++;
295 CharEL=0;
296 }
297 else
298 {
299 CharEL++;
300 if (CharEL>=ScreenCol)
301 {
302 if (i+1<len)
303 {
304 if(szOut[i+1] != _T('\n')) LineCount++;
305 }
306 CharEL=0;
307 }
308 }
309
310 /* FIXME : write more that one char at time */
311 WriteFile (GetStdHandle (nStdHandle),&pBuf[i],sizeof(TCHAR),&dwWritten,NULL);
312 if(LineCount >= ScreenLines)
313 {
314 if(_tcsncicmp(&szOut[i],_T("\n"),2)!=0)
315 WriteFile (GetStdHandle (nStdHandle),_T("\n"),sizeof(TCHAR),&dwWritten,NULL);
316
317 if(PagePrompt() != PROMPT_YES)
318 {
319 return;
320 }
321 //reset the number of lines being printed
322 LineCount = 0;
323 CharEL=0;
324 }
325
326 }
327
328 #ifdef UNICODE
329 free(pBuf);
330 #endif
331 }
332
333 VOID ConErrFormatMessage (DWORD MessageId, ...)
334 {
335 TCHAR szMsg[RC_STRING_MAX_SIZE];
336 DWORD ret;
337 LPTSTR text;
338 va_list arg_ptr;
339
340 va_start (arg_ptr, MessageId);
341 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
342 NULL,
343 MessageId,
344 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
345 (LPTSTR) &text,
346 0,
347 &arg_ptr);
348
349 va_end (arg_ptr);
350 if(ret > 0)
351 {
352 ConErrPuts (text);
353 LocalFree(text);
354 }
355 else
356 {
357 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
358 ConErrPrintf(szMsg);
359 }
360 }
361
362 VOID ConOutFormatMessage (DWORD MessageId, ...)
363 {
364 TCHAR szMsg[RC_STRING_MAX_SIZE];
365 DWORD ret;
366 LPTSTR text;
367 va_list arg_ptr;
368
369 va_start (arg_ptr, MessageId);
370 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
371 NULL,
372 MessageId,
373 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
374 (LPTSTR) &text,
375 0,
376 &arg_ptr);
377
378 va_end (arg_ptr);
379 if(ret > 0)
380 {
381 ConErrPuts (text);
382 LocalFree(text);
383 }
384 else
385 {
386 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
387 ConErrPrintf(szMsg);
388 }
389 }
390
391 VOID ConOutPrintf (LPTSTR szFormat, ...)
392 {
393 va_list arg_ptr;
394
395 va_start (arg_ptr, szFormat);
396 ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
397 va_end (arg_ptr);
398 }
399
400 VOID ConOutPrintfPaging (BOOL NewPage, LPTSTR szFormat, ...)
401 {
402 va_list arg_ptr;
403
404 va_start (arg_ptr, szFormat);
405 ConPrintfPaging(NewPage, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
406 va_end (arg_ptr);
407 }
408
409 VOID ConErrChar (TCHAR c)
410 {
411 ConChar(c, STD_ERROR_HANDLE);
412 }
413
414
415 VOID ConErrResPuts (UINT resID)
416 {
417 TCHAR szMsg[RC_STRING_MAX_SIZE];
418 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
419 ConPuts(szMsg, STD_ERROR_HANDLE);
420 }
421
422 VOID ConErrPuts (LPTSTR szText)
423 {
424 ConPuts(szText, STD_ERROR_HANDLE);
425 }
426
427
428 VOID ConErrPrintf (LPTSTR szFormat, ...)
429 {
430 va_list arg_ptr;
431
432 va_start (arg_ptr, szFormat);
433 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
434 va_end (arg_ptr);
435 }
436
437 #ifdef _DEBUG
438 VOID DebugPrintf (LPTSTR szFormat, ...)
439 {
440 va_list arg_ptr;
441
442 va_start (arg_ptr, szFormat);
443 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
444 va_end (arg_ptr);
445 #if 0
446 TCHAR szOut[OUTPUT_BUFFER_SIZE];
447 va_start (arg_ptr, szFormat);
448 _vstprintf (szOut, szFormat, arg_ptr);
449 OutputDebugString (szOut);
450 va_end (arg_ptr);
451 #endif
452 }
453 #endif /* _DEBUG */
454
455 VOID SetCursorXY (SHORT x, SHORT y)
456 {
457 COORD coPos;
458
459 coPos.X = x;
460 coPos.Y = y;
461 SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
462 }
463
464
465 VOID GetCursorXY (PSHORT x, PSHORT y)
466 {
467 CONSOLE_SCREEN_BUFFER_INFO csbi;
468
469 GetConsoleScreenBufferInfo (hConsole, &csbi);
470
471 *x = csbi.dwCursorPosition.X;
472 *y = csbi.dwCursorPosition.Y;
473 }
474
475
476 SHORT GetCursorX (VOID)
477 {
478 CONSOLE_SCREEN_BUFFER_INFO csbi;
479
480 GetConsoleScreenBufferInfo (hConsole, &csbi);
481
482 return csbi.dwCursorPosition.X;
483 }
484
485
486 SHORT GetCursorY (VOID)
487 {
488 CONSOLE_SCREEN_BUFFER_INFO csbi;
489
490 GetConsoleScreenBufferInfo (hConsole, &csbi);
491
492 return csbi.dwCursorPosition.Y;
493 }
494
495
496 VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
497 {
498 CONSOLE_SCREEN_BUFFER_INFO csbi;
499
500 GetConsoleScreenBufferInfo (hConsole, &csbi);
501
502 if (maxx)
503 *maxx = csbi.dwSize.X;
504 if (maxy)
505 *maxy = csbi.dwSize.Y;
506 }
507
508
509 VOID SetCursorType (BOOL bInsert, BOOL bVisible)
510 {
511 CONSOLE_CURSOR_INFO cci;
512
513 cci.dwSize = bInsert ? 10 : 99;
514 cci.bVisible = bVisible;
515
516 SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
517 }
518
519 /* EOF */