Synchronize up to trunk's revision r57689.
[reactos.git] / base / shell / cmd / console.c
1 /*
2 * CONSOLE.C - console input/output functions.
3 *
4 *
5 * History:
6 *
7 * 20-Jan-1999 (Eric Kohl)
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 * 02-Feb-2007 (Paolo Devoti) <devotip at gmail.com>)
17 * Fixed ConPrintfPaging
18 */
19
20 #include <precomp.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 ConInFlush (VOID)
53 {
54 FlushConsoleInputBuffer (GetStdHandle (STD_INPUT_HANDLE));
55 }
56
57
58 VOID ConInKey (PINPUT_RECORD lpBuffer)
59 {
60 HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
61 DWORD dwRead;
62
63 if (hInput == INVALID_HANDLE_VALUE)
64 WARN ("Invalid input handle!!!\n");
65
66 do
67 {
68 ReadConsoleInput (hInput, lpBuffer, 1, &dwRead);
69 if ((lpBuffer->EventType == KEY_EVENT) &&
70 (lpBuffer->Event.KeyEvent.bKeyDown == TRUE))
71 break;
72 }
73 while (TRUE);
74 }
75
76
77 VOID ConInString (LPTSTR lpInput, DWORD dwLength)
78 {
79 DWORD dwOldMode;
80 DWORD dwRead = 0;
81 HANDLE hFile;
82
83 LPTSTR p;
84 PCHAR pBuf;
85
86 #ifdef _UNICODE
87 pBuf = (PCHAR)cmd_alloc(dwLength - 1);
88 #else
89 pBuf = lpInput;
90 #endif
91 ZeroMemory (lpInput, dwLength * sizeof(TCHAR));
92 hFile = GetStdHandle (STD_INPUT_HANDLE);
93 GetConsoleMode (hFile, &dwOldMode);
94
95 SetConsoleMode (hFile, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
96
97 ReadFile (hFile, (PVOID)pBuf, dwLength - 1, &dwRead, NULL);
98
99 #ifdef _UNICODE
100 MultiByteToWideChar(InputCodePage, 0, pBuf, dwRead, lpInput, dwLength - 1);
101 cmd_free(pBuf);
102 #endif
103 for (p = lpInput; *p; p++)
104 {
105 if (*p == _T('\x0d'))
106 {
107 *p = _T('\0');
108 break;
109 }
110 }
111
112 SetConsoleMode (hFile, dwOldMode);
113 }
114
115 static VOID ConWrite(TCHAR *str, DWORD len, DWORD nStdHandle)
116 {
117 DWORD dwWritten;
118 HANDLE hOutput = GetStdHandle(nStdHandle);
119
120 if (WriteConsole(hOutput, str, len, &dwWritten, NULL))
121 return;
122
123 /* We're writing to a file or pipe instead of the console. Convert the
124 * string from TCHARs to the desired output format, if the two differ */
125 if (bUnicodeOutput)
126 {
127 #ifndef _UNICODE
128 WCHAR *buffer = cmd_alloc(len * sizeof(WCHAR));
129 if (!buffer)
130 {
131 error_out_of_memory();
132 return;
133 }
134 len = MultiByteToWideChar(OutputCodePage, 0, str, len, buffer, len);
135 str = (PVOID)buffer;
136 #endif
137 WriteFile(hOutput, str, len * sizeof(WCHAR), &dwWritten, NULL);
138 #ifndef _UNICODE
139 cmd_free(buffer);
140 #endif
141 }
142 else
143 {
144 #ifdef _UNICODE
145 CHAR *buffer = cmd_alloc(len * MB_LEN_MAX * sizeof(CHAR));
146 if (!buffer)
147 {
148 error_out_of_memory();
149 return;
150 }
151 len = WideCharToMultiByte(OutputCodePage, 0, str, len, buffer, len * MB_LEN_MAX, NULL, NULL);
152 str = (PVOID)buffer;
153 #endif
154 WriteFile(hOutput, str, len, &dwWritten, NULL);
155 #ifdef _UNICODE
156 cmd_free(buffer);
157 #endif
158 }
159 }
160
161 VOID ConOutChar (TCHAR c)
162 {
163 ConWrite(&c, 1, STD_OUTPUT_HANDLE);
164 }
165
166 VOID ConPuts(LPTSTR szText, DWORD nStdHandle)
167 {
168 ConWrite(szText, _tcslen(szText), nStdHandle);
169 }
170
171 VOID ConOutResPaging(BOOL NewPage, UINT resID)
172 {
173 TCHAR szMsg[RC_STRING_MAX_SIZE];
174 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
175 ConOutPrintfPaging(NewPage, szMsg);
176 }
177
178 VOID ConOutResPuts (UINT resID)
179 {
180 TCHAR szMsg[RC_STRING_MAX_SIZE];
181 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
182
183 ConPuts(szMsg, STD_OUTPUT_HANDLE);
184 }
185
186 VOID ConOutPuts (LPTSTR szText)
187 {
188 ConPuts(szText, STD_OUTPUT_HANDLE);
189 }
190
191
192 VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
193 {
194 TCHAR szOut[OUTPUT_BUFFER_SIZE];
195 ConWrite(szOut, _vstprintf(szOut, szFormat, arg_ptr), nStdHandle);
196 }
197
198 INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
199 {
200 INT len;
201 CONSOLE_SCREEN_BUFFER_INFO csbi;
202 TCHAR szOut[OUTPUT_BUFFER_SIZE];
203 DWORD dwWritten;
204 HANDLE hOutput = GetStdHandle(nStdHandle);
205
206 /* used to count number of lines since last pause */
207 static int LineCount = 0;
208
209 /* used to see how big the screen is */
210 int ScreenLines = 0;
211
212 /* chars since start of line */
213 int CharSL;
214
215 int from = 0, i = 0;
216
217 if(NewPage == TRUE)
218 LineCount = 0;
219
220 /* rest LineCount and return if no string have been given */
221 if (szFormat == NULL)
222 return 0;
223
224
225 //get the size of the visual screen that can be printed too
226 if (!GetConsoleScreenBufferInfo(hOutput, &csbi))
227 {
228 // we assuming its a file handle
229 ConPrintf(szFormat, arg_ptr, nStdHandle);
230 return 0;
231 }
232 //subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt()
233 ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top) - 4;
234 CharSL = csbi.dwCursorPosition.X;
235
236 //make sure they didnt make the screen to small
237 if(ScreenLines<4)
238 {
239 ConPrintf(szFormat, arg_ptr, nStdHandle);
240 return 0;
241 }
242
243 len = _vstprintf (szOut, szFormat, arg_ptr);
244
245 while (i < len)
246 {
247 // Search until the end of a line is reached
248 if (szOut[i++] != _T('\n') && ++CharSL < csbi.dwSize.X)
249 continue;
250
251 LineCount++;
252 CharSL=0;
253
254 if(LineCount >= ScreenLines)
255 {
256 WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
257 from = i;
258
259 if(PagePrompt() != PROMPT_YES)
260 {
261 return 1;
262 }
263 //reset the number of lines being printed
264 LineCount = 0;
265 }
266 }
267
268 WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
269
270 return 0;
271 }
272
273 VOID ConErrFormatMessage (DWORD MessageId, ...)
274 {
275 TCHAR szMsg[RC_STRING_MAX_SIZE];
276 DWORD ret;
277 LPTSTR text;
278 va_list arg_ptr;
279
280 va_start (arg_ptr, MessageId);
281 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
282 NULL,
283 MessageId,
284 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
285 (LPTSTR) &text,
286 0,
287 &arg_ptr);
288
289 va_end (arg_ptr);
290 if(ret > 0)
291 {
292 ConErrPuts (text);
293 LocalFree(text);
294 }
295 else
296 {
297 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
298 ConErrPrintf(szMsg);
299 }
300 }
301
302 VOID ConOutFormatMessage (DWORD MessageId, ...)
303 {
304 TCHAR szMsg[RC_STRING_MAX_SIZE];
305 DWORD ret;
306 LPTSTR text;
307 va_list arg_ptr;
308
309 va_start (arg_ptr, MessageId);
310 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
311 NULL,
312 MessageId,
313 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
314 (LPTSTR) &text,
315 0,
316 &arg_ptr);
317
318 va_end (arg_ptr);
319 if(ret > 0)
320 {
321 ConErrPuts (text);
322 LocalFree(text);
323 }
324 else
325 {
326 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
327 ConErrPrintf(szMsg);
328 }
329 }
330
331 VOID ConOutResPrintf (UINT resID, ...)
332 {
333 TCHAR szMsg[RC_STRING_MAX_SIZE];
334 va_list arg_ptr;
335
336 va_start (arg_ptr, resID);
337 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
338 ConPrintf(szMsg, arg_ptr, STD_OUTPUT_HANDLE);
339 va_end (arg_ptr);
340 }
341
342 VOID ConOutPrintf (LPTSTR szFormat, ...)
343 {
344 va_list arg_ptr;
345
346 va_start (arg_ptr, szFormat);
347 ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
348 va_end (arg_ptr);
349 }
350
351 INT ConOutPrintfPaging (BOOL NewPage, LPTSTR szFormat, ...)
352 {
353 INT iReturn;
354 va_list arg_ptr;
355
356 va_start (arg_ptr, szFormat);
357 iReturn = ConPrintfPaging(NewPage, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
358 va_end (arg_ptr);
359 return iReturn;
360 }
361
362 VOID ConErrChar (TCHAR c)
363 {
364 ConWrite(&c, 1, STD_ERROR_HANDLE);
365 }
366
367
368 VOID ConErrResPuts (UINT resID)
369 {
370 TCHAR szMsg[RC_STRING_MAX_SIZE];
371 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
372 ConPuts(szMsg, STD_ERROR_HANDLE);
373 }
374
375 VOID ConErrPuts (LPTSTR szText)
376 {
377 ConPuts(szText, STD_ERROR_HANDLE);
378 }
379
380
381 VOID ConErrResPrintf (UINT resID, ...)
382 {
383 TCHAR szMsg[RC_STRING_MAX_SIZE];
384 va_list arg_ptr;
385
386 va_start (arg_ptr, resID);
387 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
388 ConPrintf(szMsg, arg_ptr, STD_ERROR_HANDLE);
389 va_end (arg_ptr);
390 }
391
392 VOID ConErrPrintf (LPTSTR szFormat, ...)
393 {
394 va_list arg_ptr;
395
396 va_start (arg_ptr, szFormat);
397 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
398 va_end (arg_ptr);
399 }
400
401 VOID SetCursorXY (SHORT x, SHORT y)
402 {
403 COORD coPos;
404
405 coPos.X = x;
406 coPos.Y = y;
407 SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
408 }
409
410
411 VOID GetCursorXY (PSHORT x, PSHORT y)
412 {
413 CONSOLE_SCREEN_BUFFER_INFO csbi;
414
415 GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
416
417 *x = csbi.dwCursorPosition.X;
418 *y = csbi.dwCursorPosition.Y;
419 }
420
421
422 SHORT GetCursorX (VOID)
423 {
424 CONSOLE_SCREEN_BUFFER_INFO csbi;
425
426 GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
427
428 return csbi.dwCursorPosition.X;
429 }
430
431
432 SHORT GetCursorY (VOID)
433 {
434 CONSOLE_SCREEN_BUFFER_INFO csbi;
435
436 GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
437
438 return csbi.dwCursorPosition.Y;
439 }
440
441
442 VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
443 {
444 CONSOLE_SCREEN_BUFFER_INFO csbi;
445
446 if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
447 {
448 csbi.dwSize.X = 80;
449 csbi.dwSize.Y = 25;
450 }
451
452 if (maxx)
453 *maxx = csbi.dwSize.X;
454 if (maxy)
455 *maxy = csbi.dwSize.Y;
456 }
457
458
459 VOID SetCursorType (BOOL bInsert, BOOL bVisible)
460 {
461 CONSOLE_CURSOR_INFO cci;
462
463 cci.dwSize = bInsert ? 10 : 99;
464 cci.bVisible = bVisible;
465
466 SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
467 }
468
469 /* EOF */