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