Updated years in version info.
[reactos.git] / rosapps / cmd / misc.c
1 /*
2 * MISC.C - misc. functions.
3 *
4 *
5 * History:
6 *
7 * 07/12/98 (Rob Lake)
8 * started
9 *
10 * 07/13/98 (Rob Lake)
11 * moved functions in here
12 *
13 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
14 * added config.h include
15 *
16 * 18-Dec-1998 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
17 * Changed split() to accept quoted arguments.
18 * Removed parse_firstarg().
19 *
20 * 23-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
21 * Fixed an ugly bug in split(). In rare cases (last character
22 * of the string is a space) it ignored the NULL character and
23 * tried to add the following to the argument list.
24 *
25 * 28-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
26 * FileGetString() seems to be working now.
27 *
28 * 06-Nov-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
29 * Added PagePrompt() and FilePrompt().
30 */
31
32 #include "config.h"
33
34 #include <windows.h>
35 #include <ctype.h>
36 #include <string.h>
37 #include <stdlib.h>
38 //#include <stdarg.h>
39 #include <stdio.h>
40 #include <tchar.h>
41
42 #include "cmd.h"
43
44
45 /*
46 * get a character out-of-band and honor Ctrl-Break characters
47 */
48 TCHAR cgetchar (VOID)
49 {
50 HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
51 INPUT_RECORD irBuffer;
52 DWORD dwRead;
53
54 do
55 {
56 ReadConsoleInput (hInput, &irBuffer, 1, &dwRead);
57 if ((irBuffer.EventType == KEY_EVENT) &&
58 (irBuffer.Event.KeyEvent.bKeyDown == TRUE))
59 {
60 if ((irBuffer.Event.KeyEvent.dwControlKeyState &
61 (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) &
62 (irBuffer.Event.KeyEvent.wVirtualKeyCode == 'C'))
63 bCtrlBreak = TRUE;
64
65 break;
66 }
67 }
68 while (TRUE);
69
70 #ifndef _UNICODE
71 return irBuffer.Event.KeyEvent.uChar.AsciiChar;
72 #else
73 return irBuffer.Event.KeyEvent.uChar.UnicodeChar;
74 #endif /* _UNICODE */
75 }
76
77
78 /*
79 * Check if Ctrl-Break was pressed during the last calls
80 */
81
82 BOOL CheckCtrlBreak (INT mode)
83 {
84 static BOOL bLeaveAll = FALSE; /* leave all batch files */
85 TCHAR c;
86
87 switch (mode)
88 {
89 case BREAK_OUTOFBATCH:
90 bLeaveAll = 0;
91 return FALSE;
92
93 case BREAK_BATCHFILE:
94 if (bLeaveAll)
95 return TRUE;
96
97 if (!bCtrlBreak)
98 return FALSE;
99
100 /* we need to be sure the string arrives on the screen! */
101 do
102 ConOutPuts (_T("\r\nCtrl-Break pressed. Cancel batch file? (Yes/No/All) "));
103 while (!_tcschr ("YNA\3", c = _totupper (cgetchar())) || !c);
104
105 ConOutPuts (_T("\r\n"));
106
107 if (c == _T('N'))
108 return bCtrlBreak = FALSE; /* ignore */
109
110 /* leave all batch files */
111 bLeaveAll = ((c == _T('A')) || (c == _T('\3')));
112 break;
113
114 case BREAK_INPUT:
115 if (!bCtrlBreak)
116 return FALSE;
117 break;
118 }
119
120 /* state processed */
121 bCtrlBreak = FALSE;
122 return TRUE;
123 }
124
125
126 /*
127 * split - splits a line up into separate arguments, deliminators
128 * are spaces and slashes ('/').
129 */
130
131 LPTSTR *split (LPTSTR s, LPINT args)
132 {
133 LPTSTR *arg;
134 LPTSTR *p;
135 LPTSTR start;
136 LPTSTR q;
137 INT ac;
138 INT len;
139 BOOL bQuoted = FALSE;
140
141 arg = malloc (sizeof (LPTSTR));
142 if (!arg)
143 return NULL;
144 *arg = NULL;
145
146 ac = 0;
147 while (*s)
148 {
149 /* skip leading spaces */
150 while (*s && (_istspace (*s) || _istcntrl (*s)))
151 ++s;
152
153 /* if quote (") then set bQuoted */
154 if (*s == _T('\"'))
155 {
156 ++s;
157 bQuoted = TRUE;
158 }
159
160 start = s;
161
162 /* the first character can be '/' */
163 if (*s == _T('/'))
164 ++s;
165
166 /* skip to next word delimiter or start of next option */
167 if (bQuoted)
168 {
169 while (_istprint (*s) && (*s != _T('\"')) && (*s != _T('/')))
170 ++s;
171 }
172 else
173 {
174 while (_istprint (*s) && !_istspace (*s) && (*s != _T('/')))
175 ++s;
176 }
177
178 /* a word was found */
179 if (s != start)
180 {
181 /* add new entry for new argument */
182 arg = realloc (p = arg, (ac + 2) * sizeof (LPTSTR));
183 if (!arg)
184 {
185 freep (p);
186 return NULL;
187 }
188
189 /* create new entry */
190 q = arg[ac] = malloc (((len = s - start) + 1) * sizeof (TCHAR));
191 arg[++ac] = NULL;
192 if (!q)
193 {
194 freep (arg);
195 return NULL;
196 }
197 memcpy (q, start, len * sizeof (TCHAR));
198 q[len] = _T('\0');
199 }
200
201 /* adjust string pointer if quoted (") */
202 if (bQuoted)
203 {
204 ++s;
205 bQuoted = FALSE;
206 }
207 }
208
209 *args = ac;
210
211 return arg;
212 }
213
214
215 /*
216 * freep -- frees memory used for a call to split
217 *
218 */
219 VOID freep (LPTSTR *p)
220 {
221 LPTSTR *q;
222
223 if (!p)
224 return;
225
226 q = p;
227 while (*q)
228 free(*q++);
229
230 free(p);
231 }
232
233
234 LPTSTR stpcpy (LPTSTR dest, LPTSTR src)
235 {
236 _tcscpy (dest, src);
237 return (dest + _tcslen (src));
238 }
239
240
241
242 /*
243 * Checks if a path is valid (accessible)
244 */
245
246 BOOL IsValidPathName (LPCTSTR pszPath)
247 {
248 TCHAR szOldPath[MAX_PATH];
249 BOOL bResult;
250
251 GetCurrentDirectory (MAX_PATH, szOldPath);
252 bResult = SetCurrentDirectory (pszPath);
253
254 SetCurrentDirectory (szOldPath);
255
256 return bResult;
257 }
258
259
260 /*
261 * Checks if a file exists (accessible)
262 */
263
264 BOOL IsValidFileName (LPCTSTR pszPath)
265 {
266 return (GetFileAttributes (pszPath) != 0xFFFFFFFF);
267 }
268
269
270 BOOL IsValidDirectory (LPCTSTR pszPath)
271 {
272 return (GetFileAttributes (pszPath) & FILE_ATTRIBUTE_DIRECTORY);
273 }
274
275
276 BOOL FileGetString (HANDLE hFile, LPTSTR lpBuffer, INT nBufferLength)
277 {
278 LPTSTR lpString;
279 TCHAR ch;
280 DWORD dwRead;
281
282 lpString = lpBuffer;
283
284 while ((--nBufferLength > 0) &&
285 ReadFile(hFile, &ch, 1, &dwRead, NULL) && dwRead)
286 {
287 if (ch == _T('\r'))
288 {
289 /* overread '\n' */
290 ReadFile (hFile, &ch, 1, &dwRead, NULL);
291 break;
292 }
293 *lpString++ = ch;
294 }
295
296 if (!dwRead && lpString == lpBuffer)
297 return FALSE;
298
299 *lpString++ = _T('\0');
300
301 return TRUE;
302 }
303
304 #ifndef __REACTOS__
305 /*
306 * GetConsoleWindow - returns the handle to the current console window
307 */
308 HWND GetConsoleWindow (VOID)
309 {
310 TCHAR original[256];
311 TCHAR temp[256];
312 HWND h=0;
313
314 if(h)
315 return h;
316
317 GetConsoleTitle (original, sizeof(original));
318
319 _tcscpy (temp, original);
320 _tcscat (temp, _T("-xxx "));
321
322 if (FindWindow (0, temp) == NULL )
323 {
324 SetConsoleTitle (temp);
325 Sleep (0);
326
327 while(!(h = FindWindow (0, temp)))
328 ;
329
330 SetConsoleTitle (original);
331 }
332
333 return h;
334 }
335 #endif
336
337
338 INT PagePrompt (VOID)
339 {
340 INPUT_RECORD ir;
341
342 ConOutPrintf ("Press a key to continue...\n");
343
344 RemoveBreakHandler ();
345 ConInDisable ();
346
347 do
348 {
349 ConInKey (&ir);
350 }
351 while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
352 (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
353 (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
354
355 AddBreakHandler ();
356 ConInEnable ();
357
358 if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
359 ((ir.Event.KeyEvent.wVirtualKeyCode == 'C') &&
360 (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
361 return PROMPT_BREAK;
362
363 return PROMPT_YES;
364 }
365
366
367 INT FilePromptYN (LPTSTR szFormat, ...)
368 {
369 TCHAR szOut[512];
370 va_list arg_ptr;
371 // TCHAR cKey = 0;
372 // LPTSTR szKeys = _T("yna");
373
374 TCHAR szIn[10];
375 LPTSTR p;
376
377 va_start (arg_ptr, szFormat);
378 _vstprintf (szOut, szFormat, arg_ptr);
379 va_end (arg_ptr);
380
381 ConOutPrintf (szFormat);
382
383 /* preliminary fix */
384 ConInString (szIn, 10);
385 ConOutPrintf (_T("\n"));
386
387 _tcsupr (szIn);
388 for (p = szIn; _istspace (*p); p++)
389 ;
390
391 if (*p == _T('Y'))
392 return PROMPT_YES;
393 else if (*p == _T('N'))
394 return PROMPT_NO;
395 #if 0
396 else if (*p == _T('\03'))
397 return PROMPT_BREAK;
398 #endif
399
400 return PROMPT_NO;
401
402
403 /* unfinished sollution */
404 #if 0
405 RemoveBreakHandler ();
406 ConInDisable ();
407
408 do
409 {
410 ConInKey (&ir);
411 cKey = _totlower (ir.Event.KeyEvent.uChar.AsciiChar);
412 if (_tcschr (szKeys, cKey[0]) == NULL)
413 cKey = 0;
414
415
416 }
417 while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
418 (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
419 (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
420
421 AddBreakHandler ();
422 ConInEnable ();
423
424 if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
425 ((ir.Event.KeyEvent.wVirtualKeyCode == 'C') &&
426 (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
427 return PROMPT_BREAK;
428
429 return PROMPT_YES;
430 #endif
431 }
432
433
434 INT FilePromptYNA (LPTSTR szFormat, ...)
435 {
436 TCHAR szOut[512];
437 va_list arg_ptr;
438 // TCHAR cKey = 0;
439 // LPTSTR szKeys = _T("yna");
440
441 TCHAR szIn[10];
442 LPTSTR p;
443
444 va_start (arg_ptr, szFormat);
445 _vstprintf (szOut, szFormat, arg_ptr);
446 va_end (arg_ptr);
447
448 ConOutPrintf (szFormat);
449
450 /* preliminary fix */
451 ConInString (szIn, 10);
452 ConOutPrintf (_T("\n"));
453
454 _tcsupr (szIn);
455 for (p = szIn; _istspace (*p); p++)
456 ;
457
458 if (*p == _T('Y'))
459 return PROMPT_YES;
460 else if (*p == _T('N'))
461 return PROMPT_NO;
462 if (*p == _T('A'))
463 return PROMPT_ALL;
464 #if 0
465 else if (*p == _T('\03'))
466 return PROMPT_BREAK;
467 #endif
468
469 return PROMPT_NO;
470
471
472 /* unfinished sollution */
473 #if 0
474 RemoveBreakHandler ();
475 ConInDisable ();
476
477 do
478 {
479 ConInKey (&ir);
480 cKey = _totlower (ir.Event.KeyEvent.uChar.AsciiChar);
481 if (_tcschr (szKeys, cKey[0]) == NULL)
482 cKey = 0;
483
484
485 }
486 while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
487 (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
488 (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
489
490 AddBreakHandler ();
491 ConInEnable ();
492
493 if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
494 ((ir.Event.KeyEvent.wVirtualKeyCode == 'C') &&
495 (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
496 return PROMPT_BREAK;
497
498 return PROMPT_YES;
499 #endif
500 }
501
502 /* EOF */