/***************************************************************************** * * * HCMISC.H * * * * Copyright (C) Microsoft Corporation 1990. * * All Rights reserved. * * * ****************************************************************************** * * * Module Intent * * * * Miscellaneous functions for HC including string manipulation and * * memory allocation. * * * ****************************************************************************** * * * Testing Notes * * * ****************************************************************************** * * * Current Owner: JohnSc * * * ****************************************************************************** * * * Released by Development: 00/00/00 * * * *****************************************************************************/ /***************************************************************************** * * Revision History: Created 00/00/00 by NeelMah * * 11/21/90 JohnSc Added this comment header, fixed VSkipTrailing bug (tabs) * *****************************************************************************/ #include "stdafx.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif /***************************************************************************** * * * Defines * * * *****************************************************************************/ #define cbSzBlockSize 32000 // string block size // DOS int 21 AX error codes #define wHunkyDory 0x00 #define wInvalidFunctionCode 0x01 #define wFileNotFound 0x02 #define wPathNotFound 0x03 #define wTooManyOpenFiles 0x04 #define wAccessDenied 0x05 #define wInvalidHandle 0x06 #define wInvalidAccessCode 0x0c /***************************************************************************** * * * Static Variables * * * *****************************************************************************/ static WORD cbSzBlockUsed = 0; // no. of bytes already used. static PSTR szBlock = NULL; // current string block. static void STDCALL WExtendedError(LPWORD perr, LPBYTE pclass, LPBYTE paction, LPBYTE plocus); /*----------------------------------------------------------------------------- * SzParseList( szList ) * * Description: * This function may be used to parse a list of strings separated * by semicolons and surrounded by whitespace. Note that whitespace * does not delimit the strings in the list. * * Arguments: * szString -- List of strings to be parsed. This should only be * passed for the first string to be parsed from the * list; successive strings are parsed by passing NULL. * * Returns; * The next string in the list. * * +++ * * Notes: * This process will destroy the original list of strings. Also, * this function makes use of the library function strtok, which * contains the static variable of the list being parsed. Thus, * you must not attempt to parse a different list using this * function or strtok while in the middle of parsing a list. *-----------------------------------------------------------------------------*/ PSTR STDCALL SzParseList(PSTR pszList) { pszList = SzTrimSz(StrToken(pszList, ';')); // If string contains only whitespace, go on to next string while (pszList != NULL && *pszList == '\0') pszList = SzTrimSz(StrToken(NULL, ';')); return pszList; } /*----------------------------------------------------------------------------- * SzGetKeySz(szStr, szKey, icbKeySize, piCount ) * * Description: * This function extracts a string from a list. While it used * to be used to extract keywords, it is currently only used in * parsebld.c to extract build tags. * * Arguments: * * Returns; * returns TRUE if successful else FALSE. *-----------------------------------------------------------------------------*/ PSTR STDCALL SzGetKeySz(PSTR pszStr, PSTR szKey, int icbKeySize, int* piCount) { PSTR szTemp; *piCount = 0; pszStr = FirstNonSpace(pszStr, options.fDBCS); szTemp = szKey; while (*pszStr != '\0' && *pszStr != ';') { if (*piCount < icbKeySize) *szKey++ = *pszStr++; else pszStr++; (*piCount)++; } *szKey = '\0'; RemoveTrailingSpaces(szTemp); if (*pszStr) pszStr++; return pszStr; } /*----------------------------------------------------------------------------- * SzGetExtSz(szStr) * * Description: * This function returns the pointer to the extenstion if any for the * given file name string. * * Arguments: * 1. szStr - string to which exten string to be appened. * * Returns; * returns the pointer to the extension of the given file name string if * any else returns null *-----------------------------------------------------------------------------*/ PSTR STDCALL SzGetExtSz(PSTR szStr) { PSTR pszTmp; BOOL fFound = FALSE; int iT = 0; // skip trailing blanks RemoveTrailingSpaces(szStr); pszTmp = szStr + strlen(szStr) - 1; while ((pszTmp > szStr) && (iT < 4)) { if (*pszTmp == '.') { fFound = TRUE; break; } if (IsCharAlphaNumeric(*pszTmp)) { pszTmp--; iT++; } else break; } if (!fFound) return(NULL); return(pszTmp); } PSTR STDCALL SzSkipBlanksSz(PSTR sz) { RemoveTrailingSpaces(sz); return FirstNonSpace(sz, options.fDBCS); } /*----------------------------------------------------------------------------- * QResizeTable() * * Description: * This function acquires a table of initial size or resizes the * previously acquired table by increasing the size. * * Arguments: * 1. qvTable - initial table pointer. * 2. lcNew - number of elements currently in table. * 3. qlcMac - pointer to number of elements allocated for in table. * 4. cbEntry - size of each entry in the table. * 5. cInit - initial number of elements to put in table. * 6. cIncr - if table is used fully, increment by these many entries. * * Returns; * returns the reallocated table pointer. *-----------------------------------------------------------------------------*/ void* STDCALL QResizeTable(void* qvTable, int lcNew, int* qlcMac, int cbEntry, int cInit, int cIncr) { if (*qlcMac <= lcNew) { if (*qlcMac == 0L) { qvTable = lcCalloc((int) cbEntry * cInit); *qlcMac = cInit; } else { *qlcMac += cIncr; ASSERT(qvTable != NULL); qvTable = lcReAlloc(qvTable, (int) cbEntry * (*qlcMac)); } } ASSERT(qvTable != NULL); ASSERT(*qlcMac >= lcNew); return(qvTable); } /*----------------------------------------------------------------------------- * PSTR SzMacroFromSz( sz ) * * Description: * This function returns a pointer to the macro string contained in * sz, if any. * * Input * sz: Hotspot term possibly containing a macro. * * Returns; * Pointer to the macro string, or NULL if it isn't a macro. *-----------------------------------------------------------------------------*/ PSTR STDCALL SzMacroFromSz(PSTR psz) { if (*psz == '[' && CharAnsiUpper(*(psz + 1)) == 'S' && *(psz + 2) == ']') return(psz + 3); if (*psz == '$') return (psz + 1); if (*psz == '!') return (psz + 1); return( NULL ); } /*----------------------------------------------------------------------------- * SzTranslateHash() * * Description: * This function is used to translate hash values via the alias table. * If the hash value is aliased, the function returns a pointer to the * context string corresponding to the translated hash value. * * Arguments: * 1. qhash - pointer to id where the context id will be returned * if the given id is found to be an alias id. * * Returns; * Alias string if one was found, otherwise NULL. * *-----------------------------------------------------------------------------*/ PSTR STDCALL SzTranslateHash(HASH* qhash ) { int ialias; QALIAS qalias; if (pdrgAlias) { for (ialias = 0, qalias = (QALIAS) pdrgAlias->GetBasePtr(); ialias < pdrgAlias->Count(); ialias++, qalias++) { if (*qhash == qalias->hashAlias) { *qhash = qalias->hashCtx; return qalias->szCtx; } } } return NULL; } /*************************************************************************** * - Name: ErrorQch - * Purpose: Displays standard WinHelp error message dialog based * the string passed. * * Arguments: qch - string to display * * Returns: Nothing. * * Globals Used: hwndHelpCur - main window handle * pchCaption - main help caption * * Notes: Used by * ***************************************************************************/ void STDCALL ErrorQch(PCSTR qch) { MessageBox(NULL, qch, GetStringResource(IDS_TITLE), MB_OK | MB_ICONINFORMATION | MB_SYSTEMMODAL); } /*************************************************************************** FUNCTION: WExtendedError PURPOSE: Get extended DOS error information PARAMETERS: perr pclass paction plocus RETURNS: COMMENTS: MODIFICATION DATES: 01-Mar-1993 [ralphw] ***************************************************************************/ VOID STDCALL DOS3Call(void); #pragma warning(disable:4035) // no return value #pragma warning(disable:4704) // in-line assembler precludes global optimizations static void STDCALL WExtendedError(LPWORD perr, LPBYTE pclass, LPBYTE paction, LPBYTE plocus) { // REVIEW: what is being returned? } int iCbTotalUncompressed; int iCbTotalPhrase; int iCbTotalJohn; int iCbZeckBlockIn; int iCbZeckBlockOut; void FASTCALL AddZeckCounts( int iCbUncomp, int iCbComp) { iCbZeckBlockIn += iCbUncomp; iCbZeckBlockOut += iCbComp; } void FASTCALL AddCharCounts(int iCbTotal, int iCbPhrase, int iCbJohn) { iCbTotalUncompressed += iCbTotal; iCbTotalPhrase += iCbPhrase; iCbTotalJohn += iCbJohn; } const char txtIncreased[] = "INCREASED"; const char txtDecreased[] = "decreased"; void STDCALL ReportCharCounts(void) { /* * Note that we include zeck savings as part of the total savings count. * The reason is that Zeck will get different savings results when * run over plain text versus compressed text, so its savings must * be calculated into the total savings count. */ if (options.fsCompress & COMPRESS_TEXT_HALL) { int savings = ((iCbTotalUncompressed - iCbTotalJohn) - cbHallOverhead) + (iCbZeckBlockIn - iCbZeckBlockOut); wsprintf(szParentString, GetStringResource(IDS_COMPRESSION_SAVE), ((options.fsCompress & COMPRESS_TEXT_ZECK) ? "Hall+Zeck" : "Hall"), ((savings < 0) ? txtIncreased : txtDecreased), FormatNumber(abs(savings))); SendLogStringToParent(); } else if (options.fsCompress & COMPRESS_TEXT_PHRASE) { int savings = (iCbTotalUncompressed - iCbTotalPhrase) - cbCompressedPhrase + (iCbZeckBlockIn - iCbZeckBlockOut); wsprintf(szParentString, GetStringResource(IDS_COMPRESSION_SAVE), ((options.fsCompress & COMPRESS_TEXT_ZECK) ? "Phrase+Zeck" : "Phrase"), ((savings < 0) ? txtIncreased : txtDecreased), FormatNumber(abs(savings))); SendLogStringToParent(); } else if (options.fsCompress & COMPRESS_TEXT_ZECK && !(options.fsCompress & COMPRESS_TEXT_PHRASE) && !(options.fsCompress & COMPRESS_TEXT_HALL)) { int savings = (iCbZeckBlockIn - iCbZeckBlockOut); wsprintf(szParentString, GetStringResource(IDS_COMPRESSION_SAVE), "Zeck", ((savings < 0) ? txtIncreased : txtDecreased), FormatNumber(abs(savings))); SendLogStringToParent(); } } #ifndef _INC_CTYPE #include #endif void STDCALL RemoveTrailingSpaces(PSTR pszString) { if (!options.fDBCS) { PSTR psz = pszString + strlen(pszString) - 1; while (IsSpace(*psz)) { if (--psz <= pszString) { *pszString = '\0'; return; } } psz[1] = '\0'; } else { /* * Removing trailing spaces in DBCS requires stepping through * from the beginning of the string since we can't know if a * trailing space is really a space or the second byte of a lead * byte. */ PSTR psz = pszString + strlen(pszString) - 1; while (IsSpace(*psz) && psz > pszString + 2 && !IsDBCSLeadByte(psz[-1])) { if (--psz <= pszString) { *pszString = '\0'; return; } } psz[1] = '\0'; } } /*----------------------------------------------------------------------------- * SzTrimSz( sz ) * * Description: * This function removes whitespaces (blank, tab, or newline) from * the beginning and ending of the string sz. * * Arguments: * sz -- string to be trimmed of whitespace. * * Returns: * returns the pointer to the trimmed string. * * +++ * * Notes: * This function changes the original string. *-----------------------------------------------------------------------------*/ PSTR STDCALL SzTrimSz(PSTR pszOrg) { if (!pszOrg) return NULL; // Skip over leading whitespace if (options.fDBCS) { PSTR psz = pszOrg; while (!IsFirstByte(*psz) && IsSpace(*psz)) psz++; if (psz != pszOrg) strcpy(pszOrg, psz); } else if (IsSpace(*pszOrg)) strcpy(pszOrg, FirstNonSpace(pszOrg, FALSE)); RemoveTrailingSpaces(pszOrg); return pszOrg; } BOOL STDCALL IsSpace(char ch) { if (options.fDBCS) return (!IsFirstByte(ch) && (ch == ' ' || ch == '\t')); else return ((ch == ' ' || ch == '\t')); } /*************************************************************************** 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, char chDelimiter) { static PSTR pszSavedList = NULL; PSTR psz; if (pszList) { pszSavedList = pszList; // On the first call, remove any leading token matches while (*pszSavedList == chDelimiter) pszSavedList++; } if (options.fDBCS) { psz = pszSavedList; while (*psz && *psz != chDelimiter) { psz = CharNext(psz); } if (!*psz) psz = NULL; } else { psz = strchr(pszSavedList, chDelimiter); } 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; } /*************************************************************************** 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 (options.fDBCS) { 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; }