- Remove hard-coded reference to cmdstart.bat and load it from registry (Software...
[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 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 VOID ConInString (LPTSTR lpInput, DWORD dwLength)
93 {
94 DWORD dwOldMode;
95 DWORD dwRead;
96 HANDLE hFile;
97
98 LPTSTR p;
99 DWORD i;
100 PCHAR pBuf;
101
102 #ifdef _UNICODE
103 pBuf = (PCHAR)cmd_alloc(dwLength);
104 #else
105 pBuf = lpInput;
106 #endif
107 ZeroMemory (lpInput, dwLength * sizeof(TCHAR));
108 hFile = GetStdHandle (STD_INPUT_HANDLE);
109 GetConsoleMode (hFile, &dwOldMode);
110
111 SetConsoleMode (hFile, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
112
113 ReadFile (hFile, (PVOID)pBuf, dwLength, &dwRead, NULL);
114
115 #ifdef _UNICODE
116 MultiByteToWideChar( InputCodePage, 0, pBuf, dwLength + 1, lpInput, dwLength + 1);
117 #endif
118 p = lpInput;
119 for (i = 0; i < dwRead; i++, p++)
120 {
121 if (*p == _T('\x0d'))
122 {
123 *p = _T('\0');
124 break;
125 }
126 }
127
128 #ifdef _UNICODE
129 cmd_free(pBuf);
130 #endif
131
132 SetConsoleMode (hFile, dwOldMode);
133 }
134
135 static VOID ConChar(TCHAR c, DWORD nStdHandle)
136 {
137 DWORD dwWritten;
138 CHAR cc;
139 #ifdef _UNICODE
140 CHAR as[2];
141 WCHAR ws[2];
142 ws[0] = c;
143 ws[1] = 0;
144 WideCharToMultiByte( OutputCodePage, 0, ws, 2, as, 2, NULL, NULL);
145 cc = as[0];
146 #else
147 cc = c;
148 #endif
149 WriteFile (GetStdHandle (nStdHandle),
150 &cc,
151 1,
152 &dwWritten,
153 NULL);
154 }
155
156 VOID ConOutChar (TCHAR c)
157 {
158 ConChar(c, STD_OUTPUT_HANDLE);
159 }
160
161 VOID ConPuts(LPTSTR szText, DWORD nStdHandle)
162 {
163 DWORD dwWritten;
164 PCHAR pBuf;
165 INT len;
166
167 len = _tcslen(szText);
168 #ifdef _UNICODE
169 pBuf = cmd_alloc(len + 1);
170 len = WideCharToMultiByte( OutputCodePage, 0, szText, len + 1, pBuf, len + 1, NULL, NULL) - 1;
171 #else
172 pBuf = szText;
173 #endif
174 WriteFile (GetStdHandle (nStdHandle),
175 pBuf,
176 len,
177 &dwWritten,
178 NULL);
179 WriteFile (GetStdHandle (nStdHandle),
180 _T("\n"),
181 1,
182 &dwWritten,
183 NULL);
184 #ifdef _UNICODE
185 cmd_free(pBuf);
186 #endif
187 }
188
189 VOID ConOutResPaging(BOOL NewPage, UINT resID)
190 {
191 TCHAR szMsg[RC_STRING_MAX_SIZE];
192 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
193 ConOutPrintfPaging(NewPage, szMsg);
194 }
195
196 VOID ConOutResPuts (UINT resID)
197 {
198 TCHAR szMsg[RC_STRING_MAX_SIZE];
199 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
200
201 ConPuts(szMsg, STD_OUTPUT_HANDLE);
202 }
203
204 VOID ConOutPuts (LPTSTR szText)
205 {
206 ConPuts(szText, STD_OUTPUT_HANDLE);
207 }
208
209
210 VOID ConPrintf(LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
211 {
212 INT len;
213 PCHAR pBuf;
214 TCHAR szOut[OUTPUT_BUFFER_SIZE];
215 DWORD dwWritten;
216
217 len = _vstprintf (szOut, szFormat, arg_ptr);
218 #ifdef _UNICODE
219 pBuf = cmd_alloc(len + 1);
220 len = WideCharToMultiByte( OutputCodePage, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
221 #else
222 pBuf = szOut;
223 #endif
224
225 WriteFile (GetStdHandle (nStdHandle),
226 pBuf,
227 len,
228 &dwWritten,
229 NULL);
230
231
232 #ifdef _UNICODE
233 cmd_free(pBuf);
234 #endif
235 }
236
237 INT ConPrintfPaging(BOOL NewPage, LPTSTR szFormat, va_list arg_ptr, DWORD nStdHandle)
238 {
239 INT len;
240 PCHAR pBuf;
241 CONSOLE_SCREEN_BUFFER_INFO csbi;
242 TCHAR szOut[OUTPUT_BUFFER_SIZE];
243 DWORD dwWritten;
244
245 /* used to count number of lines since last pause */
246 static int LineCount = 0;
247
248 /* used to see how big the screen is */
249 int ScreenLines = 0;
250
251 /* the number of chars in a roow */
252 int ScreenCol = 0;
253
254 /* chars since start of line */
255 int CharSL = 0;
256
257 int i = 0;
258
259 if(NewPage == TRUE)
260 LineCount = 0;
261
262 /* rest LineCount and return if no string have been given */
263 if (szFormat == NULL)
264 return 0;
265
266
267 //get the size of the visual screen that can be printed too
268 if (!GetConsoleScreenBufferInfo(hConsole, &csbi))
269 {
270 // we assuming its a file handle
271 ConPrintf(szFormat, arg_ptr, nStdHandle);
272 return 0;
273 }
274 //subtract 2 to account for "press any key..." and for the blank line at the end of PagePrompt()
275 ScreenLines = (csbi.srWindow.Bottom - csbi.srWindow.Top) - 4;
276 ScreenCol = (csbi.srWindow.Right - csbi.srWindow.Left) + 1;
277
278 //make sure they didnt make the screen to small
279 if(ScreenLines<4)
280 {
281 ConPrintf(szFormat, arg_ptr, nStdHandle);
282 return 0;
283 }
284
285 len = _vstprintf (szOut, szFormat, arg_ptr);
286 #ifdef _UNICODE
287 pBuf = cmd_alloc(len + 1);
288 len = WideCharToMultiByte( OutputCodePage, 0, szOut, len + 1, pBuf, len + 1, NULL, NULL) - 1;
289 #else
290 pBuf = szOut;
291 #endif
292
293 for(i = 0; i < len; i++)
294 {
295 // search 'end of string' '\n' or 'end of screen line'
296 for(; (i < len) && (pBuf[i] != _T('\n') && (CharSL<ScreenCol)) ; i++)
297 CharSL++;
298
299 WriteFile (GetStdHandle (nStdHandle),&pBuf[i-CharSL],sizeof(CHAR)*(CharSL+1),&dwWritten,NULL);
300 LineCount++;
301 CharSL=0;
302
303 if(LineCount >= ScreenLines)
304 {
305 if(_strnicmp(&pBuf[i], "\n", 2)!=0)
306 WriteFile (GetStdHandle (nStdHandle),_T("\n"),sizeof(CHAR),&dwWritten,NULL);
307
308 if(PagePrompt() != PROMPT_YES)
309 {
310 #ifdef _UNICODE
311 cmd_free(pBuf);
312 #endif
313 return 1;
314 }
315 //reset the number of lines being printed
316 LineCount = 0;
317 CharSL=0;
318 }
319
320 }
321
322 #ifdef _UNICODE
323 cmd_free(pBuf);
324 #endif
325 return 0;
326 }
327
328 VOID ConErrFormatMessage (DWORD MessageId, ...)
329 {
330 TCHAR szMsg[RC_STRING_MAX_SIZE];
331 DWORD ret;
332 LPTSTR text;
333 va_list arg_ptr;
334
335 va_start (arg_ptr, MessageId);
336 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
337 NULL,
338 MessageId,
339 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
340 (LPTSTR) &text,
341 0,
342 &arg_ptr);
343
344 va_end (arg_ptr);
345 if(ret > 0)
346 {
347 ConErrPuts (text);
348 LocalFree(text);
349 }
350 else
351 {
352 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
353 ConErrPrintf(szMsg);
354 }
355 }
356
357 VOID ConOutFormatMessage (DWORD MessageId, ...)
358 {
359 TCHAR szMsg[RC_STRING_MAX_SIZE];
360 DWORD ret;
361 LPTSTR text;
362 va_list arg_ptr;
363
364 va_start (arg_ptr, MessageId);
365 ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
366 NULL,
367 MessageId,
368 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
369 (LPTSTR) &text,
370 0,
371 &arg_ptr);
372
373 va_end (arg_ptr);
374 if(ret > 0)
375 {
376 ConErrPuts (text);
377 LocalFree(text);
378 }
379 else
380 {
381 LoadString(CMD_ModuleHandle, STRING_CONSOLE_ERROR, szMsg, RC_STRING_MAX_SIZE);
382 ConErrPrintf(szMsg);
383 }
384 }
385
386 VOID ConOutPrintf (LPTSTR szFormat, ...)
387 {
388 va_list arg_ptr;
389
390 va_start (arg_ptr, szFormat);
391 ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
392 va_end (arg_ptr);
393 }
394
395 INT ConOutPrintfPaging (BOOL NewPage, LPTSTR szFormat, ...)
396 {
397 INT iReturn;
398 va_list arg_ptr;
399
400 va_start (arg_ptr, szFormat);
401 iReturn = ConPrintfPaging(NewPage, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
402 va_end (arg_ptr);
403 return iReturn;
404 }
405
406 VOID ConErrChar (TCHAR c)
407 {
408 ConChar(c, STD_ERROR_HANDLE);
409 }
410
411
412 VOID ConErrResPuts (UINT resID)
413 {
414 TCHAR szMsg[RC_STRING_MAX_SIZE];
415 LoadString(CMD_ModuleHandle, resID, szMsg, RC_STRING_MAX_SIZE);
416 ConPuts(szMsg, STD_ERROR_HANDLE);
417 }
418
419 VOID ConErrPuts (LPTSTR szText)
420 {
421 ConPuts(szText, STD_ERROR_HANDLE);
422 }
423
424
425 VOID ConErrPrintf (LPTSTR szFormat, ...)
426 {
427 va_list arg_ptr;
428
429 va_start (arg_ptr, szFormat);
430 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
431 va_end (arg_ptr);
432 }
433
434 #ifdef _DEBUG
435 VOID DebugPrintf (LPTSTR szFormat, ...)
436 {
437 va_list arg_ptr;
438
439 va_start (arg_ptr, szFormat);
440 ConPrintf(szFormat, arg_ptr, STD_ERROR_HANDLE);
441 va_end (arg_ptr);
442 #if 0
443 TCHAR szOut[OUTPUT_BUFFER_SIZE];
444 va_start (arg_ptr, szFormat);
445 _vstprintf (szOut, szFormat, arg_ptr);
446 OutputDebugString (szOut);
447 va_end (arg_ptr);
448 #endif
449 }
450 #endif /* _DEBUG */
451
452 VOID SetCursorXY (SHORT x, SHORT y)
453 {
454 COORD coPos;
455
456 coPos.X = x;
457 coPos.Y = y;
458 SetConsoleCursorPosition (GetStdHandle (STD_OUTPUT_HANDLE), coPos);
459 }
460
461
462 VOID GetCursorXY (PSHORT x, PSHORT y)
463 {
464 CONSOLE_SCREEN_BUFFER_INFO csbi;
465
466 GetConsoleScreenBufferInfo (hConsole, &csbi);
467
468 *x = csbi.dwCursorPosition.X;
469 *y = csbi.dwCursorPosition.Y;
470 }
471
472
473 SHORT GetCursorX (VOID)
474 {
475 CONSOLE_SCREEN_BUFFER_INFO csbi;
476
477 GetConsoleScreenBufferInfo (hConsole, &csbi);
478
479 return csbi.dwCursorPosition.X;
480 }
481
482
483 SHORT GetCursorY (VOID)
484 {
485 CONSOLE_SCREEN_BUFFER_INFO csbi;
486
487 GetConsoleScreenBufferInfo (hConsole, &csbi);
488
489 return csbi.dwCursorPosition.Y;
490 }
491
492
493 VOID GetScreenSize (PSHORT maxx, PSHORT maxy)
494 {
495 CONSOLE_SCREEN_BUFFER_INFO csbi;
496
497 GetConsoleScreenBufferInfo (hConsole, &csbi);
498
499 if (maxx)
500 *maxx = csbi.dwSize.X;
501 if (maxy)
502 *maxy = csbi.dwSize.Y;
503 }
504
505
506 VOID SetCursorType (BOOL bInsert, BOOL bVisible)
507 {
508 CONSOLE_CURSOR_INFO cci;
509
510 cci.dwSize = bInsert ? 10 : 99;
511 cci.bVisible = bVisible;
512
513 SetConsoleCursorInfo (GetStdHandle (STD_OUTPUT_HANDLE), &cci);
514 }
515
516 /* EOF */