Made cmd unicode compatible.
[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 if (!GetConsoleScreenBufferInfo(hConsole, &csbi))
270 {
271 // we assuming its a file handle
272 ConPrintf(szFormat, arg_ptr, nStdHandle);
273 return;
274 }
275 //subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt()
276 ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top) - 4;
277 ScreenCol = (csbi.srWindow.Right - csbi.srWindow.Left) + 1;
278
279 //make sure they didnt make the screen to small
280 if(ScreenLines<4)
281 {
282 ConPrintf(szFormat, arg_ptr, nStdHandle);
283 return ;
284 }
285
286 len = _vstprintf (szOut, szFormat, arg_ptr);
287 #ifdef _UNICODE
288 pBuf = malloc(len + 1);
289 len = WideCharToMultiByte( OutputCodePage, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
290 #else
291 pBuf = szOut;
292 #endif
293
294 for(i = 0; i < len; i++)
295 {
296
297 if(pBuf[i] == '\n')
298 {
299 LineCount++;
300 CharEL=0;
301 }
302 else
303 {
304 CharEL++;
305 if (CharEL>=ScreenCol)
306 {
307 if (i+1<len)
308 {
309 if(pBuf[i+1] != '\n') LineCount++;
310 }
311 CharEL=0;
312 }
313 }
314
315 /* FIXME : write more that one char at time */
316 WriteFile (GetStdHandle (nStdHandle),&pBuf[i],sizeof(CHAR),&dwWritten,NULL);
317 if(LineCount >= ScreenLines)
318 {
319 if(strnicmp(&pBuf[i], "\n", 2)!=0)
320 WriteFile (GetStdHandle (nStdHandle),"\n",sizeof(CHAR),&dwWritten,NULL);
321
322 if(PagePrompt() != PROMPT_YES)
323 {
324 return;
325 }
326 //reset the number of lines being printed
327 LineCount = 0;
328 CharEL=0;
329 }
330
331 }
332
333 #ifdef UNICODE
334 free(pBuf);
335 #endif
336 }
337
338 VOID ConErrFormatMessage (DWORD MessageId, ...)
339 {
340 TCHAR szMsg[RC_STRING_MAX_SIZE];
341 DWORD ret;
342 LPTSTR text;
343 va_list arg_ptr;
344
345 va_start (arg_ptr, MessageId);
346 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
347 NULL,
348 MessageId,
349 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
350 (LPTSTR) &text,
351 0,
352 &arg_ptr);
353
354 va_end (arg_ptr);
355 if(ret > 0)
356 {
357 ConErrPuts (text);
358 LocalFree(text);
359 }
360 else
361 {
362 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
363 ConErrPrintf(szMsg);
364 }
365 }
366
367 VOID ConOutFormatMessage (DWORD MessageId, ...)
368 {
369 TCHAR szMsg[RC_STRING_MAX_SIZE];
370 DWORD ret;
371 LPTSTR text;
372 va_list arg_ptr;
373
374 va_start (arg_ptr, MessageId);
375 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
376 NULL,
377 MessageId,
378 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
379 (LPTSTR) &text,
380 0,
381 &arg_ptr);
382
383 va_end (arg_ptr);
384 if(ret > 0)
385 {
386 ConErrPuts (text);
387 LocalFree(text);
388 }
389 else
390 {
391 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
392 ConErrPrintf(szMsg);
393 }
394 }
395
396 VOID ConOutPrintf (LPTSTR szFormat, ...)
397 {
398 va_list arg_ptr;
399
400 va_start (arg_ptr, szFormat);
401 ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
402 va_end (arg_ptr);
403 }
404
405 VOID ConOutPrintfPaging (BOOL NewPage, LPTSTR szFormat, ...)
406 {
407 va_list arg_ptr;
408
409 va_start (arg_ptr, szFormat);
410 ConPrintfPaging(NewPage, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
411 va_end (arg_ptr);
412 }
413
414 VOID ConErrChar (TCHAR c)
415 {
416 ConChar(c, STD_ERROR_HANDLE);
417 }
418
419
420 VOID ConErrResPuts (UINT resID)
421 {
422 TCHAR szMsg[RC_STRING_MAX_SIZE];
423 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
424 ConPuts(szMsg, STD_ERROR_HANDLE);
425 }
426
427 VOID ConErrPuts (LPTSTR szText)
428 {
429 ConPuts(szText, STD_ERROR_HANDLE);
430 }
431
432
433 VOID ConErrPrintf (LPTSTR szFormat, ...)
434 {
435 va_list arg_ptr;
436
437 va_start (arg_ptr, szFormat);
438 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
439 va_end (arg_ptr);
440 }
441
442 #ifdef _DEBUG
443 VOID DebugPrintf (LPTSTR szFormat, ...)
444 {
445 va_list arg_ptr;
446
447 va_start (arg_ptr, szFormat);
448 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
449 va_end (arg_ptr);
450 #if 0
451 TCHAR szOut[OUTPUT_BUFFER_SIZE];
452 va_start (arg_ptr, szFormat);
453 _vstprintf (szOut, szFormat, arg_ptr);
454 OutputDebugString (szOut);
455 va_end (arg_ptr);
456 #endif
457 }
458 #endif /* _DEBUG */
459
460 VOID SetCursorXY (SHORT x, SHORT y)
461 {
462 COORD coPos;
463
464 coPos.X = x;
465 coPos.Y = y;
466 SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
467 }
468
469
470 VOID GetCursorXY (PSHORT x, PSHORT y)
471 {
472 CONSOLE_SCREEN_BUFFER_INFO csbi;
473
474 GetConsoleScreenBufferInfo (hConsole, &csbi);
475
476 *x = csbi.dwCursorPosition.X;
477 *y = csbi.dwCursorPosition.Y;
478 }
479
480
481 SHORT GetCursorX (VOID)
482 {
483 CONSOLE_SCREEN_BUFFER_INFO csbi;
484
485 GetConsoleScreenBufferInfo (hConsole, &csbi);
486
487 return csbi.dwCursorPosition.X;
488 }
489
490
491 SHORT GetCursorY (VOID)
492 {
493 CONSOLE_SCREEN_BUFFER_INFO csbi;
494
495 GetConsoleScreenBufferInfo (hConsole, &csbi);
496
497 return csbi.dwCursorPosition.Y;
498 }
499
500
501 VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
502 {
503 CONSOLE_SCREEN_BUFFER_INFO csbi;
504
505 GetConsoleScreenBufferInfo (hConsole, &csbi);
506
507 if (maxx)
508 *maxx = csbi.dwSize.X;
509 if (maxy)
510 *maxy = csbi.dwSize.Y;
511 }
512
513
514 VOID SetCursorType (BOOL bInsert, BOOL bVisible)
515 {
516 CONSOLE_CURSOR_INFO cci;
517
518 cci.dwSize = bInsert ? 10 : 99;
519 cci.bVisible = bVisible;
520
521 SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
522 }
523
524 /* EOF */