283 lines
6.3 KiB
C
283 lines
6.3 KiB
C
//---------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation 1993-1994
|
|
//
|
|
// File: string.c
|
|
//
|
|
// This files contains common string routines
|
|
//
|
|
// History:
|
|
// 10-09-93 ScottH Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
///////////////////////////////////////////////////// INCLUDES
|
|
|
|
#include "brfprv.h" // common headers
|
|
#include "strings.h"
|
|
|
|
|
|
#ifdef NOTUSED
|
|
#pragma data_seg(DATASEG_PERINSTANCE)
|
|
|
|
static LPTSTR s_pszNextToken = NULL;
|
|
|
|
#pragma data_seg()
|
|
#endif // NOTUSED
|
|
|
|
|
|
// Some of these are replacements for the C runtime routines.
|
|
// This is so we don't have to link to the CRT libs.
|
|
//
|
|
|
|
// WARNING: all of these APIs do not setup DS, so you can not access
|
|
// any data in the default data seg of this DLL.
|
|
//
|
|
// do not create any global variables... talk to chrisg if you don't
|
|
// understand this
|
|
|
|
#ifdef DBCS
|
|
#define FASTCALL
|
|
#else
|
|
#define FASTCALL _fastcall
|
|
#endif
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: Case sensitive character comparison for DBCS
|
|
|
|
Returns: FALSE if they match, TRUE if no match
|
|
Cond: --
|
|
*/
|
|
BOOL FASTCALL ChrCmp(
|
|
WORD w1,
|
|
WORD wMatch)
|
|
{
|
|
/* Most of the time this won't match, so test it first for speed.
|
|
*/
|
|
if (LOBYTE(w1) == LOBYTE(wMatch))
|
|
{
|
|
if (IsDBCSLeadByte(LOBYTE(w1)))
|
|
{
|
|
return(w1 != wMatch);
|
|
}
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: Case insensitive character comparison for DBCS
|
|
|
|
Returns: FALSE if match, TRUE if not
|
|
Cond: --
|
|
*/
|
|
BOOL FASTCALL ChrCmpI(
|
|
WORD w1,
|
|
WORD wMatch)
|
|
{
|
|
TCHAR sz1[3], sz2[3];
|
|
|
|
if (IsDBCSLeadByte(sz1[0] = LOBYTE(w1)))
|
|
{
|
|
sz1[1] = HIBYTE(w1);
|
|
sz1[2] = TEXT('\0');
|
|
}
|
|
else
|
|
sz1[1] = TEXT('\0');
|
|
|
|
*(WORD *)sz2 = wMatch;
|
|
sz2[2] = TEXT('\0');
|
|
return lstrcmpi(sz1, sz2);
|
|
}
|
|
|
|
|
|
#ifdef NOTUSED // BUGBUG: this is not DBCS aware
|
|
/*----------------------------------------------------------
|
|
Purpose: strtok
|
|
|
|
Swiped from the C 7.0 runtime sources.
|
|
|
|
Returns:
|
|
Cond:
|
|
*/
|
|
LPTSTR PUBLIC StrTok(
|
|
LPTSTR psz,
|
|
LPCTSTR rgchTokens)
|
|
{
|
|
TUCHAR map[32];
|
|
LPTSTR pszToken;
|
|
|
|
ZeroInit(map, map);
|
|
|
|
do
|
|
{
|
|
map[*rgchTokens >> 3] |= (1 << (*rgchTokens & 7));
|
|
} while (*rgchTokens++);
|
|
|
|
if (!psz)
|
|
{
|
|
ENTEREXCLUSIVE()
|
|
{
|
|
psz = s_pszNextToken;
|
|
}
|
|
LEAVEEXCLUSIVE()
|
|
}
|
|
|
|
while (map[*psz >> 3] & (1 << (*psz & 7)) && *psz)
|
|
psz++;
|
|
pszToken = psz;
|
|
for (;; psz++)
|
|
{
|
|
if (map[*psz >> 3] & (1 << (*psz & 7)))
|
|
{
|
|
if (!*psz && psz == pszToken)
|
|
return(NULL);
|
|
if (*psz)
|
|
*psz++ = TEXT('\0');
|
|
|
|
ENTEREXCLUSIVE()
|
|
{
|
|
g_pszNextToken = psz;
|
|
}
|
|
LEAVEEXCLUSIVE()
|
|
return pszToken;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
#if 0
|
|
/*----------------------------------------------------------
|
|
Purpose: Find first occurrence of character in string
|
|
|
|
Returns: Pointer to the first occurrence of ch in
|
|
Cond: --
|
|
*/
|
|
LPTSTR PUBLIC StrChr(
|
|
LPCTSTR psz,
|
|
WORD wMatch)
|
|
{
|
|
for ( ; *psz; psz = CharNext(psz))
|
|
{
|
|
if (!ChrCmp(*(WORD *)psz, wMatch))
|
|
return (LPTSTR)psz;
|
|
}
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: strnicmp
|
|
|
|
Swiped from the C 7.0 runtime sources.
|
|
|
|
Returns:
|
|
Cond:
|
|
*/
|
|
int PUBLIC lstrnicmp(
|
|
LPCTSTR psz1,
|
|
LPCTSTR psz2,
|
|
UINT count)
|
|
{
|
|
int ch1;
|
|
int ch2;
|
|
int result = 0;
|
|
|
|
if (count)
|
|
{
|
|
do
|
|
{
|
|
ch1 = (int)CharLower((LPTSTR)MAKELONG(*psz1, 0));
|
|
ch2 = (int)CharLower((LPTSTR)MAKELONG(*psz2, 0));
|
|
psz1 = CharNext(psz1);
|
|
psz2 = CharNext(psz2);
|
|
} while (--count && ch1 && ch2 && !ChrCmp((WORD)ch1, (WORD)ch2));
|
|
result = ch1 - ch2;
|
|
}
|
|
return(result);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: Get a string from the resource string table. Returned
|
|
ptr is a ptr to static memory. The next call to this
|
|
function will wipe out the prior contents.
|
|
Returns: Ptr to string
|
|
Cond: --
|
|
*/
|
|
LPTSTR PUBLIC SzFromIDS(
|
|
UINT ids, // resource ID
|
|
LPTSTR pszBuf,
|
|
UINT cchBuf)
|
|
{
|
|
ASSERT(pszBuf);
|
|
|
|
*pszBuf = NULL_CHAR;
|
|
LoadString(g_hinst, ids, pszBuf, cchBuf);
|
|
return pszBuf;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
Purpose: Formats a string by allocating a buffer and loading
|
|
the given resource strings to compose the string.
|
|
|
|
Returns: the count of characters
|
|
|
|
Cond: Caller should free the allocated buffer using GFree.
|
|
*/
|
|
BOOL PUBLIC FmtString(
|
|
LPCTSTR * ppszBuf,
|
|
UINT idsFmt,
|
|
LPUINT rgids,
|
|
UINT cids)
|
|
{
|
|
UINT cch = 0;
|
|
UINT cchMax;
|
|
LPTSTR pszBuf;
|
|
|
|
ASSERT(ppszBuf);
|
|
ASSERT(rgids);
|
|
ASSERT(cids > 0);
|
|
|
|
cchMax = (1+cids) * MAXPATHLEN;
|
|
pszBuf = GAlloc(CbFromCch(cchMax));
|
|
if (pszBuf)
|
|
{
|
|
// The first cids DWORDS are the addresses of the offset strings
|
|
// in the buffer (passed to wvsprintf)
|
|
LPTSTR pszMsgs = GAlloc((cids * sizeof(DWORD)) + (cids * CbFromCch(MAXPATHLEN)));
|
|
if (pszMsgs)
|
|
{
|
|
TCHAR szFmt[MAXPATHLEN];
|
|
LPDWORD rgpsz = (LPDWORD)pszMsgs;
|
|
LPTSTR pszT = pszMsgs + (cids * sizeof(DWORD));
|
|
UINT i;
|
|
|
|
// Load the series of strings
|
|
for (i = 0; i < cids; i++, pszT += MAXPATHLEN)
|
|
{
|
|
rgpsz[i] = (DWORD)pszT;
|
|
SzFromIDS(rgids[i], pszT, MAXPATHLEN);
|
|
}
|
|
|
|
// Compose the string
|
|
SzFromIDS(idsFmt, szFmt, ARRAYSIZE(szFmt));
|
|
cch = FormatMessage(FORMAT_MESSAGE_FROM_STRING,
|
|
szFmt, 0, 0, pszBuf, cchMax, (va_list *)&rgpsz);
|
|
ASSERT(cch <= cchMax);
|
|
|
|
GFree(pszMsgs);
|
|
}
|
|
// pszBuf is freed by caller
|
|
}
|
|
|
|
*ppszBuf = pszBuf;
|
|
return cch;
|
|
}
|
|
|