|
|
/*++
Copyright (c) 1993-1995 Microsoft Corporation
Module Name:
nwconv.c
Abstract:
Author:
Arthur Hanson (arth) 27-Jul-1994
Revision History:
--*/
#include "globals.h"
LPTSTR alpsz[TOTAL_STRINGS]; // String resource array cache.
static UINT cswitch = 0; static HCURSOR hCursor;
/////////////////////////////////////////////////////////////////////////
LPTSTR Lids( WORD idsStr )
/*++
Routine Description:
Returns the requested string from the string table. Caches the strings in an internal buffer. Will return a NULL string if the string can't be loaded.
Arguments:
Return Value:
--*/
{ WORD idsString; static TCHAR szEmpty[] = TEXT(""); TCHAR Buffer[MAX_STRING_SIZE];
WORD nLen; LPTSTR lpsz;
idsString = idsStr - IDS_STRINGBASE; if ((idsString == 0) ||( idsString > TOTAL_STRINGS)) return(szEmpty);
// -1 index as table is 0 based and 0 is not a valid string ID.
if (alpsz[idsString-1]) return((LPTSTR)alpsz[idsString-1]);
if (!(nLen = (WORD) LoadString(hInst, idsStr, (LPTSTR) Buffer, MAX_STRING_SIZE))) return(szEmpty);
if (!(lpsz = AllocMemory((nLen+1) * sizeof(TCHAR)))) return(szEmpty);
lstrcpy((LPTSTR)lpsz, (LPTSTR) Buffer);
return (alpsz[idsString-1] = lpsz); } // Lids
/////////////////////////////////////////////////////////////////////////
VOID StringTableDestroy()
/*++
Routine Description:
Frees up all the memory allocated in the string table.
Arguments:
Return Value:
--*/
{ int i;
for (i=0; i < TOTAL_STRINGS ; i++ ) { if (alpsz[i]) { FreeMemory(alpsz[i]); alpsz[i]=NULL; } } } // StringTableDestroy
/////////////////////////////////////////////////////////////////////////
VOID CursorHourGlass()
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ if (!cswitch) { hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT)); ShowCursor(TRUE); }
cswitch++;
} // CursorHourGlass
/////////////////////////////////////////////////////////////////////////
VOID CursorNormal()
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
if (cswitch == 0) return;
cswitch--;
if (!cswitch) { ShowCursor(FALSE); SetCursor(hCursor); }
} // Cursor Normal
/////////////////////////////////////////////////////////////////////////
BOOL BitTest( int Bit, BYTE *Bits )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ int i, j;
i = Bit / 8; j = Bit % 8;
if ((Bits[i] >> j) & 0x01) return TRUE; else return FALSE;
} // BitTest
/////////////////////////////////////////////////////////////////////////
BOOL CenterWindow( HWND hwndChild, HWND hwndParent )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ RECT rChild, rParent; int wChild, hChild, wParent, hParent; int wScreen, hScreen, xNew, yNew; HDC hdc;
// Get the Height and Width of the child window
GetWindowRect (hwndChild, &rChild); wChild = rChild.right - rChild.left; hChild = rChild.bottom - rChild.top;
// Get the Height and Width of the parent window
GetWindowRect (hwndParent, &rParent); wParent = rParent.right - rParent.left; hParent = rParent.bottom - rParent.top;
// Get the display limits
hdc = GetDC (hwndChild); wScreen = GetDeviceCaps (hdc, HORZRES); hScreen = GetDeviceCaps (hdc, VERTRES); ReleaseDC (hwndChild, hdc);
// Calculate new X position, then adjust for screen
xNew = rParent.left + ((wParent - wChild) /2); if (xNew < 0) xNew = 0; else if ((xNew+wChild) > wScreen) xNew = wScreen - wChild;
// Calculate new Y position, then adjust for screen
yNew = rParent.top + ((hParent - hChild) /2); if (yNew < 0) yNew = 0; else if ((yNew+hChild) > hScreen) yNew = hScreen - hChild;
// Set it, and return
return SetWindowPos (hwndChild, NULL, xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
} // CenterWindow
/////////////////////////////////////////////////////////////////////////
TCHAR * lstrchr( LPTSTR String, TCHAR c )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ TCHAR *ptrChar = String; BOOL Found = FALSE;
while(*ptrChar && !Found) { if (*ptrChar == c) Found = TRUE; else ptrChar++; }
if (Found) return ptrChar; else return NULL;
} // lstrchr
/////////////////////////////////////////////////////////////////////////
BOOL IsPath( LPTSTR Path )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ ULONG len; LPTSTR ptr;
len = lstrlen(Path); if (len < 2) // must have a slash and character
return FALSE;
// now know path is at least 2 characters long
ptr = Path;
// if slash anywhere then it has to be a path
while (*ptr) if (*ptr == TEXT('\\')) return TRUE; else ptr++;
// no slash - unless this is a drive then it aint no path.
if (Path[1] == TEXT(':')) return TRUE;
return FALSE;
} // IsPath
/////////////////////////////////////////////////////////////////////////
LPTSTR lToStr( ULONG Number )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static TCHAR String[15]; TCHAR tString[15]; LPTSTR sptr, dptr; ULONG Count;
sptr = String; dptr = tString; wsprintf(tString, TEXT("%lu"), Number); Count = lstrlen(tString);
*sptr++ = *dptr++; Count--;
while (*dptr) { if (!(Count % 3)) *sptr++ = TEXT(',');
*sptr++ = *dptr++; Count--; } *sptr = TEXT('\0');
return String; } // lToStr;
/////////////////////////////////////////////////////////////////////////
LPTSTR TimeToStr( ULONG TotTime )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static TCHAR String[10]; ULONG Hours, Minutes, Seconds;
Hours = TotTime / 3600; TotTime -= (Hours * 3600); Minutes = TotTime / 60; Seconds = TotTime - (Minutes * 60);
wsprintf(String, TEXT("%3lu:%2lu:%2lu"), Hours, Minutes, Seconds);
return String; } // TimeToStr;
/////////////////////////////////////////////////////////////////////////
LPTSTR DateToStr( ULONG TotTime )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ static TCHAR String[10]; ULONG Hours, Minutes, Seconds;
Hours = TotTime / 3600; TotTime -= (Hours * 3600); Minutes = TotTime / 60; Seconds = TotTime - (Minutes * 60);
wsprintf(String, TEXT("%3lu:%2lu:%2lu"), Hours, Minutes, Seconds);
return String; } // DateToStr;
/*+-----------------------------------------------------------------------+
| Took the _splitpath and _makepath routines and converted them to | | be NT (long file name) and Unicode friendly. | +-----------------------------------------------------------------------+*/
/////////////////////////////////////////////////////////////////////////
VOID lsplitpath( const TCHAR *path, TCHAR *drive, TCHAR *dir, TCHAR *fname, TCHAR *ext )
/*++
Routine Description:
Splits a path name into its individual components
Arguments:
path - pointer to path name to be parsed drive - pointer to buffer for drive component, if any dir - pointer to buffer for subdirectory component, if any fname - pointer to buffer for file base name component, if any ext - pointer to buffer for file name extension component, if any
Return Value:
drive - pointer to drive string. Includes ':' if a drive was given. dir - pointer to subdirectory string. Includes leading and trailing '/' or '\', if any. fname - pointer to file base name ext - pointer to file extension, if any. Includes leading '.'.
--*/
{ TCHAR *p; TCHAR *last_slash = NULL, *dot = NULL; unsigned len;
// init these so we don't exit with bogus values
drive[0] = TEXT('\0'); dir[0] = TEXT('\0'); fname[0] = TEXT('\0'); ext[0] = TEXT('\0');
if (path[0] == TEXT('\0')) return;
/*+---------------------------------------------------------------------+
| Assume that the path argument has the following form, where any or | | all of the components may be missing. | | | | <drive><dir><fname><ext> | | | | drive: | | 0 to MAX_DRIVE-1 characters, the last of which, if any, is a | | ':' or a '\' in the case of a UNC path. | | dir: | | 0 to _MAX_DIR-1 characters in the form of an absolute path | | (leading '/' or '\') or relative path, the last of which, if | | any, must be a '/' or '\'. E.g - | | | | absolute path: | | \top\next\last\ ; or | | /top/next/last/ | | relative path: | | top\next\last\ ; or | | top/next/last/ | | Mixed use of '/' and '\' within a path is also tolerated | | fname: | | 0 to _MAX_FNAME-1 characters not including the '.' character | | ext: | | 0 to _MAX_EXT-1 characters where, if any, the first must be a | | '.' | +---------------------------------------------------------------------+*/
// extract drive letter and :, if any
if ( path[0] && (path[1] == TEXT(':')) ) { if (drive) { drive[0] = path[0]; drive[1] = path[1]; drive[2] = TEXT('\0'); } path += 2; }
// if no drive then check for UNC pathname
if (drive[0] == TEXT('\0')) if ((path[0] == TEXT('\\')) && (path[1] == TEXT('\\'))) { // got a UNC path so put server-sharename into drive
drive[0] = path[0]; drive[1] = path[1]; path += 2;
p = &drive[2]; while ((*path != TEXT('\0')) && (*path != TEXT('\\'))) *p++ = *path++;
if (*path == TEXT('\0')) return;
// now sitting at the share - copy this as well (copy slash first)
*p++ = *path++; while ((*path != TEXT('\0')) && (*path != TEXT('\\'))) *p++ = *path++;
// tack on terminating NULL
*p = TEXT('\0'); }
/*+---------------------------------------------------------------------+
| extract path string, if any. Path now points to the first character| | of the path, if any, or the filename or extension, if no path was | | specified. Scan ahead for the last occurence, if any, of a '/' or | | '\' path separator character. If none is found, there is no path. | | We will also note the last '.' character found, if any, to aid in | | handling the extension. | +---------------------------------------------------------------------+*/
for (last_slash = NULL, p = (TCHAR *)path; *p; p++) { if (*p == TEXT('/') || *p == TEXT('\\')) // point to one beyond for later copy
last_slash = p + 1; else if (*p == TEXT('.')) dot = p; }
if (last_slash) {
// found a path - copy up through last_slash or max. characters allowed,
// whichever is smaller
if (dir) { len = (USHORT) __min((last_slash - path), (_MAX_DIR - 1)); lstrcpyn(dir, path, len + 1); dir[len] = TEXT('\0'); } path = last_slash; }
/*+---------------------------------------------------------------------+
| extract file name and extension, if any. Path now points to the | | first character of the file name, if any, or the extension if no | | file name was given. Dot points to the '.' beginning the extension,| | if any. | +---------------------------------------------------------------------+*/
if (dot && (dot >= path)) { // found the marker for an extension - copy the file name up to the
// '.'.
if (fname) { len = (USHORT) __min((dot - path), (_MAX_FNAME - 1)); lstrcpyn(fname, path, len + 1); *(fname + len) = TEXT('\0'); }
// now we can get the extension - remember that p still points to the
// terminating nul character of path.
if (ext) { len = (USHORT) __min((p - dot), (_MAX_EXT - 1)); lstrcpyn(ext, dot, len + 1); ext[len] = TEXT('\0'); } } else { // found no extension, give empty extension and copy rest of string
// into fname.
if (fname) { len = (USHORT) __min((p - path), (_MAX_FNAME - 1)); lstrcpyn(fname, path, len + 1); fname[len] = TEXT('\0'); } if (ext) { *ext = TEXT('\0'); } }
} // lsplitpath
/////////////////////////////////////////////////////////////////////////
VOID lmakepath( TCHAR *path, const TCHAR *drive, const TCHAR *dir, const TCHAR *fname, const TCHAR *ext )
/*++
Routine Description:
create a path name from its individual components.
Arguments:
char *path - pointer to buffer for constructed path char *drive - pointer to drive component, may or may not contain trailing ':' char *dir - pointer to subdirectory component, may or may not include leading and/or trailing '/' or '\' characters char *fname - pointer to file base name component char *ext - pointer to extension component, may or may not contain a leading '.'.
Return Value:
path - pointer to constructed path name
--*/
{ const TCHAR *p;
/*+---------------------------------------------------------------------+
| we assume that the arguments are in the following form (although we | | do not diagnose invalid arguments or illegal filenames (such as | | names longer than 8.3 or with illegal characters in them) | | | | drive: | | A or A: | | dir: | | \top\next\last\ ; or | | /top/next/last/ ; or | | | | either of the above forms with either/both the leading and | | trailing / or \ removed. Mixed use of '/' and '\' is also | | tolerated | | fname: | | any valid file name | | ext: | | any valid extension (none if empty or null ) | +---------------------------------------------------------------------+*/
// copy drive
if (drive && *drive) while (*drive) *path++ = *drive++;
// copy dir
if ((p = dir) && *p) { do { *path++ = *p++; } while (*p); if ((*(p-1) != TEXT('/')) && (*(p-1) != TEXT('\\'))) { *path++ = TEXT('\\'); } }
// copy fname
if (p = fname) { while (*p) { *path++ = *p++; } }
// copy ext, including 0-terminator - check to see if a '.' needs to be
// inserted.
if (p = ext) { if (*p && *p != TEXT('.')) { *path++ = TEXT('.'); } while (*path++ = *p++) ; } else { // better add the 0-terminator
*path = TEXT('\0'); }
} // lmakepath
#ifndef _UNICODE
#error "Function below not DBCS safe"
#endif
VOID EscapeFormattingChars( LPTSTR String, ULONG BufferLength )
/*++
Routine Description:
Escapes any formatting chars (ie. % chars) in the string so if you sprintf it, you dont trap out as a result of trying to access bogus stack data.
Arguments:
String - String to fix up. Escaping is done IN PLACE. BufferLength - Size of the buffer the string is in. We need to know this since we are inserting characters. BufferLength is in characters, not bytes.
Return Value:
None
--*/ {
ULONG Length; LONG Avail ; LPTSTR End, Tmp = String ;
if (!Tmp) return ;
Length = lstrlen(String) ;
//
// Point past end of string. We use this to figure out
// via pointer substraction how much needs to be shifted
// down as we insert chars.
//
End = Tmp + Length + 1 ;
//
// How much is avail for escape chars
//
Avail = BufferLength - (Length+1) ;
while (*Tmp) {
if (*Tmp == TEXT('%')) {
//
// If no more space, just change to '_'.
//
if (Avail <= 0) {
*Tmp = TEXT('_') ; } else {
//
// Move string over and add escape character.
// This is not very efficient but we assume
// that this is not common.
//
--Avail ; memmove(Tmp+1, Tmp, (UINT) (End - Tmp)) ; *Tmp = TEXT('%') ; Tmp++ ; }
}
++Tmp ; } }
|