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