- npapi.h: Correct definitions of function pointer prototypes.
[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
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, NULL, NULL);
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 ConWrite(_T("\n"), 1, nStdHandle);
170 }
171
172 VOID ConOutResPaging(BOOL NewPage, UINT resID)
173 {
174 TCHAR szMsg[RC_STRING_MAX_SIZE];
175 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
176 ConOutPrintfPaging(NewPage, szMsg);
177 }
178
179 VOID ConOutResPuts (UINT resID)
180 {
181 TCHAR szMsg[RC_STRING_MAX_SIZE];
182 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
183
184 ConPuts(szMsg, STD_OUTPUT_HANDLE);
185 }
186
187 VOID ConOutPuts (LPTSTR szText)
188 {
189 ConPuts(szText, STD_OUTPUT_HANDLE);
190 }
191
192
193 VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
194 {
195 TCHAR szOut[OUTPUT_BUFFER_SIZE];
196 ConWrite(szOut, _vstprintf(szOut, szFormat, arg_ptr), nStdHandle);
197 }
198
199 INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
200 {
201 INT len;
202 CONSOLE_SCREEN_BUFFER_INFO csbi;
203 TCHAR szOut[OUTPUT_BUFFER_SIZE];
204 DWORD dwWritten;
205 HANDLE hOutput = GetStdHandle(nStdHandle);
206
207 /* used to count number of lines since last pause */
208 static int LineCount = 0;
209
210 /* used to see how big the screen is */
211 int ScreenLines = 0;
212
213 /* chars since start of line */
214 int CharSL;
215
216 int from = 0, i = 0;
217
218 if(NewPage == TRUE)
219 LineCount = 0;
220
221 /* rest LineCount and return if no string have been given */
222 if (szFormat == NULL)
223 return 0;
224
225
226 //get the size of the visual screen that can be printed too
227 if (!GetConsoleScreenBufferInfo(hOutput, &csbi))
228 {
229 // we assuming its a file handle
230 ConPrintf(szFormat, arg_ptr, nStdHandle);
231 return 0;
232 }
233 //subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt()
234 ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top) - 4;
235 CharSL = csbi.dwCursorPosition.X;
236
237 //make sure they didnt make the screen to small
238 if(ScreenLines<4)
239 {
240 ConPrintf(szFormat, arg_ptr, nStdHandle);
241 return 0;
242 }
243
244 len = _vstprintf (szOut, szFormat, arg_ptr);
245
246 while (i < len)
247 {
248 // Search until the end of a line is reached
249 if (szOut[i++] != _T('\n') && ++CharSL < csbi.dwSize.X)
250 continue;
251
252 LineCount++;
253 CharSL=0;
254
255 if(LineCount >= ScreenLines)
256 {
257 WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
258 from = i;
259
260 if(PagePrompt() != PROMPT_YES)
261 {
262 return 1;
263 }
264 //reset the number of lines being printed
265 LineCount = 0;
266 }
267 }
268
269 WriteConsole(hOutput, &szOut[from], i-from, &dwWritten, NULL);
270
271 return 0;
272 }
273
274 VOID ConErrFormatMessage (DWORD MessageId, ...)
275 {
276 TCHAR szMsg[RC_STRING_MAX_SIZE];
277 DWORD ret;
278 LPTSTR text;
279 va_list arg_ptr;
280
281 va_start (arg_ptr, MessageId);
282 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
283 NULL,
284 MessageId,
285 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
286 (LPTSTR) &text,
287 0,
288 &arg_ptr);
289
290 va_end (arg_ptr);
291 if(ret > 0)
292 {
293 ConErrPuts (text);
294 LocalFree(text);
295 }
296 else
297 {
298 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
299 ConErrPrintf(szMsg);
300 }
301 }
302
303 VOID ConOutFormatMessage (DWORD MessageId, ...)
304 {
305 TCHAR szMsg[RC_STRING_MAX_SIZE];
306 DWORD ret;
307 LPTSTR text;
308 va_list arg_ptr;
309
310 va_start (arg_ptr, MessageId);
311 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
312 NULL,
313 MessageId,
314 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
315 (LPTSTR) &text,
316 0,
317 &arg_ptr);
318
319 va_end (arg_ptr);
320 if(ret > 0)
321 {
322 ConErrPuts (text);
323 LocalFree(text);
324 }
325 else
326 {
327 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
328 ConErrPrintf(szMsg);
329 }
330 }
331
332 VOID ConOutResPrintf (UINT resID, ...)
333 {
334 TCHAR szMsg[RC_STRING_MAX_SIZE];
335 va_list arg_ptr;
336
337 va_start (arg_ptr, resID);
338 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
339 ConPrintf(szMsg, arg_ptr, STD_OUTPUT_HANDLE);
340 va_end (arg_ptr);
341 }
342
343 VOID ConOutPrintf (LPTSTR szFormat, ...)
344 {
345 va_list arg_ptr;
346
347 va_start (arg_ptr, szFormat);
348 ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
349 va_end (arg_ptr);
350 }
351
352 INT ConOutPrintfPaging (BOOL NewPage, LPTSTR szFormat, ...)
353 {
354 INT iReturn;
355 va_list arg_ptr;
356
357 va_start (arg_ptr, szFormat);
358 iReturn = ConPrintfPaging(NewPage, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
359 va_end (arg_ptr);
360 return iReturn;
361 }
362
363 VOID ConErrChar (TCHAR c)
364 {
365 ConWrite(&c, 1, STD_ERROR_HANDLE);
366 }
367
368
369 VOID ConErrResPuts (UINT resID)
370 {
371 TCHAR szMsg[RC_STRING_MAX_SIZE];
372 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
373 ConPuts(szMsg, STD_ERROR_HANDLE);
374 }
375
376 VOID ConErrPuts (LPTSTR szText)
377 {
378 ConPuts(szText, STD_ERROR_HANDLE);
379 }
380
381
382 VOID ConErrResPrintf (UINT resID, ...)
383 {
384 TCHAR szMsg[RC_STRING_MAX_SIZE];
385 va_list arg_ptr;
386
387 va_start (arg_ptr, resID);
388 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
389 ConPrintf(szMsg, arg_ptr, STD_ERROR_HANDLE);
390 va_end (arg_ptr);
391 }
392
393 VOID ConErrPrintf (LPTSTR szFormat, ...)
394 {
395 va_list arg_ptr;
396
397 va_start (arg_ptr, szFormat);
398 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
399 va_end (arg_ptr);
400 }
401
402 VOID SetCursorXY (SHORT x, SHORT y)
403 {
404 COORD coPos;
405
406 coPos.X = x;
407 coPos.Y = y;
408 SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
409 }
410
411
412 VOID GetCursorXY (PSHORT x, PSHORT y)
413 {
414 CONSOLE_SCREEN_BUFFER_INFO csbi;
415
416 GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
417
418 *x = csbi.dwCursorPosition.X;
419 *y = csbi.dwCursorPosition.Y;
420 }
421
422
423 SHORT GetCursorX (VOID)
424 {
425 CONSOLE_SCREEN_BUFFER_INFO csbi;
426
427 GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
428
429 return csbi.dwCursorPosition.X;
430 }
431
432
433 SHORT GetCursorY (VOID)
434 {
435 CONSOLE_SCREEN_BUFFER_INFO csbi;
436
437 GetConsoleScreenBufferInfo (GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
438
439 return csbi.dwCursorPosition.Y;
440 }
441
442
443 VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
444 {
445 CONSOLE_SCREEN_BUFFER_INFO csbi;
446
447 if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
448 {
449 csbi.dwSize.X = 80;
450 csbi.dwSize.Y = 25;
451 }
452
453 if (maxx)
454 *maxx = csbi.dwSize.X;
455 if (maxy)
456 *maxy = csbi.dwSize.Y;
457 }
458
459
460 VOID SetCursorType (BOOL bInsert, BOOL bVisible)
461 {
462 CONSOLE_CURSOR_INFO cci;
463
464 cci.dwSize = bInsert ? 10 : 99;
465 cci.bVisible = bVisible;
466
467 SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
468 }
469
470 /* EOF */