901 lines
19 KiB
C++
901 lines
19 KiB
C++
/****************************************************************************
|
|
*
|
|
* COMMON.CPP
|
|
*
|
|
* Copyright (C) Microsoft Corporation 1993-1994
|
|
* All Rights reserved.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#ifndef _CSTR_INCLUDED
|
|
#include "cstr.h"
|
|
#endif
|
|
|
|
#ifndef _INC_CTYPE
|
|
#include <ctype.h>
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
void STDCALL InitializeHwDll(HWDLL_INIT* pinit)
|
|
{
|
|
hinstApp = pinit->hinstApp;
|
|
pszErrorFile = pinit->pszErrorFile;
|
|
hwndApp = pinit->hwndWindow;
|
|
CopyAssertInfo = pinit->CopyAssertInfo;
|
|
pszMsgBoxTitle = pinit->pszMsgBoxTitle;
|
|
if (pinit->version > DLL_VERSION)
|
|
DllMsgBox(IDS_DLL_OUT_OF_DATE);
|
|
|
|
pinit->fDBCSSystem = _fDBCSSystem;
|
|
pinit->lcidSystem = _lcidSystem;
|
|
pinit->fDualCPU = _fDualCPU;
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: stristr
|
|
|
|
PURPOSE: Case-insensitive search for a sub string in a main string
|
|
|
|
PARAMETERS:
|
|
pszMain
|
|
pszSub
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
Not tested
|
|
|
|
MODIFICATION DATES:
|
|
28-Mar-1994 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
PSTR STDCALL stristr(PCSTR pszMain, PCSTR pszSub)
|
|
{
|
|
PSTR pszCur = (PSTR) pszMain;
|
|
char ch = tolower(*pszSub);
|
|
int cb = strlen(pszSub) - 1; // -1 to ignore leading character
|
|
|
|
for (;;) {
|
|
while (tolower(*pszCur) != ch && *pszCur)
|
|
pszCur++;
|
|
if (!*pszCur)
|
|
return NULL;
|
|
if (_strnicmp(pszCur + 1, pszSub + 1, cb) == 0)
|
|
return pszCur;
|
|
pszCur++;
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: IsThereMore
|
|
|
|
PURPOSE: Given a pointer to an argument, or the space after an argument,
|
|
return a pointer to the next argument if there is one, or
|
|
NULL if there is no additional argument
|
|
|
|
RETURNS: Pointer to second item, NULL if none found.
|
|
|
|
COMMENTS:
|
|
Normally a dot command such as .list is passed to this to determine
|
|
if there is additional text on the same line. If there is, a pointer
|
|
to the second item is returned.
|
|
|
|
MODIFICATION DATES:
|
|
03-Apr-1989 [ralphw]
|
|
05-Jul-1989 [ralphw]
|
|
If the current pointer is to a quote, then skip everything until
|
|
the next quote.
|
|
|
|
***************************************************************************/
|
|
|
|
PSTR STDCALL IsThereMore(PCSTR psz)
|
|
{
|
|
if (!psz)
|
|
return NULL;
|
|
|
|
// If the current argument is quoted, skip to next quote
|
|
|
|
if (*psz == CH_QUOTE || *psz == CH_START_QUOTE) {
|
|
char chEnd = (*psz == CH_QUOTE) ? CH_QUOTE : CH_END_QUOTE;
|
|
KeepTrying:
|
|
for (psz++; *psz != chEnd && *psz; psz++);
|
|
if (psz[-1] == CH_BACKSLASH) {
|
|
psz++;
|
|
goto KeepTrying;
|
|
}
|
|
if (*psz == chEnd)
|
|
psz++;
|
|
}
|
|
|
|
// find the first space or EOL
|
|
|
|
while (*psz > CH_SPACE && *psz)
|
|
psz++;
|
|
|
|
// find the first non-space
|
|
|
|
while (isspace(*psz))
|
|
psz++;
|
|
return (*psz) ? (PSTR) psz : NULL;
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: FirstNonSpace
|
|
|
|
PURPOSE: Return a pointer to the first non-space character
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
30-May-1989 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
#ifndef _INC_CTYPE
|
|
#include <ctype.h>
|
|
#endif
|
|
|
|
PSTR STDCALL FirstNonSpace(PCSTR psz, BOOL fDBCS)
|
|
{
|
|
if (fDBCS) {
|
|
while (!IsDBCSLeadByte(*psz) && IsDbcsSpace(*psz, TRUE))
|
|
psz++;
|
|
return (PSTR) psz;
|
|
}
|
|
|
|
while(IsDbcsSpace(*psz, FALSE))
|
|
psz++;
|
|
return (PSTR) psz;
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: IsDbcsSpace
|
|
|
|
PURPOSE: DBCS-aware version of isspace
|
|
|
|
PARAMETERS:
|
|
ch
|
|
fDBCS
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
14-Jan-1995 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
BOOL STDCALL IsDbcsSpace(char ch, BOOL fDBCS)
|
|
{
|
|
if (fDBCS)
|
|
return (!IsDBCSLeadByte(ch) && (ch == CH_SPACE || ch == CH_TAB));
|
|
else
|
|
return ((ch == CH_SPACE || ch == CH_TAB));
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: ChangeExtension
|
|
|
|
PURPOSE: Changes the extension of a filename
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
The extension can be specified with or without the leading period.
|
|
|
|
MODIFICATION DATES:
|
|
25-May-1990 [ralphw]
|
|
04-Aug-1990 [ralphw]
|
|
NULL for an extension means remove any existing extension
|
|
|
|
***************************************************************************/
|
|
|
|
void STDCALL ChangeExtension(PSTR pszDest, PCSTR pszExt)
|
|
{
|
|
PSTR psz;
|
|
BOOL fDBCSSystem = IsDbcsSystem();
|
|
|
|
ASSERT(pszDest);
|
|
|
|
// If NULL is specified, simply remove any existing extension
|
|
|
|
if (pszExt == NULL || !*pszExt) {
|
|
if ((psz = StrRChr(pszDest, '.', fDBCSSystem)) != NULL)
|
|
*psz = '\0';
|
|
return;
|
|
}
|
|
|
|
if ((psz = StrRChr(pszDest, '.', fDBCSSystem)) == NULL)
|
|
psz = pszDest + strlen(pszDest); // filename didn't have an extension
|
|
if (*pszExt != '.')
|
|
*psz++ = '.';
|
|
strcpy(psz, pszExt);
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: StrChr
|
|
|
|
PURPOSE: DBCS-capable version of strchr
|
|
|
|
PARAMETERS:
|
|
pszString
|
|
ch
|
|
fDBCS
|
|
|
|
RETURNS: pointer to the character
|
|
|
|
COMMENTS: This can NOT find a DBCS character. It can only be used to
|
|
find a SBCS character imbedded in a DBCS character string.
|
|
|
|
MODIFICATION DATES:
|
|
29-Jul-1994 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
PSTR STDCALL StrChr(PCSTR pszString, char ch, BOOL fDBCS)
|
|
{
|
|
if (!fDBCS)
|
|
return strchr(pszString, ch);
|
|
while (*pszString) {
|
|
while (IsDBCSLeadByte(*pszString))
|
|
pszString += 2;
|
|
if (*pszString == ch)
|
|
return (PSTR) pszString;
|
|
else if (!*pszString)
|
|
return NULL;
|
|
pszString++;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: StrRChr
|
|
|
|
PURPOSE: DBCS-enabled version of strrchr
|
|
|
|
PARAMETERS:
|
|
pszString
|
|
ch
|
|
fDBCS
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
14-Jan-1995 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
PSTR STDCALL StrRChr(PCSTR pszString, char ch, BOOL fDBCS)
|
|
{
|
|
if (!fDBCS)
|
|
return strrchr(pszString, ch);
|
|
PSTR pszLast = StrChr(pszString, ch, fDBCS);
|
|
if (!pszLast)
|
|
return NULL;
|
|
PSTR pszNext;
|
|
while ((pszNext = StrChr(pszLast + 1, ch, fDBCS)))
|
|
pszLast = pszNext;
|
|
return pszLast;
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: RemoveObject
|
|
|
|
PURPOSE: Unlike DeleteObject (which this function calls), this
|
|
function not only deletes the object, but zeros-out the
|
|
handle of the object.
|
|
|
|
PARAMETERS:
|
|
phobj
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
It's perfectly fine to call this with a NULL handle -- the function
|
|
will return immediately without attempting to delete the object.
|
|
|
|
When compiling the debugging version, this function will confirm
|
|
that the object was deleted.
|
|
|
|
MODIFICATION DATES:
|
|
05-Feb-1992 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
void STDCALL RemoveObject(HGDIOBJ *phobj)
|
|
{
|
|
if (*phobj == NULL)
|
|
return; // object has already been deleted
|
|
|
|
VERIFY(DeleteObject(*phobj));
|
|
*phobj = NULL;
|
|
}
|
|
|
|
BOOL STDCALL IsThisChicago(void)
|
|
{
|
|
|
|
// handles both version 4.00 and 3.99.
|
|
|
|
if (HIBYTE(LOWORD(GetVersion())) >= 90 ||
|
|
LOBYTE(LOWORD(GetVersion())) >= 4)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL STDCALL nstrisubcmp(PCSTR mainstring, PCSTR substring)
|
|
{
|
|
int cb = lstrlen(substring);
|
|
int cbMain = lstrlen(mainstring);
|
|
if (cb > cbMain)
|
|
return FALSE;
|
|
return (CompareString(GetUserDefaultLCID(), NORM_IGNORECASE,
|
|
mainstring, cb, substring, cb) == 2);
|
|
}
|
|
|
|
const int MAX_STRING_RESOURCE_LEN = 255;
|
|
|
|
int STDCALL MsgBox(UINT idString, UINT nType)
|
|
{
|
|
char szMsg[MAX_STRING_RESOURCE_LEN + 1];
|
|
if (LoadString(hinstApp, idString, szMsg,
|
|
sizeof(szMsg)) == 0) {
|
|
#ifdef _DEBUG
|
|
wsprintf(szMsg, "invalid string id #%u", idString);
|
|
DBWIN(szMsg);
|
|
#endif
|
|
return 0;
|
|
}
|
|
return MessageBox(hwndApp, szMsg, pszMsgBoxTitle, nType);
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: DllMsgBox
|
|
|
|
PURPOSE: Same as MsgBox, but uses a string resource id from the dll
|
|
|
|
PARAMETERS:
|
|
idString
|
|
nType
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
29-Jun-1995 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
int STDCALL DllMsgBox(UINT idString, UINT nType)
|
|
{
|
|
char szMsg[MAX_STRING_RESOURCE_LEN + 1];
|
|
if (LoadString(hinstDll, idString, szMsg,
|
|
sizeof(szMsg)) == 0) {
|
|
#ifdef _DEBUG
|
|
wsprintf(szMsg, "invalid string id #%u", idString);
|
|
DBWIN(szMsg);
|
|
#endif
|
|
return 0;
|
|
}
|
|
return MessageBox(hwndApp, szMsg, pszMsgBoxTitle, nType);
|
|
}
|
|
|
|
int STDCALL MsgBox(PCSTR pszMsg, UINT nType)
|
|
{
|
|
return MessageBox(hwndApp, pszMsg, pszMsgBoxTitle, nType);
|
|
}
|
|
|
|
static char szStringBuf[MAX_STRING_RESOURCE_LEN + MAX_PATH];
|
|
|
|
PCSTR STDCALL GetStringResource(int idString)
|
|
{
|
|
if (LoadString(hinstApp, idString, szStringBuf,
|
|
sizeof(szStringBuf)) == 0) {
|
|
#ifdef _DEBUG
|
|
wsprintf(szStringBuf, "invalid string id #%u", idString);
|
|
DBWIN(szStringBuf);
|
|
#endif
|
|
szStringBuf[0] = '\0';
|
|
}
|
|
return (PCSTR) szStringBuf;
|
|
}
|
|
|
|
PCSTR STDCALL GetStringResource(int idString, PCSTR pszAppend)
|
|
{
|
|
if (LoadString(hinstApp, idString, szStringBuf,
|
|
sizeof(szStringBuf)) == 0) {
|
|
#ifdef _DEBUG
|
|
wsprintf(szStringBuf, "invalid string id #%u", idString);
|
|
DBWIN(szStringBuf);
|
|
#endif
|
|
szStringBuf[0] = '\0';
|
|
}
|
|
strcat(szStringBuf, pszAppend);
|
|
return (PCSTR) szStringBuf;
|
|
}
|
|
|
|
PCSTR STDCALL GetDllStringResource(int idString)
|
|
{
|
|
if (LoadString(hinstDll, idString, szStringBuf,
|
|
sizeof(szStringBuf)) == 0) {
|
|
#ifdef _DEBUG
|
|
wsprintf(szStringBuf, "invalid string id #%u", idString);
|
|
DBWIN(szStringBuf);
|
|
#endif
|
|
szStringBuf[0] = '\0';
|
|
}
|
|
return (PCSTR) szStringBuf;
|
|
}
|
|
|
|
static HCURSOR hcurRestore, hcurWait;
|
|
|
|
void STDCALL WaitCursor(void)
|
|
{
|
|
if (!hcurWait)
|
|
hcurWait = LoadCursor(NULL, (LPSTR) IDC_WAIT);
|
|
|
|
hcurRestore = SetCursor(hcurWait);
|
|
}
|
|
|
|
void STDCALL RemoveWaitCursor(void) {
|
|
SetCursor(hcurRestore);
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: FormatNumber
|
|
|
|
PURPOSE: Convert a number into a string, and insert commas every
|
|
3 digits
|
|
|
|
PARAMETERS:
|
|
num
|
|
|
|
RETURNS: Pointer to the string containing the number
|
|
|
|
COMMENTS:
|
|
Cycles through an array of strings, allowing up to MAX_STRING
|
|
requests before a duplicate would occur. This is important for
|
|
calls to sprintf() where all the pointers are retrieved before
|
|
the strings are actually used.
|
|
|
|
MODIFICATION DATES:
|
|
03-Jul-1994 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
#define MAX_NUM 15
|
|
#define MAX_STRING 10
|
|
|
|
#include <stdlib.h>
|
|
|
|
PCSTR STDCALL FormatNumber(int num)
|
|
{
|
|
static int pos = 0;
|
|
static char szNum[MAX_NUM * MAX_STRING];
|
|
PSTR pszNum = szNum + (pos * MAX_STRING);
|
|
if (++pos >= MAX_STRING)
|
|
pos = 0;
|
|
|
|
_itoa(num, pszNum, 10);
|
|
|
|
int cb = strlen(pszNum) - 3;
|
|
while (cb > 0) {
|
|
memmove(pszNum + cb + 1, pszNum + cb, strlen(pszNum + cb) + 1);
|
|
pszNum[cb] = ',';
|
|
cb -= 3;
|
|
}
|
|
return pszNum;
|
|
}
|
|
|
|
void STDCALL OOM(void)
|
|
{
|
|
|
|
/*
|
|
* If our heap initializatin fails, we won't have an instance handle
|
|
* yet, so we can't load a string resource. In this case, we have no
|
|
* choice but to use the English message.
|
|
*/
|
|
|
|
if (!hinstDll)
|
|
FatalAppExit(0,
|
|
"There is not enough memory available for this task.\nQuit one or more applications to increase available memory, and then try again.");
|
|
else
|
|
FatalAppExit(0, GetDllStringResource(IDS_OOM));
|
|
}
|
|
|
|
void AssertErrorReport(PCSTR pszExpression, UINT Line, LPCSTR pszFile)
|
|
{
|
|
char szBuf[512], szErrorFile[30];
|
|
HFILE hf;
|
|
OFSTRUCT of;
|
|
static BOOL fAsserted = FALSE;
|
|
char szExpression[256];
|
|
char szName[_MAX_FNAME];
|
|
BOOL fCopiedToPike = FALSE;
|
|
|
|
if (fAsserted)
|
|
return; // we already asserted
|
|
else
|
|
fAsserted = TRUE;
|
|
|
|
/*
|
|
* Often the expression will have been obtained via GetStringResource,
|
|
* so we make a copy of it here to save the information.
|
|
*/
|
|
|
|
strncpy(szExpression, pszExpression, sizeof(szExpression));
|
|
|
|
#ifdef INTERNAL
|
|
if (!GetVolumeInformation("c:\\", szName, sizeof(szName),
|
|
NULL, NULL, NULL, NULL, 0)) {
|
|
strcpy(szName, pszErrorFile);
|
|
}
|
|
else {
|
|
szName[8] = '\0';
|
|
CharLower(szName);
|
|
strcat(szName, ".err");
|
|
strcpy(szErrorFile, "\\\\pike\\bugs\\flash\\");
|
|
strcat(szErrorFile, szName);
|
|
}
|
|
|
|
of.cBytes = sizeof(OFSTRUCT);
|
|
hf = OpenFile(szErrorFile, &of, OF_CREATE | OF_WRITE);
|
|
if (hf == HFILE_ERROR) {
|
|
|
|
// couldn't find \\pike, so copy it to their C drive.
|
|
|
|
strcpy(szErrorFile, "c:\\");
|
|
strcat(szErrorFile, szName);
|
|
hf = OpenFile(szErrorFile, &of, OF_CREATE | OF_WRITE);
|
|
}
|
|
else
|
|
fCopiedToPike = TRUE;
|
|
#else
|
|
|
|
if (!GetVolumeInformation("c:\\", szName, sizeof(szName),
|
|
NULL, NULL, NULL, NULL, 0)) {
|
|
strcpy(szErrorFile, pszErrorFile);
|
|
}
|
|
else {
|
|
strcpy(szErrorFile, "c:\\");
|
|
CharLower(szName);
|
|
strcat(szErrorFile, szName);
|
|
szErrorFile[10] = '\0';
|
|
strcat(szErrorFile, ".err");
|
|
}
|
|
|
|
of.cBytes = sizeof(OFSTRUCT);
|
|
hf = OpenFile(szErrorFile, &of, OF_CREATE | OF_WRITE);
|
|
|
|
#endif // INTERNAL
|
|
|
|
if (hf >= 0) {
|
|
strcpy(szBuf, GetStringResource(IDS_VERSION));
|
|
wsprintf(szBuf + strlen(szBuf),
|
|
GetDllStringResource(IDS_ASSERTION_FAILURE),
|
|
(LPSTR) pszFile, Line, (LPSTR) szExpression);
|
|
_lwrite(hf, szBuf, strlen(szBuf));
|
|
|
|
if (CopyAssertInfo) {
|
|
char szSysInfo[512];
|
|
CopyAssertInfo(szSysInfo);
|
|
_lwrite(hf, szSysInfo, strlen(szSysInfo));
|
|
}
|
|
|
|
wsprintf(szBuf,
|
|
GetDllStringResource((fCopiedToPike ?
|
|
IDS_ASSRT_COPIED_MSG : IDS_ASSRT_COPY_MSG)),
|
|
szErrorFile);
|
|
MsgBox(szBuf);
|
|
_lclose(hf);
|
|
}
|
|
else {
|
|
DllMsgBox(IDS_INTERNAL_ERROR);
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
int answer = ::MessageBox(NULL, pszExpression, "Retry to call DebugBreak()",
|
|
MB_ABORTRETRYIGNORE);
|
|
|
|
if (answer == IDRETRY) {
|
|
DebugBreak();
|
|
return;
|
|
}
|
|
else if (answer == IDIGNORE)
|
|
return;
|
|
#endif
|
|
|
|
/*
|
|
* Send a WM_CLOSE message to give the application the opportunity to
|
|
* clean up resources before being terminated.
|
|
*/
|
|
|
|
if (IsValidWindow(hwndApp))
|
|
SendMessage(hwndApp, WM_CLOSE, 0, 0);
|
|
|
|
// What does AfxWinTerm() do with a non-MFC app?
|
|
|
|
AfxWinTerm();
|
|
_exit(1);
|
|
return;
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: MoveClientWindow
|
|
|
|
PURPOSE: Moves a child window using screen coordinates
|
|
|
|
PARAMETERS:
|
|
hwndParent
|
|
hwndChild
|
|
prc - rectangle containing coordinates
|
|
fRedraw
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
This function is similar to MoveWindow, only it expects the
|
|
coordinates to be in screen coordinates rather then client
|
|
coordinates. This makes it possible to use functions like
|
|
GetWindowRect() and use the values directly.
|
|
|
|
MODIFICATION DATES:
|
|
25-Feb-1992 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
BOOL STDCALL MoveClientWindow(HWND hwndParent, HWND hwndChild,
|
|
const RECT *prc, BOOL fRedraw)
|
|
{
|
|
CPoint pt(0, 0);
|
|
ScreenToClient(hwndParent, &pt);
|
|
|
|
return SetWindowPos(hwndChild, NULL, prc->left + pt.x, prc->top + pt.y,
|
|
RECT_WIDTH(prc), RECT_HEIGHT(prc),
|
|
(fRedraw ? (SWP_NOZORDER | SWP_NOACTIVATE) :
|
|
(SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW)));
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: AddTrailingBackslash
|
|
|
|
PURPOSE:
|
|
|
|
PARAMETERS:
|
|
npszStr
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
|
|
MODIFICATION DATES:
|
|
03-Nov-1992 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
void STDCALL AddTrailingBackslash(PSTR psz)
|
|
{
|
|
int sPos;
|
|
|
|
if (psz != NULL && *psz != '\0') {
|
|
|
|
if (_fDBCSSystem) {
|
|
PSTR pszEnd = psz + strlen(psz);
|
|
if (*(CharPrev(psz, pszEnd)) != '\\' &&
|
|
*(CharPrev(psz, pszEnd)) != '/' &&
|
|
*(CharPrev(psz, pszEnd)) != ':') {
|
|
*pszEnd++ = '\\';
|
|
*pszEnd++ = '\0';
|
|
}
|
|
}
|
|
else {
|
|
sPos = strlen(psz) - 1;
|
|
|
|
if (psz[sPos] != '\\' && psz[sPos] != '/' && psz[sPos] != ':') {
|
|
psz[sPos + 1] = '\\';
|
|
psz[sPos + 2] = '\0';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
|
|
FUNCTION: StrToken
|
|
|
|
PURPOSE: DBCS-enabed variant of strtok
|
|
|
|
PARAMETERS:
|
|
pszList
|
|
chDelimiter
|
|
|
|
RETURNS:
|
|
|
|
COMMENTS:
|
|
You can NOT specify a DBCS character to look for
|
|
|
|
MODIFICATION DATES:
|
|
06-Jan-1995 [ralphw]
|
|
|
|
***************************************************************************/
|
|
|
|
PSTR STDCALL StrToken(PSTR pszList, PCSTR pszDelimeters)
|
|
{
|
|
static PSTR pszSavedList = NULL;
|
|
PSTR psz, pszTokens;
|
|
|
|
if (pszList) {
|
|
pszSavedList = pszList;
|
|
|
|
// On the first call, remove any leading token matches
|
|
|
|
for (psz = (PSTR) pszDelimeters; *psz; psz++) {
|
|
if (*psz == *pszSavedList) {
|
|
pszSavedList++;
|
|
psz = (PSTR) pszDelimeters - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_fDBCSSystem) {
|
|
psz = pszSavedList;
|
|
|
|
while (*psz) {
|
|
for (pszTokens = (PSTR) pszDelimeters; *pszTokens; pszTokens++) {
|
|
if (*pszTokens == *psz)
|
|
break;
|
|
}
|
|
if (*pszTokens == *psz)
|
|
break;
|
|
psz = CharNext(psz);
|
|
}
|
|
if (!*psz)
|
|
psz = NULL;
|
|
}
|
|
else {
|
|
psz = strpbrk(pszSavedList, pszDelimeters);
|
|
}
|
|
|
|
if (!psz) {
|
|
if (!*pszSavedList)
|
|
return NULL;
|
|
else {
|
|
PSTR pszReturn = pszSavedList;
|
|
pszSavedList = pszSavedList + strlen(pszSavedList);
|
|
return pszReturn;
|
|
}
|
|
}
|
|
*psz++ = '\0';
|
|
PSTR pszReturn = pszSavedList;
|
|
pszSavedList = psz;
|
|
return pszReturn;
|
|
}
|
|
|
|
// Same as above, but allows two active strtokens at once
|
|
|
|
PSTR STDCALL StrToken2(PSTR pszList, PCSTR pszDelimeters)
|
|
{
|
|
static PSTR pszSavedList = NULL;
|
|
PSTR psz, pszTokens;
|
|
|
|
if (pszList) {
|
|
pszSavedList = pszList;
|
|
|
|
// On the first call, remove any leading token matches
|
|
|
|
for (psz = (PSTR) pszDelimeters; *psz; psz++) {
|
|
if (*psz == *pszSavedList) {
|
|
pszSavedList++;
|
|
psz = (PSTR) pszDelimeters - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (_fDBCSSystem) {
|
|
psz = pszSavedList;
|
|
|
|
while (*psz) {
|
|
for (pszTokens = (PSTR) pszDelimeters; *pszTokens; pszTokens++) {
|
|
if (*pszTokens == *psz)
|
|
break;
|
|
}
|
|
if (*pszTokens == *psz)
|
|
break;
|
|
psz = CharNext(psz);
|
|
}
|
|
if (!*psz)
|
|
psz = NULL;
|
|
}
|
|
else {
|
|
psz = strpbrk(pszSavedList, pszDelimeters);
|
|
}
|
|
|
|
if (!psz) {
|
|
if (!*pszSavedList)
|
|
return NULL;
|
|
else {
|
|
PSTR pszReturn = pszSavedList;
|
|
pszSavedList = pszSavedList + strlen(pszSavedList);
|
|
return pszReturn;
|
|
}
|
|
}
|
|
*psz++ = '\0';
|
|
PSTR pszReturn = pszSavedList;
|
|
pszSavedList = psz;
|
|
return pszReturn;
|
|
}
|
|
|
|
void STDCALL MsgCantOpen(PCSTR pszFile)
|
|
{
|
|
CStr csz(GetDllStringResource(IDS_CANNOT_OPEN));
|
|
csz += pszFile;
|
|
MsgBox(csz);
|
|
}
|
|
|
|
#include <cderr.h>
|
|
|
|
static PSTR apszCDErr[] = {
|
|
"CDERR_GENERALCODES",
|
|
"CDERR_STRUCTSIZE",
|
|
"CDERR_INITIALIZATION",
|
|
"CDERR_NOTEMPLATE",
|
|
"CDERR_NOHINSTANCE",
|
|
"CDERR_LOADSTRFAILURE",
|
|
"CDERR_FINDRESFAILURE",
|
|
"CDERR_LOADRESFAILURE",
|
|
"CDERR_LOCKRESFAILURE",
|
|
"CDERR_MEMALLOCFAILURE",
|
|
"CDERR_MEMLOCKFAILURE",
|
|
"CDERR_NOHOOK"
|
|
};
|
|
|
|
static PSTR apszFNErr[] = {
|
|
"FNERR_FILENAMECODES",
|
|
"FNERR_SUBCLASSFAILURE",
|
|
"FNERR_INVALIDFILENAME",
|
|
"FNERR_BUFFERTOOSMALL"
|
|
};
|
|
|
|
void STDCALL ReportComDlgError(DWORD Error)
|
|
{
|
|
char szMsg[100];
|
|
|
|
strcpy(szMsg, GetDllStringResource(IDS_COMMDLG_ERROR));
|
|
|
|
if (Error >= CDERR_GENERALCODES && Error <= PDERR_PRINTERCODES)
|
|
strcat(szMsg, apszCDErr[Error]);
|
|
else if (Error >= FNERR_FILENAMECODES && Error <= FRERR_FINDREPLACECODES)
|
|
strcat(szMsg, apszFNErr[Error - FNERR_FILENAMECODES]);
|
|
else
|
|
wsprintf(szMsg + strlen(szMsg), "%lu", Error);
|
|
|
|
MsgBox(szMsg);
|
|
return;
|
|
}
|