2 * MISC.C - misc. functions.
11 * moved functions in here
13 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
14 * added config.h include
16 * 18-Dec-1998 (Eric Kohl)
17 * Changed split() to accept quoted arguments.
18 * Removed parse_firstarg().
20 * 23-Jan-1999 (Eric Kohl)
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.
25 * 28-Jan-1999 (Eric Kohl)
26 * FileGetString() seems to be working now.
28 * 06-Nov-1999 (Eric Kohl)
29 * Added PagePrompt() and FilePrompt().
31 * 30-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
32 * Remove all hardcoded strings in En.rc
38 * get a character out-of-band and honor Ctrl-Break characters
43 HANDLE hInput
= GetStdHandle (STD_INPUT_HANDLE
);
44 INPUT_RECORD irBuffer
;
49 ReadConsoleInput (hInput
, &irBuffer
, 1, &dwRead
);
50 if ((irBuffer
.EventType
== KEY_EVENT
) &&
51 (irBuffer
.Event
.KeyEvent
.bKeyDown
!= FALSE
))
53 if (irBuffer
.Event
.KeyEvent
.dwControlKeyState
&
54 (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
56 if (irBuffer
.Event
.KeyEvent
.wVirtualKeyCode
== 'C')
62 else if ((irBuffer
.Event
.KeyEvent
.wVirtualKeyCode
== VK_SHIFT
) ||
63 (irBuffer
.Event
.KeyEvent
.wVirtualKeyCode
== VK_MENU
) ||
64 (irBuffer
.Event
.KeyEvent
.wVirtualKeyCode
== VK_CONTROL
))
77 return irBuffer
.Event
.KeyEvent
.uChar
.AsciiChar
;
79 return irBuffer
.Event
.KeyEvent
.uChar
.UnicodeChar
;
84 * Takes a path in and returns it with the correct case of the letters
86 VOID
GetPathCase( TCHAR
* Path
, TCHAR
* OutPath
)
89 TCHAR TempPath
[MAX_PATH
];
90 WIN32_FIND_DATA FindFileData
;
92 _tcscpy(TempPath
, _T(""));
93 _tcscpy(OutPath
, _T(""));
95 for(i
= 0; i
< _tcslen(Path
); i
++)
97 if (Path
[i
] != _T('\\'))
99 _tcsncat(TempPath
, &Path
[i
], 1);
100 if (i
!= _tcslen(Path
) - 1)
103 /* Handle the base part of the path different.
104 Because if you put it into findfirstfile, it will
105 return your current folder */
106 if (_tcslen(TempPath
) == 2 && TempPath
[1] == _T(':'))
108 _tcscat(OutPath
, TempPath
);
109 _tcscat(OutPath
, _T("\\"));
110 _tcscat(TempPath
, _T("\\"));
114 hFind
= FindFirstFile(TempPath
,&FindFileData
);
115 if (hFind
== INVALID_HANDLE_VALUE
)
117 _tcscpy(OutPath
, Path
);
120 _tcscat(TempPath
, _T("\\"));
121 _tcscat(OutPath
, FindFileData
.cFileName
);
122 _tcscat(OutPath
, _T("\\"));
129 * Check if Ctrl-Break was pressed during the last calls
132 BOOL
CheckCtrlBreak(INT mode
)
134 static BOOL bLeaveAll
= FALSE
; /* leave all batch files */
135 TCHAR options
[4]; /* Yes, No, All */
140 case BREAK_OUTOFBATCH
:
144 case BREAK_BATCHFILE
:
152 LoadString(CMD_ModuleHandle
, STRING_COPY_OPTION
, options
, ARRAYSIZE(options
));
154 ConOutResPuts(STRING_CANCEL_BATCH_FILE
);
157 c
= _totupper(cgetchar());
158 } while (!(_tcschr(options
, c
) || c
== _T('\3')) || !c
);
160 ConOutChar(_T('\n'));
164 bCtrlBreak
= FALSE
; /* ignore */
168 /* leave all batch files */
169 bLeaveAll
= ((c
== options
[2]) || (c
== _T('\3')));
179 /* state processed */
183 /* add new entry for new argument */
184 BOOL
add_entry (LPINT ac
, LPTSTR
**arg
, LPCTSTR entry
)
189 q
= cmd_alloc ((_tcslen(entry
) + 1) * sizeof (TCHAR
));
192 WARN("Cannot allocate memory for q!\n");
198 *arg
= cmd_realloc (oldarg
, (*ac
+ 2) * sizeof (LPTSTR
));
201 WARN("Cannot reallocate memory for arg!\n");
209 (*arg
)[++(*ac
)] = NULL
;
214 static BOOL
expand (LPINT ac
, LPTSTR
**arg
, LPCTSTR pattern
)
217 WIN32_FIND_DATA FindData
;
220 LPTSTR dirpart
, fullname
;
222 pathend
= _tcsrchr (pattern
, _T('\\'));
225 dirpart
= cmd_alloc((pathend
- pattern
+ 2) * sizeof(TCHAR
));
228 WARN("Cannot allocate memory for dirpart!\n");
231 memcpy(dirpart
, pattern
, pathend
- pattern
+ 1);
232 dirpart
[pathend
- pattern
+ 1] = _T('\0');
238 hFind
= FindFirstFile (pattern
, &FindData
);
239 if (INVALID_HANDLE_VALUE
!= hFind
)
245 fullname
= cmd_alloc((_tcslen(dirpart
) + _tcslen(FindData
.cFileName
) + 1) * sizeof(TCHAR
));
248 WARN("Cannot allocate memory for fullname!\n");
253 _tcscat (_tcscpy (fullname
, dirpart
), FindData
.cFileName
);
254 ok
= add_entry(ac
, arg
, fullname
);
260 ok
= add_entry(ac
, arg
, FindData
.cFileName
);
262 } while (FindNextFile (hFind
, &FindData
) && ok
);
267 ok
= add_entry(ac
, arg
, pattern
);
279 * split - splits a line up into separate arguments, delimiters
280 * are spaces and slashes ('/').
282 LPTSTR
*split (LPTSTR s
, LPINT args
, BOOL expand_wildcards
, BOOL handle_plus
)
290 arg
= cmd_alloc (sizeof (LPTSTR
));
293 WARN("Cannot allocate memory for arg!\n");
301 BOOL bQuoted
= FALSE
;
303 /* skip leading spaces */
304 while (*s
&& (_istspace(*s
) || _istcntrl(*s
)))
309 /* the first character can be '/' */
313 /* skip to next word delimiter or start of next option */
314 while (_istprint(*s
))
316 /* if quote (") then set bQuoted */
317 bQuoted
^= (*s
== _T('\"'));
319 /* Check if we have unquoted text */
322 /* check for separators */
325 (handle_plus
&& (*s
== _T('+'))))
327 /* Make length at least one character */
336 /* a word was found */
339 q
= cmd_alloc (((len
= s
- start
) + 1) * sizeof (TCHAR
));
342 WARN("Cannot allocate memory for q!\n");
345 memcpy (q
, start
, len
* sizeof (TCHAR
));
348 if (expand_wildcards
&& (_T('/') != *start
) &&
349 (NULL
!= _tcschr(q
, _T('*')) || NULL
!= _tcschr(q
, _T('?'))))
351 if (! expand(&ac
, &arg
, q
))
360 if (! add_entry(&ac
, &arg
, q
))
377 * splitspace() is a function which uses JUST spaces as delimiters. split() uses "/" AND spaces.
378 * The way it works is real similar to split(), search the difference ;)
379 * splitspace is needed for commands such as "move" where paths as C:\this/is\allowed/ are allowed
381 LPTSTR
*splitspace (LPTSTR s
, LPINT args
)
389 arg
= cmd_alloc (sizeof (LPTSTR
));
392 WARN("Cannot allocate memory for arg!\n");
400 BOOL bQuoted
= FALSE
;
402 /* skip leading spaces */
403 while (*s
&& (_istspace (*s
) || _istcntrl (*s
)))
408 /* skip to next word delimiter or start of next option */
409 while (_istprint(*s
) && (bQuoted
|| !_istspace(*s
)))
411 /* if quote (") then set bQuoted */
412 bQuoted
^= (*s
== _T('\"'));
416 /* a word was found */
419 q
= cmd_alloc (((len
= s
- start
) + 1) * sizeof (TCHAR
));
422 WARN("Cannot allocate memory for q!\n");
425 memcpy (q
, start
, len
* sizeof (TCHAR
));
428 if (! add_entry(&ac
, &arg
, q
))
444 * freep -- frees memory used for a call to split
446 VOID
freep (LPTSTR
*p
)
460 LPTSTR
_stpcpy (LPTSTR dest
, LPCTSTR src
)
463 return (dest
+ _tcslen (src
));
467 StripQuotes(TCHAR
*in
)
480 * Checks if a path is valid (is accessible)
482 BOOL
IsValidPathName(IN LPCTSTR pszPath
)
485 TCHAR szOldPath
[MAX_PATH
];
487 GetCurrentDirectory(ARRAYSIZE(szOldPath
), szOldPath
);
488 bResult
= SetCurrentDirectory(pszPath
);
490 SetCurrentDirectory(szOldPath
);
496 * Checks if a file exists (is accessible)
498 BOOL
IsExistingFile(IN LPCTSTR pszPath
)
500 DWORD attr
= GetFileAttributes(pszPath
);
501 return ((attr
!= INVALID_FILE_ATTRIBUTES
) && !(attr
& FILE_ATTRIBUTE_DIRECTORY
));
504 BOOL
IsExistingDirectory(IN LPCTSTR pszPath
)
506 DWORD attr
= GetFileAttributes(pszPath
);
507 return ((attr
!= INVALID_FILE_ATTRIBUTES
) && (attr
& FILE_ATTRIBUTE_DIRECTORY
));
512 BOOL __stdcall
PagePrompt(PCON_PAGER Pager
, DWORD Done
, DWORD Total
)
514 SHORT iScreenWidth
, iCursorY
;
517 ConOutResPuts(STRING_MISC_HELP1
);
519 RemoveBreakHandler();
526 while ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_SHIFT
) ||
527 (ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_MENU
) ||
528 (ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_CONTROL
));
534 * Get the screen width, erase the full line where the cursor is,
535 * and move the cursor back to the beginning of the line.
537 GetScreenSize(&iScreenWidth
, NULL
);
538 iCursorY
= GetCursorY();
539 SetCursorXY(0, iCursorY
);
540 while (iScreenWidth
-- > 0) // Or call FillConsoleOutputCharacter ?
542 SetCursorXY(0, iCursorY
);
544 if ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) ||
545 ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== _T('C')) &&
546 (ir
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))))
548 /* We break, output a newline */
549 ConOutChar(_T('\n'));
559 INT
FilePromptYN (UINT resID
)
561 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
563 // LPTSTR szKeys = _T("yna");
569 ConOutResPrintf (resID
);
571 /* preliminary fix */
572 ConInString(szIn
, 10);
575 for (p
= szIn
; _istspace (*p
); p
++)
578 LoadString(CMD_ModuleHandle
, STRING_CHOICE_OPTION
, szMsg
, ARRAYSIZE(szMsg
));
580 if (_tcsncmp(p
, &szMsg
[0], 1) == 0)
582 else if (_tcsncmp(p
, &szMsg
[1], 1) == 0)
585 else if (*p
== _T('\03'))
591 /* unfinished solution */
593 RemoveBreakHandler();
599 cKey
= _totlower (ir
.Event
.KeyEvent
.uChar
.AsciiChar
);
600 if (_tcschr (szKeys
, cKey
[0]) == NULL
)
605 while ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_SHIFT
) ||
606 (ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_MENU
) ||
607 (ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_CONTROL
));
612 if ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) ||
613 ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== 'C') &&
614 (ir
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))))
622 INT
FilePromptYNA (UINT resID
)
624 TCHAR szMsg
[RC_STRING_MAX_SIZE
];
626 // LPTSTR szKeys = _T("yna");
632 ConOutResPrintf (resID
);
634 /* preliminary fix */
635 ConInString(szIn
, 10);
638 for (p
= szIn
; _istspace (*p
); p
++)
641 LoadString(CMD_ModuleHandle
, STRING_COPY_OPTION
, szMsg
, ARRAYSIZE(szMsg
));
643 if (_tcsncmp(p
, &szMsg
[0], 1) == 0)
645 else if (_tcsncmp(p
, &szMsg
[1], 1) == 0)
647 else if (_tcsncmp(p
, &szMsg
[2], 1) == 0)
650 else if (*p
== _T('\03'))
656 /* unfinished solution */
658 RemoveBreakHandler();
664 cKey
= _totlower (ir
.Event
.KeyEvent
.uChar
.AsciiChar
);
665 if (_tcschr (szKeys
, cKey
[0]) == NULL
)
668 while ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_SHIFT
) ||
669 (ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_MENU
) ||
670 (ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_CONTROL
));
675 if ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== VK_ESCAPE
) ||
676 ((ir
.Event
.KeyEvent
.wVirtualKeyCode
== _T('C')) &&
677 (ir
.Event
.KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))))