unicode build fixes
[reactos.git] / reactos / base / shell / 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 _T("\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 INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
239 {
240 INT len;
241 PTCHAR 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 0;
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 0;
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 0;
284 }
285
286 len = _vstprintf (szOut, szFormat, arg_ptr);
287 pBuf = szOut;
288
289 for(i = 0; i < len; i++)
290 {
291
292 if(pBuf[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(pBuf[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(CHAR),&dwWritten,NULL);
312 if(LineCount >= ScreenLines)
313 {
314 if(_tcsnicmp(&pBuf[i], _T("\n"), 2)!=0)
315 WriteFile (GetStdHandle (nStdHandle),_T("\n"),sizeof(CHAR),&dwWritten,NULL);
316
317 if(PagePrompt() != PROMPT_YES)
318 {
319 return 1;
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 return 0;
332 }
333
334 VOID ConErrFormatMessage (DWORD MessageId, ...)
335 {
336 TCHAR szMsg[RC_STRING_MAX_SIZE];
337 DWORD ret;
338 LPTSTR text;
339 va_list arg_ptr;
340
341 va_start (arg_ptr, MessageId);
342 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
343 NULL,
344 MessageId,
345 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
346 (LPTSTR) &text,
347 0,
348 &arg_ptr);
349
350 va_end (arg_ptr);
351 if(ret > 0)
352 {
353 ConErrPuts (text);
354 LocalFree(text);
355 }
356 else
357 {
358 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
359 ConErrPrintf(szMsg);
360 }
361 }
362
363 VOID ConOutFormatMessage (DWORD MessageId, ...)
364 {
365 TCHAR szMsg[RC_STRING_MAX_SIZE];
366 DWORD ret;
367 LPTSTR text;
368 va_list arg_ptr;
369
370 va_start (arg_ptr, MessageId);
371 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
372 NULL,
373 MessageId,
374 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
375 (LPTSTR) &text,
376 0,
377 &arg_ptr);
378
379 va_end (arg_ptr);
380 if(ret > 0)
381 {
382 ConErrPuts (text);
383 LocalFree(text);
384 }
385 else
386 {
387 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
388 ConErrPrintf(szMsg);
389 }
390 }
391
392 VOID ConOutPrintf (LPTSTR szFormat, ...)
393 {
394 va_list arg_ptr;
395
396 va_start (arg_ptr, szFormat);
397 ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
398 va_end (arg_ptr);
399 }
400
401 INT ConOutPrintfPaging (BOOL NewPage, LPTSTR szFormat, ...)
402 {
403 INT iReturn;
404 va_list arg_ptr;
405
406 va_start (arg_ptr, szFormat);
407 iReturn = ConPrintfPaging(NewPage, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
408 va_end (arg_ptr);
409 return iReturn;
410 }
411
412 VOID ConErrChar (TCHAR c)
413 {
414 ConChar(c, STD_ERROR_HANDLE);
415 }
416
417
418 VOID ConErrResPuts (UINT resID)
419 {
420 TCHAR szMsg[RC_STRING_MAX_SIZE];
421 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
422 ConPuts(szMsg, STD_ERROR_HANDLE);
423 }
424
425 VOID ConErrPuts (LPTSTR szText)
426 {
427 ConPuts(szText, STD_ERROR_HANDLE);
428 }
429
430
431 VOID ConErrPrintf (LPTSTR szFormat, ...)
432 {
433 va_list arg_ptr;
434
435 va_start (arg_ptr, szFormat);
436 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
437 va_end (arg_ptr);
438 }
439
440 #ifdef _DEBUG
441 VOID DebugPrintf (LPTSTR szFormat, ...)
442 {
443 va_list arg_ptr;
444
445 va_start (arg_ptr, szFormat);
446 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
447 va_end (arg_ptr);
448 #if 0
449 TCHAR szOut[OUTPUT_BUFFER_SIZE];
450 va_start (arg_ptr, szFormat);
451 _vstprintf (szOut, szFormat, arg_ptr);
452 OutputDebugString (szOut);
453 va_end (arg_ptr);
454 #endif
455 }
456 #endif /* _DEBUG */
457
458 VOID SetCursorXY (SHORT x, SHORT y)
459 {
460 COORD coPos;
461
462 coPos.X = x;
463 coPos.Y = y;
464 SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
465 }
466
467
468 VOID GetCursorXY (PSHORT x, PSHORT y)
469 {
470 CONSOLE_SCREEN_BUFFER_INFO csbi;
471
472 GetConsoleScreenBufferInfo (hConsole, &csbi);
473
474 *x = csbi.dwCursorPosition.X;
475 *y = csbi.dwCursorPosition.Y;
476 }
477
478
479 SHORT GetCursorX (VOID)
480 {
481 CONSOLE_SCREEN_BUFFER_INFO csbi;
482
483 GetConsoleScreenBufferInfo (hConsole, &csbi);
484
485 return csbi.dwCursorPosition.X;
486 }
487
488
489 SHORT GetCursorY (VOID)
490 {
491 CONSOLE_SCREEN_BUFFER_INFO csbi;
492
493 GetConsoleScreenBufferInfo (hConsole, &csbi);
494
495 return csbi.dwCursorPosition.Y;
496 }
497
498
499 VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
500 {
501 CONSOLE_SCREEN_BUFFER_INFO csbi;
502
503 GetConsoleScreenBufferInfo (hConsole, &csbi);
504
505 if (maxx)
506 *maxx = csbi.dwSize.X;
507 if (maxy)
508 *maxy = csbi.dwSize.Y;
509 }
510
511
512 VOID SetCursorType (BOOL bInsert, BOOL bVisible)
513 {
514 CONSOLE_CURSOR_INFO cci;
515
516 cci.dwSize = bInsert ? 10 : 99;
517 cci.bVisible = bVisible;
518
519 SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
520 }
521
522 /* EOF */