You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3037 lines
85 KiB
3037 lines
85 KiB
/** CustRes.c
|
|
*
|
|
* Custom resource handler module for TOKRES.
|
|
*
|
|
* Written by SteveBl
|
|
*
|
|
* Exported Functions:
|
|
* int ParseResourceDescriptionFile(FILE *ResourceDescriptionFile);
|
|
*
|
|
* int GetCustomResource(FILE *inResFile, DWORD *lsize,
|
|
* CUSTOM_RESOURCE *pCustomResource,
|
|
* WORD wTypeId);
|
|
*
|
|
* void TokCustomResource(FILE *TokFile, RESHEADER ResHeader,
|
|
* CUSTOM_RESOURCE *pCustomResource);
|
|
*
|
|
* void PutCustomResource(FILE *OutResFile, FILE *TokFile,
|
|
* RESHEADER ResHeader,
|
|
* CUSTOM_RESOURCE *pCustomResource);
|
|
*
|
|
* void ClearCustomResource(CUSTOM_RESOURCE *pCustomResource);
|
|
*
|
|
* History:
|
|
* Initial version written January 21, 1992. -- SteveBl
|
|
*
|
|
* 01/21/93 - Changes to allow arb length token texts. Also, fix
|
|
* some latent bugs. MHotchin
|
|
**/
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <tchar.h>
|
|
|
|
#ifdef RLDOS
|
|
#include "dosdefs.h"
|
|
#else
|
|
#include <windows.h>
|
|
#include "windefs.h"
|
|
#endif
|
|
|
|
#include "custres.h"
|
|
#include "restok.h"
|
|
#include "resread.h"
|
|
|
|
|
|
extern PROJDATA gProj; //... Fields filled in main (UI)
|
|
|
|
|
|
extern BOOL gbMaster;
|
|
extern UCHAR szDHW[];
|
|
|
|
enum LOCALIZABLE_TYPES // determines data storage, reading, and printing method
|
|
{
|
|
NOTLOCALIZABLE, // not to be stored
|
|
NOTLOCALIZABLESZ, // unlocalizable null terminated string
|
|
NOTLOCALIZABLEWSZ, // unlocalizable null terminated Unicode string
|
|
LT_INTEGER, // store as a long integer
|
|
LT_FLOAT, // store as a double preceision floating point number
|
|
LT_CHAR, // store as a single character
|
|
LT_STRING, // an array of char
|
|
LT_SZ, // a null terminated array of characters
|
|
LT_WCHAR, // store as a single Unicode character
|
|
LT_WSTRING, // an array of Unicode char
|
|
LT_WSZ, // a null terminated array of Unicode characters
|
|
LT_UNSIGNED=16 // add with the others
|
|
};
|
|
|
|
typedef struct typesizes
|
|
{
|
|
CHAR *szType;
|
|
enum LOCALIZABLE_TYPES iType;
|
|
int iShortSize;
|
|
int iLongSize;
|
|
} TYPESIZES;
|
|
|
|
TYPESIZES rgTypeSizes[] =
|
|
{
|
|
#ifdef RLWIN32
|
|
"WCHAR", LT_WCHAR, 2, 2,
|
|
"TCHAR", LT_WCHAR, 2, 2,
|
|
"INT", LT_INTEGER, 4, 4,
|
|
"SIGNED", LT_INTEGER, 4, 4,
|
|
"UNSIGNED", LT_INTEGER, 4, 4,
|
|
"ENUM", LT_INTEGER, 4, 4,
|
|
#else //RLWIN32
|
|
"TCHAR", LT_CHAR, 1, 1,
|
|
"INT", LT_INTEGER, 2, 4,
|
|
"SIGNED", LT_INTEGER, 2, 4,
|
|
"UNSIGNED", LT_INTEGER, 2, 4,
|
|
"ENUM", LT_INTEGER, 2, 2,
|
|
#endif //RLWIN32
|
|
"CHAR", LT_CHAR, 1, 1,
|
|
"BYTE", LT_INTEGER, 1, 1,
|
|
"WORD", LT_INTEGER, 2, 2,
|
|
"SHORT", LT_INTEGER, 2, 2,
|
|
"FLOAT", LT_FLOAT, 4, 4,
|
|
"LONG", LT_INTEGER, 4, 4,
|
|
"DOUBLE", LT_FLOAT, 8, 8,
|
|
"DWORD", LT_INTEGER, 4, 4
|
|
};
|
|
|
|
typedef struct resourcetypes
|
|
{
|
|
CHAR *szType;
|
|
int iType;
|
|
} RESOURCETYPES;
|
|
|
|
RESOURCETYPES rgResourceTypes[] =
|
|
{
|
|
"CURSOR", 1,
|
|
"BITMAP", 2,
|
|
"ICON", 3,
|
|
"MENU", 4,
|
|
"DIALOG", 5,
|
|
"STRING", 6,
|
|
"FONTDIR", 7,
|
|
"FONT", 8,
|
|
"ACCELERATORS", 9,
|
|
"RCDATA", 10,
|
|
"ERRTABLE", 11,
|
|
"GROUP_CURSOR", 12,
|
|
"GROUP_ICON", 14,
|
|
"NAMETABLE", 15,
|
|
"VERSION", 16
|
|
};
|
|
|
|
typedef struct CustResTemplate
|
|
{
|
|
enum LOCALIZABLE_TYPES iType;
|
|
unsigned uSize;
|
|
struct CustResTemplate far *pNext;
|
|
} CUSTRESTEMPLATE;
|
|
|
|
typedef struct CustResNode
|
|
{
|
|
BYTE bTypeFlag; /* Indicat's if ID or string */
|
|
BYTE bNameFlag; /* Indicat's if ID or string */
|
|
WORD wTypeID;
|
|
WORD wNameID;
|
|
TCHAR *pszType;
|
|
TCHAR *pszName;
|
|
CUSTRESTEMPLATE far *pTemplate;
|
|
struct CustResNode far *pNext;
|
|
} CUSTRESNODE;
|
|
|
|
typedef CUSTRESTEMPLATE far * FPCUSTRESTEMPLATE;
|
|
typedef CUSTRESNODE far * FPCUSTRESNODE;
|
|
|
|
CUSTRESNODE far *pCustResList = NULL;
|
|
|
|
#define SYMBOLSIZE 255
|
|
|
|
int fUseSavedSymbol = FALSE;
|
|
int *piLineNumber = NULL;
|
|
CHAR szSavedSymbol[ SYMBOLSIZE];
|
|
|
|
/*
|
|
* Function Predefinitions:
|
|
*/
|
|
static int GetResourceType( CHAR sz[]);
|
|
static int AddStructureElement( int iType,
|
|
int nSize,
|
|
FPCUSTRESTEMPLATE *ppCRT,
|
|
int fMerge);
|
|
#ifdef RLWIN32
|
|
static void AddToW( TCHAR *sz, int *c, int lTarget, TCHAR ch);
|
|
static TCHAR *CheckBufSizeW(
|
|
int *lTarget, //... Length of output buffer
|
|
int cOutBufLen, //... Bytes already used in output buffer
|
|
int cDelta, //... # characters we want to add to output buffer
|
|
TCHAR *szOutBuf); //... ptr to output buffer
|
|
#endif
|
|
|
|
static CHAR *CheckBufSize(
|
|
int *lTarget, //... Length of output buffer
|
|
int cOutBufLen, //... Bytes already used in output buffer
|
|
int cDelta, //... # characters we want to add to output buffer
|
|
CHAR *szOutBuf); //... ptr to output buffer
|
|
static void AddTo( CHAR *sz, int *c, int lTarget, CHAR ch);
|
|
static int UngetSymbol( CHAR sz[]);
|
|
static int GetNextSymbol( CHAR sz[], unsigned n, FILE *f);
|
|
static int ParseBlock( FILE *f, FPCUSTRESTEMPLATE *ppCRT);
|
|
static CUSTRESNODE far * MatchResource( RESHEADER Resheader);
|
|
static void far * GetResData( enum LOCALIZABLE_TYPES wType,
|
|
unsigned uSize,
|
|
FILE *f,
|
|
DWORD *lSize);
|
|
static int PutResData( void far *pData,
|
|
enum LOCALIZABLE_TYPES wType,
|
|
unsigned uSize,
|
|
FILE *f);
|
|
static void far * GetTextData( enum LOCALIZABLE_TYPES wType,
|
|
unsigned uSize,
|
|
TCHAR sz[]);
|
|
static int PutTextData( void far *pData,
|
|
enum LOCALIZABLE_TYPES wType,
|
|
unsigned uSize,
|
|
TCHAR sz[],
|
|
int l);
|
|
int atoihex( CHAR sz[]);
|
|
|
|
/** Function: GetResourceType
|
|
* Returns the value of the number or resource type in sz.
|
|
*
|
|
* Arguments:
|
|
* sz, string containing either a positive number or a resource type
|
|
*
|
|
* Returns:
|
|
* value in resource
|
|
*
|
|
* Error Codes:
|
|
* -1 if illegal value
|
|
*
|
|
* History:
|
|
* 1/92 - initial implementation -- SteveBl
|
|
**/
|
|
static int GetResourceType( CHAR sz[])
|
|
{
|
|
int i;
|
|
|
|
if (sz[0] >= '0' && sz[0] <= '9')
|
|
{
|
|
return atoi(sz);
|
|
}
|
|
|
|
for (i = sizeof(rgResourceTypes)/sizeof(RESOURCETYPES);i--;)
|
|
{
|
|
if ( ! lstrcmpiA( sz, rgResourceTypes[i].szType) )
|
|
{
|
|
return rgResourceTypes[i].iType;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/** Function: AddStructureElement
|
|
* Adds an element's type and size to the Template list.
|
|
* If this element can be merged with the last element do so.
|
|
*
|
|
* Arguments:
|
|
* iType, how the data is interpreted
|
|
* nSize, number of bytes used by the data
|
|
* ppCRT, pointer to the next Custom Resource Template pointer
|
|
* fMerge, if true then NOTLOCALIZABLE data will be merged.
|
|
*
|
|
* Returns:
|
|
* 0 - if successful
|
|
* !0 - if unsuccessful
|
|
*
|
|
* Error Codes:
|
|
* 1 - out of memory
|
|
*
|
|
* History:
|
|
* 1/92 - initial implementation -- SteveBl
|
|
**/
|
|
|
|
static int AddStructureElement(
|
|
|
|
int iType,
|
|
int nSize,
|
|
FPCUSTRESTEMPLATE *ppCRT,
|
|
int fMerge)
|
|
{
|
|
if ( fMerge
|
|
&& ((iType == NOTLOCALIZABLE && (*ppCRT)->iType == NOTLOCALIZABLE)
|
|
|| (iType == NOTLOCALIZABLESZ && (*ppCRT)->iType == NOTLOCALIZABLESZ)
|
|
|| (iType == NOTLOCALIZABLEWSZ && (*ppCRT)->iType == NOTLOCALIZABLEWSZ)))
|
|
{
|
|
// combine this with the last one
|
|
(*ppCRT)->uSize+=nSize;
|
|
return 0;
|
|
}
|
|
// can't be combined with previous element
|
|
(*ppCRT)->pNext = (CUSTRESTEMPLATE far *)FALLOC( sizeof( CUSTRESTEMPLATE));
|
|
(*ppCRT) = (*ppCRT)->pNext;
|
|
if (!*ppCRT)
|
|
{
|
|
return 1;
|
|
}
|
|
(*ppCRT)->iType = iType;
|
|
(*ppCRT)->uSize = nSize;
|
|
(*ppCRT)->pNext = NULL;
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Function: UngetSymbol
|
|
* Causes GetNextSymbol to get this symbol next time.
|
|
*
|
|
* Arguments:
|
|
* sz, string buffer for symbol
|
|
*
|
|
* Returns:
|
|
* 0 - if successful
|
|
* 1 - if unsuccessful
|
|
*
|
|
* Error Codes:
|
|
* 1 - tried to unget two symbols in a row
|
|
*
|
|
* History:
|
|
* 1/92 - initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
static int UngetSymbol( CHAR sz[])
|
|
{
|
|
if ( fUseSavedSymbol )
|
|
{
|
|
return 1; // can only unget one symbol
|
|
}
|
|
fUseSavedSymbol = 1;
|
|
CopyMemory( szSavedSymbol, sz, min( sizeof( szSavedSymbol) - 1, lstrlenA( sz)));
|
|
szSavedSymbol[ sizeof( szSavedSymbol) - 1] = '\0';
|
|
return( 0);
|
|
}
|
|
|
|
/**
|
|
* Function: GetNextSymbol
|
|
* Retrieves the next symbol from the file f.
|
|
* Whitespace and comments are removed.
|
|
* Comments are delimited by either c type comments or
|
|
* # (in which case comment extends until end of line)
|
|
* If the fUseSavedSymbol flag is set then it gets its symbol
|
|
* from szSavedSymbol instead of the file.
|
|
*
|
|
* Arguments:
|
|
* sz - string buffer for next symbol
|
|
* n - size of buffer
|
|
* f - handle to the input file
|
|
*
|
|
* Returns:
|
|
* 0 if successful with symbol in sz
|
|
* 1 if unsuccessful (sz undefined)
|
|
*
|
|
* Error Codes:
|
|
* 1 - eof
|
|
*
|
|
* History:
|
|
* 1/92 - initial implementation -- SteveBl
|
|
**/
|
|
|
|
static int GetNextSymbol( CHAR sz[], unsigned n, FILE *f)
|
|
{
|
|
unsigned c = 0;
|
|
CHAR ch, chLast;
|
|
|
|
if ( fUseSavedSymbol )
|
|
{
|
|
CopyMemory( sz, szSavedSymbol, min( (int)n, lstrlenA( szSavedSymbol) + 1));
|
|
sz[ n == 0 ? 0 : n - 1] = '\0';
|
|
fUseSavedSymbol = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (feof(f)) return 1;
|
|
ch = (CHAR) getc(f);
|
|
if (ch == '\n')
|
|
++*piLineNumber;
|
|
}
|
|
while ((ch == ' ') ||
|
|
(ch == '\n') ||
|
|
(ch == '\t') ||
|
|
(ch == '\f') ||
|
|
(ch == '\r') ||
|
|
(ch == (CHAR)-1));
|
|
|
|
if (ch == '#') // commented rest of line
|
|
{
|
|
do
|
|
{
|
|
if (feof(f))
|
|
{
|
|
return 1;
|
|
}
|
|
ch = (CHAR) getc(f);
|
|
} while (ch != '\n');
|
|
|
|
++*piLineNumber;
|
|
return GetNextSymbol( sz, n, f);
|
|
}
|
|
|
|
if (ch == '"') // it is a label, parse to the next quote
|
|
{
|
|
do
|
|
{
|
|
if (c<n)
|
|
{
|
|
sz[c++]=ch; // write all but the last quote
|
|
}
|
|
|
|
if (feof(f))
|
|
{
|
|
return 1;
|
|
}
|
|
ch = (CHAR)getc(f);
|
|
|
|
if (ch == '\n')
|
|
{
|
|
return 1;
|
|
}
|
|
} while (ch != '"');
|
|
|
|
if (c<n)
|
|
{
|
|
sz[ c++] = '\0';
|
|
}
|
|
else
|
|
{
|
|
sz[ n == 0 ? 0 : n - 1] = '\0';
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
if (ch == '/') // possible comment
|
|
{
|
|
if (feof(f))
|
|
{
|
|
return 1;
|
|
}
|
|
ch = (CHAR) getc(f);
|
|
|
|
if (ch == '/') // commented rest of line
|
|
{
|
|
do
|
|
{
|
|
if (feof(f))
|
|
{
|
|
return 1;
|
|
}
|
|
ch = (CHAR) getc(f);
|
|
} while (ch != '\n');
|
|
|
|
++*piLineNumber;
|
|
return( GetNextSymbol( sz, n, f));
|
|
}
|
|
|
|
if (ch == '*') // commented until */
|
|
{
|
|
if (feof(f))
|
|
{
|
|
return 1;
|
|
}
|
|
ch = (CHAR) getc(f);
|
|
|
|
if (ch == '\n')
|
|
{
|
|
++*piLineNumber;
|
|
}
|
|
|
|
do
|
|
{
|
|
chLast = ch;
|
|
if (feof(f))
|
|
{
|
|
return 1;
|
|
}
|
|
ch = (CHAR) getc(f);
|
|
|
|
if (ch == '\n')
|
|
++*piLineNumber;
|
|
} while (!(chLast == '*' && ch == '/'));
|
|
return( GetNextSymbol( sz, n, f));
|
|
}
|
|
ungetc(ch, f);
|
|
}
|
|
// finally found the beginning of a symbol
|
|
if (ch < '0' || (ch > '9' && ch < '@')
|
|
|| (ch > 'Z' && ch < 'a') || ch > 'z')
|
|
{
|
|
if (c<n)
|
|
{
|
|
sz[c++] = ch;
|
|
}
|
|
if (c<n)
|
|
{
|
|
sz[c] = '\0';
|
|
}
|
|
else
|
|
{
|
|
sz[ n == 0 ? 0 : n - 1] = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (c<n)
|
|
{
|
|
sz[c++]=ch;
|
|
}
|
|
if (feof(f))
|
|
{
|
|
return 0;
|
|
}
|
|
ch = (CHAR) getc(f);
|
|
} while((ch >= '0' && ch <= '9') ||
|
|
(ch >= '@' && ch <= 'Z') ||
|
|
(ch >= 'a' && ch <= 'z'));
|
|
ungetc(ch, f);
|
|
|
|
if (c<n)
|
|
{
|
|
sz[c] = '\0';
|
|
}
|
|
else
|
|
{
|
|
sz[ n == 0 ? 0 : n - 1] = '\0';
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Function: ParseBlock
|
|
* Parses a block of a custom resource description from just after the
|
|
* first curly braces { to just after the closing curly braces } .
|
|
* It returns the size of the block it just parsed (in bytes).
|
|
*
|
|
* Arguments:
|
|
* f, handle to an open description file
|
|
* ppCRT, pointer to a pointer to the next Custom Resource Template node.
|
|
*
|
|
* Returns:
|
|
* Updated pointer to the next Custom Resource Template node.
|
|
* Number of bytes in this block.
|
|
* (<0 if there was an error)
|
|
*
|
|
* Error Codes:
|
|
* -1 - Syntax error
|
|
* -2 - Unexpected end of file
|
|
* -3 - out of memory
|
|
*
|
|
* History:
|
|
* 1/92 - initial implementation -- SteveBl
|
|
*/
|
|
|
|
static int ParseBlock( FILE *f, FPCUSTRESTEMPLATE * ppCRT)
|
|
{
|
|
int c = 0; // size of the whole block
|
|
int n = 0; // size of the current item
|
|
int i; //scratch variable
|
|
int fUnsigned;
|
|
int fLong;
|
|
int iType; // type of the current item
|
|
int nElements; // size of the array (if one exists)
|
|
CHAR szSymbol[SYMBOLSIZE], sz[SYMBOLSIZE];
|
|
CUSTRESTEMPLATE far * pFirst,
|
|
// saves the first one so we know where to count
|
|
// from in case of an array
|
|
far *pTemp, far *pEnd;
|
|
int fMerge = 0;
|
|
// it's only ok to merge after the first element has been written
|
|
|
|
while (1)
|
|
{
|
|
pFirst = *ppCRT;
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0] == '}')
|
|
{
|
|
return c;
|
|
}
|
|
|
|
if ( ! lstrcmpiA( "near", szSymbol) )
|
|
{ // near * type
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0]!='*')
|
|
{
|
|
return -1;
|
|
}
|
|
// may want to check for a legal type here
|
|
do
|
|
{
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
} while ((szSymbol[0] != '[') &&
|
|
(szSymbol[0] != '}') &&
|
|
(szSymbol[0] != ','));
|
|
|
|
UngetSymbol(szSymbol);
|
|
n = 2;
|
|
iType = NOTLOCALIZABLE;
|
|
|
|
if (AddStructureElement(iType, n, ppCRT, fMerge))
|
|
{
|
|
return -3;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! lstrcmpiA( "far", szSymbol) )
|
|
{ // far * type
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0] != '*')
|
|
{
|
|
return -1;
|
|
}
|
|
// may want to check for a legal type here
|
|
do
|
|
{
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
} while ((szSymbol[0] != '[') &&
|
|
(szSymbol[0] != '}') &&
|
|
(szSymbol[0] != ','));
|
|
|
|
UngetSymbol(szSymbol);
|
|
n = 4;
|
|
iType = NOTLOCALIZABLE;
|
|
|
|
if(AddStructureElement(iType, n, ppCRT, fMerge))
|
|
{
|
|
return -3;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if (szSymbol[0] == '*')
|
|
{ // * type
|
|
// may want to check for a legal type here
|
|
do
|
|
{
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
} while ((szSymbol[0] != '[') &&
|
|
(szSymbol[0] != '}') &&
|
|
(szSymbol[0] != ','));
|
|
|
|
UngetSymbol(szSymbol);
|
|
n = 2;
|
|
iType = NOTLOCALIZABLE;
|
|
|
|
if(AddStructureElement(iType, n, ppCRT, fMerge))
|
|
{
|
|
return -3;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (szSymbol[0] == '{')
|
|
{
|
|
n = ParseBlock(f, ppCRT);
|
|
|
|
if (n<0)
|
|
{
|
|
return n;
|
|
}
|
|
}
|
|
else
|
|
{ //it must be in our list of types
|
|
fUnsigned = 0;
|
|
fLong = 0;
|
|
|
|
if ( ! lstrcmpiA( "UNSIGNED", szSymbol) )
|
|
{ // unsigned
|
|
if ( GetNextSymbol( sz, sizeof( sz), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (sz[0] == '[' || sz[0] == ',')
|
|
{
|
|
UngetSymbol(sz);
|
|
}
|
|
else
|
|
{
|
|
lstrcpyA( szSymbol, sz);
|
|
|
|
if ( lstrcmpiA( sz, "SHORT")
|
|
&& lstrcmpiA( sz, "LONG")
|
|
&& lstrcmpiA( sz, "CHAR")
|
|
&& lstrcmpiA( sz, "TCHAR")
|
|
&& lstrcmpiA( sz, "INT") )
|
|
{
|
|
// must be followed by one of these
|
|
return -1;
|
|
}
|
|
}
|
|
fUnsigned = 1;
|
|
}
|
|
else
|
|
{
|
|
if ( ! lstrcmpiA( "SIGNED", szSymbol) )
|
|
{ // signed
|
|
if ( GetNextSymbol( sz, sizeof( sz), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (sz[0] == '[' || sz[0] == ',')
|
|
{
|
|
UngetSymbol(sz);
|
|
}
|
|
else
|
|
{
|
|
lstrcpyA( szSymbol, sz);
|
|
|
|
if ( lstrcmpiA( sz, "SHORT")
|
|
&& lstrcmpiA( sz, "LONG")
|
|
&& lstrcmpiA( sz, "CHAR")
|
|
&& lstrcmpiA( sz, "TCHAR")
|
|
&& lstrcmpiA( sz, "INT") )
|
|
{
|
|
// must be followed by one of these
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! lstrcmpiA( "SHORT", szSymbol) )
|
|
{ // short
|
|
if ( GetNextSymbol( sz, sizeof( sz), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (sz[0] == '[' || sz[0] == ',')
|
|
{
|
|
UngetSymbol(sz);
|
|
}
|
|
else
|
|
{
|
|
lstrcpyA( szSymbol, sz);
|
|
|
|
if ( lstrcmpiA( sz, "INT") )
|
|
{
|
|
// must be followed by one of these
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( ! lstrcmpiA( "LONG", szSymbol) )
|
|
{ // long
|
|
if ( GetNextSymbol( sz, sizeof( sz), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (sz[0] == '[' || sz[0] == ',')
|
|
{
|
|
UngetSymbol(sz);
|
|
}
|
|
else
|
|
{
|
|
lstrcpyA( szSymbol, sz);
|
|
|
|
if ( lstrcmpiA( sz, "INT")
|
|
&& lstrcmpiA( sz, "DOUBLE"))
|
|
{
|
|
// must be followed by one of these
|
|
return -1;
|
|
}
|
|
}
|
|
// BUG! - this code allows UNSIGNED LONG DOUBLE
|
|
// which is an illegal type in c. But it's not
|
|
// a serious bug so I'll leave it.
|
|
fLong = 1;
|
|
}
|
|
}
|
|
|
|
i = sizeof(rgTypeSizes)/sizeof(TYPESIZES);
|
|
|
|
do
|
|
{
|
|
--i;
|
|
} while ( lstrcmpiA( szSymbol, rgTypeSizes[i].szType) && i);
|
|
|
|
if ( lstrcmpiA( szSymbol, rgTypeSizes[i].szType) )
|
|
{
|
|
return -1; // type not found in the list
|
|
}
|
|
|
|
if (fLong)
|
|
{
|
|
n = rgTypeSizes[i].iLongSize;
|
|
}
|
|
else
|
|
{
|
|
n = rgTypeSizes[i].iShortSize;
|
|
}
|
|
|
|
iType = rgTypeSizes[i].iType;
|
|
|
|
if (fUnsigned)
|
|
{
|
|
iType+=LT_UNSIGNED;
|
|
}
|
|
|
|
if ( lstrcmpA( szSymbol, rgTypeSizes[i].szType) )
|
|
{
|
|
iType = NOTLOCALIZABLE; // type was not in all caps
|
|
}
|
|
|
|
if ( lstrcmpiA( szSymbol, "CHAR") == 0
|
|
|| lstrcmpiA( szSymbol, "TCHAR") == 0
|
|
|| lstrcmpiA( szSymbol, "WCHAR") == 0 )
|
|
{ // check for a string
|
|
|
|
lstrcpyA( szDHW, szSymbol); // So can be used later
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0] == '[') // we have a string
|
|
{
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0] == ']') // null terminated string
|
|
{
|
|
n = 0;
|
|
|
|
if (iType != NOTLOCALIZABLE)
|
|
{
|
|
if ( lstrcmpiA( szDHW, "CHAR") == 0 )
|
|
{
|
|
iType += LT_SZ-LT_CHAR;
|
|
}
|
|
else if ( lstrcmpiA( szDHW,
|
|
"WCHAR") == 0 )
|
|
{
|
|
iType += LT_WSZ-LT_WCHAR;
|
|
}
|
|
else
|
|
{
|
|
#ifdef RLRES32
|
|
iType += LT_WSZ-LT_WCHAR;
|
|
#else
|
|
iType += LT_SZ-LT_CHAR;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( lstrcmpiA( szDHW, "CHAR") == 0 )
|
|
{
|
|
iType = NOTLOCALIZABLESZ;
|
|
}
|
|
else if ( lstrcmpiA( szDHW,
|
|
"WCHAR") == 0 )
|
|
{
|
|
iType = NOTLOCALIZABLEWSZ;
|
|
}
|
|
else
|
|
{
|
|
#ifdef RLWIN32
|
|
iType = NOTLOCALIZABLEWSZ;
|
|
#else
|
|
iType = NOTLOCALIZABLESZ;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
i = atoi(szSymbol);
|
|
|
|
if (i<1)
|
|
{
|
|
return -1;
|
|
}
|
|
n *= i;
|
|
|
|
if (iType != NOTLOCALIZABLE)
|
|
{
|
|
if ( lstrcmpiA( szDHW, "CHAR") == 0 )
|
|
{
|
|
iType += LT_STRING-LT_CHAR;
|
|
}
|
|
else if ( lstrcmpiA( szDHW,
|
|
"WCHAR") == 0 )
|
|
{
|
|
iType += LT_WSTRING-LT_WCHAR;
|
|
}
|
|
else
|
|
{
|
|
#ifdef RLRES32
|
|
iType += LT_WSTRING-LT_WCHAR;
|
|
#else
|
|
iType += LT_STRING-LT_CHAR;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0] != ']')
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UngetSymbol(szSymbol);
|
|
}
|
|
}
|
|
|
|
if(AddStructureElement(iType, n, ppCRT, fMerge))
|
|
{
|
|
return -3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
while (szSymbol[0] == '[')
|
|
{// we have an array
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if ((szSymbol[0] < '0' || szSymbol[0] > '9') && szSymbol[0] != ']')
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
nElements = atoi(szSymbol);
|
|
|
|
if (nElements < 1)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0] != ']')
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
pEnd = *ppCRT;
|
|
|
|
if (pEnd != pFirst)
|
|
{
|
|
for (i=nElements-1;i--;)
|
|
{
|
|
pTemp = pFirst;
|
|
|
|
do
|
|
{
|
|
pTemp = pTemp->pNext;
|
|
AddStructureElement(pTemp->iType,
|
|
pTemp->uSize,
|
|
ppCRT,
|
|
0);
|
|
} while (pTemp != pEnd);
|
|
}
|
|
}
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), f) )
|
|
{
|
|
return -2;
|
|
}
|
|
}
|
|
c += n;
|
|
|
|
if (szSymbol[0] == '}')
|
|
{
|
|
return c;
|
|
}
|
|
|
|
if (szSymbol[0] != ',')
|
|
{
|
|
return -1;
|
|
}
|
|
fMerge = 1;
|
|
}
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Function: LoadCustResDescriptions, Public
|
|
//
|
|
// Synopsis: Loads the Cusutom Resource Descriptions defined in the RDF
|
|
// files, to all the tokenize to parse them.
|
|
//
|
|
//
|
|
// Arguments: [szFileName] The RDF file containing the resource
|
|
// descriptions.
|
|
//
|
|
//
|
|
// Effects: The custom resources are loaded into a global list of
|
|
// resource descriptions, and used by ReadWinRes to tokenize
|
|
// the particular custom resources
|
|
//
|
|
// Returns: -1 Error Condition
|
|
// 1 Resource descrptions loaded
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// Modifies: [pCustResList] Global list of Custom resource descriptions.
|
|
//
|
|
// History:
|
|
// 16-Oct-92 Created TerryRu
|
|
//
|
|
//
|
|
// Notes: ParseResourceDescriptionFile is the function called to
|
|
// actually load the descriptions resources.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
int LoadCustResDescriptions( CHAR *szRDFs)
|
|
{
|
|
FILE *fRdf = NULL;
|
|
CHAR szCurRDF[MAXFILENAME] = "";
|
|
int i1, i2;
|
|
|
|
if (szRDFs && *szRDFs) //... resource description file name given?
|
|
{
|
|
i1 = 0;
|
|
|
|
while (szRDFs[i1] == ' ' && szRDFs[i1] != 0)
|
|
{
|
|
++i1;
|
|
}
|
|
|
|
while (szRDFs[i1] != 0)
|
|
{
|
|
i2 = 0;
|
|
|
|
while (szRDFs[i1] != ' ' && szRDFs[i1] != 0)
|
|
{
|
|
szCurRDF[i2++] = szRDFs[i1++];
|
|
}
|
|
szCurRDF[i2] = 0;
|
|
|
|
while (szRDFs[i1] == ' ' && szRDFs[i1] != 0)
|
|
{
|
|
++i1;
|
|
}
|
|
|
|
if (fRdf = FOPEN( szCurRDF, "rt"))
|
|
{
|
|
ParseResourceDescriptionFile(fRdf, &i2);
|
|
FCLOSE(fRdf);
|
|
}
|
|
else
|
|
{
|
|
return(-1);
|
|
}
|
|
}
|
|
}
|
|
return(1); //... Success
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Function: ParseResourceDescriptionFile
|
|
* Parses a resource description block creating a structure definining
|
|
* all recognized custom resources.
|
|
*
|
|
* Arguments:
|
|
* ResourceDescriptionFile, handle to an open description file
|
|
* (or the beginning of a description block)
|
|
* piErrorLine, pointer to an integer that will hold the line number
|
|
* an error occured at in the event that a parsing error is
|
|
* encountered.
|
|
*
|
|
* Returns:
|
|
* 0 if successful
|
|
* !0 if some error was encountered
|
|
* *piErrorLine will hold the line number for the error
|
|
*
|
|
* Error Codes:
|
|
* -1 - Syntax error
|
|
* -2 - Unexpected end of file
|
|
* -3 - out of memory
|
|
*
|
|
* History:
|
|
* 1/92 - initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
int ParseResourceDescriptionFile(
|
|
|
|
FILE *pfResourceDescriptionFile,
|
|
int *piErrorLine)
|
|
{
|
|
CUSTRESNODE far * lpCustResNode = NULL;
|
|
CUSTRESTEMPLATE far * pCustResTemplate;
|
|
static CHAR szSymbol[SYMBOLSIZE];
|
|
/*************************************************************************
|
|
TCHAR *szResourceType;
|
|
*************************************************************************/
|
|
int iResourceType;
|
|
int r;
|
|
BOOL fBeginList = TRUE;
|
|
|
|
// position lpCustResNode at end of the custom reosource list.
|
|
if ( lpCustResNode == NULL )
|
|
{
|
|
pCustResList = lpCustResNode =
|
|
(CUSTRESNODE far *)FALLOC( sizeof( CUSTRESNODE));
|
|
}
|
|
else
|
|
{
|
|
fBeginList = FALSE;
|
|
lpCustResNode = pCustResList;
|
|
|
|
while ( lpCustResNode->pNext )
|
|
{
|
|
lpCustResNode = lpCustResNode->pNext;
|
|
}
|
|
}
|
|
piLineNumber = piErrorLine;
|
|
*piLineNumber = 1;
|
|
|
|
|
|
if ( GetNextSymbol( szSymbol,
|
|
sizeof( szSymbol),
|
|
pfResourceDescriptionFile) )
|
|
{
|
|
return 0; // file is empty
|
|
}
|
|
|
|
while ( lstrcmpiA( szSymbol, "END") )
|
|
{
|
|
if ( szSymbol[0] != '<' )
|
|
{
|
|
return -1; // must begin with a resource number
|
|
}
|
|
|
|
if ( fBeginList == FALSE )
|
|
{
|
|
lpCustResNode->pNext =
|
|
(CUSTRESNODE far *)FALLOC( sizeof( CUSTRESNODE));
|
|
lpCustResNode = lpCustResNode->pNext;
|
|
}
|
|
fBeginList = FALSE;
|
|
|
|
// intialize nodes fields to Zero defaults.
|
|
|
|
memset( lpCustResNode, 0, sizeof( CUSTRESNODE));
|
|
|
|
//... Next symbol will be the resource type
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), pfResourceDescriptionFile) )
|
|
{
|
|
return -2; // need a number
|
|
}
|
|
//... Is type a string or a number?
|
|
if ( szSymbol[0] != '"' )
|
|
{ //... number
|
|
iResourceType = GetResourceType( szSymbol);
|
|
|
|
if ( iResourceType < 0 )
|
|
{
|
|
return -1;
|
|
}
|
|
lpCustResNode->wTypeID = (WORD)iResourceType;
|
|
lpCustResNode->bTypeFlag = TRUE;
|
|
}
|
|
else //... string
|
|
{
|
|
UINT uChars = lstrlenA( szSymbol+1) + 1;
|
|
|
|
lpCustResNode->pszType = (TCHAR *)FALLOC( MEMSIZE( uChars));
|
|
|
|
if ( lpCustResNode->pszType == NULL )
|
|
{
|
|
return -3;
|
|
}
|
|
_MBSTOWCS( lpCustResNode->pszType, szSymbol+1, uChars, (UINT)-1);
|
|
lpCustResNode->bTypeFlag = FALSE;
|
|
}
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), pfResourceDescriptionFile) )
|
|
{
|
|
return -2;
|
|
}
|
|
/*************************************************************************
|
|
//... Is a name provided?
|
|
|
|
if (szSymbol[0] != '>' && szSymbol[0] != ',')
|
|
{
|
|
return -1; // must have closing symbol for resource id #
|
|
}
|
|
|
|
if (szSymbol[0] == ',')
|
|
{ //... Yes, name is provided
|
|
if (iResourceType >= 0)
|
|
{
|
|
lpCustResNode->wNameID = (WORD)iResourceType;
|
|
lpCustResNode->bNameFlag = TRUE;
|
|
}
|
|
else
|
|
{
|
|
lpCustResNode->wTypeID = 0;
|
|
lpCustResNode->wNameID = IDFLAG;
|
|
lpCustResNode->pszType = szResourceType;
|
|
lpCustResNode->bTypeFlag = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (iResourceType >= 0)
|
|
{
|
|
lpCustResNode->wNameID = iResourceType;
|
|
}
|
|
else
|
|
{
|
|
lpCustResNode->wNameID = 0;
|
|
lpCustResNode->pszName = szResourceType;
|
|
lpCustResNode->bNameFlag = 0xff;
|
|
}
|
|
|
|
if (GetNextSymbol(szSymbol, sizeof( szSymbol), pfResourceDescriptionFile))
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0] != '"')
|
|
{
|
|
r = GetResourceType(szSymbol);
|
|
lpCustResNode->wTypeID = (WORD)r;
|
|
}
|
|
else
|
|
{
|
|
lpCustResNode->wTypeID = 0;
|
|
lpCustResNode->bTypeFlag = 0;
|
|
szResourceType = (TCHAR *)FALLOC(
|
|
MEMSIZE( (strlen( szSymbol + 1) + 1)));
|
|
strcpy((PCHAR)szResourceType, szSymbol+1);
|
|
lpCustResNode->pszType = szResourceType;
|
|
}
|
|
if (GetNextSymbol(szSymbol, sizeof( szSymbol), pfResourceDescriptionFile))
|
|
{
|
|
return -2;
|
|
}
|
|
if (szSymbol[0] != '>')
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
*************************************************************************/
|
|
|
|
// Start the template by creating a single empty node
|
|
// This is necessary for handling recursive arrays.
|
|
// There might be a way around it but this works and it is easy.
|
|
lpCustResNode->pTemplate=
|
|
(FPCUSTRESTEMPLATE)FALLOC( sizeof( CUSTRESTEMPLATE));
|
|
|
|
if (!lpCustResNode->pTemplate)
|
|
{
|
|
return -3;
|
|
}
|
|
|
|
pCustResTemplate = (lpCustResNode->pTemplate);
|
|
pCustResTemplate->iType = NOTLOCALIZABLE;
|
|
pCustResTemplate->uSize = 0;
|
|
pCustResTemplate->pNext = NULL;
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), pfResourceDescriptionFile) )
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
if (szSymbol[0] != '{')
|
|
{
|
|
return -1; // must have at least one block
|
|
}
|
|
|
|
r = ParseBlock( pfResourceDescriptionFile,
|
|
(FPCUSTRESTEMPLATE *)&pCustResTemplate);
|
|
if (r < 0)
|
|
{
|
|
return r;
|
|
}
|
|
|
|
// Now remove that initial empty node (not necessary but cleaner)
|
|
pCustResTemplate = lpCustResNode->pTemplate;
|
|
lpCustResNode->pTemplate = pCustResTemplate->pNext;
|
|
RLFREE( pCustResTemplate);
|
|
|
|
// the last thing the ParseBlock routine should have read in was a
|
|
// closing brace to close the block. The next thing we read should
|
|
// either be "end", the end of file, or a new resource definition.
|
|
|
|
if ( GetNextSymbol( szSymbol, sizeof( szSymbol), pfResourceDescriptionFile) )
|
|
{
|
|
return 0; // reached end of file
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Function: GetCustomResource
|
|
* Reads a custom resource from the resource file and returns a pointer
|
|
* to the resource data.
|
|
*
|
|
* Arguments:
|
|
* inResFile, handle to an open resource file
|
|
* lSize, size in bytes of the resource
|
|
* ppCustomResource, address of a pointer to an empty custom resource
|
|
* structure
|
|
* ResHeader, resource header for this resource
|
|
*
|
|
* Returns:
|
|
* if resource has a definition:
|
|
* returns 0 and
|
|
* inResFile containing a linked list of the localizable resource data
|
|
* else
|
|
* returns 1
|
|
*
|
|
* Error Codes:
|
|
* 0 - no error -- resource was retrieved
|
|
* 1 - resource is not an understood custom resource (use another method
|
|
* or ignore the resource)
|
|
* 2 - some error occured parsing the resource
|
|
*
|
|
* History:
|
|
* 1/92 - initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
int GetCustomResource(
|
|
|
|
FILE *inResFile,
|
|
DWORD *plSize,
|
|
FPCUSTOM_RESOURCE *ppCustomResource,
|
|
RESHEADER ResHeader)
|
|
{
|
|
CUSTOM_RESOURCE far *lpCustomResource;
|
|
CUSTRESNODE far *pCRN;
|
|
CUSTRESTEMPLATE far *pCRT;
|
|
void far * pData;
|
|
BOOL fBeginList = TRUE;
|
|
|
|
|
|
if ( ! (pCRN = MatchResource( ResHeader)) )
|
|
{
|
|
return 1; // resource doesn't have a match
|
|
}
|
|
|
|
*ppCustomResource = lpCustomResource =
|
|
(CUSTOM_RESOURCE far *)FALLOC( sizeof( CUSTOM_RESOURCE));
|
|
pCRT = pCRN->pTemplate;
|
|
|
|
while ( *plSize )
|
|
{
|
|
// allocate new custome resrouce structure
|
|
|
|
if ( fBeginList == FALSE )
|
|
{
|
|
lpCustomResource->pNext =
|
|
(CUSTOM_RESOURCE far *)FALLOC( sizeof( CUSTOM_RESOURCE));
|
|
lpCustomResource = lpCustomResource->pNext;
|
|
}
|
|
|
|
if ( ! lpCustomResource )
|
|
{
|
|
return 2; // no memory
|
|
}
|
|
pData = GetResData( pCRT->iType, pCRT->uSize, inResFile, plSize);
|
|
|
|
if ( ! pData )
|
|
{
|
|
return 2; //GetResData crapped out
|
|
}
|
|
lpCustomResource->pData = pData;
|
|
lpCustomResource->pNext = NULL;
|
|
fBeginList = FALSE;
|
|
|
|
pCRT = pCRT->pNext;
|
|
|
|
if (!pCRT)
|
|
{
|
|
pCRT = pCRN->pTemplate; //begin next structure
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Function: TokCustomResource
|
|
* Writes custom resource information to the token file.
|
|
*
|
|
* Arguments:
|
|
* TokFile, handle to the token file
|
|
* ResHeader, resource header for this resource
|
|
* ppCustomResource, address of a pointer to a filled out
|
|
* custom resource structure
|
|
*
|
|
* Returns:
|
|
* Data written to TokFile
|
|
*
|
|
* Error Codes:
|
|
* none
|
|
*
|
|
* History:
|
|
* 1/92 - initial implementation -- SteveBl
|
|
*
|
|
* 01/93 - Add support for var length Token texts MHotchin
|
|
*
|
|
**/
|
|
|
|
void TokCustomResource(
|
|
|
|
FILE *TokFile,
|
|
RESHEADER ResHeader,
|
|
FPCUSTOM_RESOURCE *ppCustomResource)
|
|
{
|
|
CUSTRESNODE far *pCRN;
|
|
CUSTRESTEMPLATE far *pCRT;
|
|
CUSTOM_RESOURCE far *lpCustomResource;
|
|
TCHAR sz[ MAXTEXTLEN];
|
|
TOKEN Token;
|
|
WORD wID = 0;
|
|
int l;
|
|
|
|
|
|
lpCustomResource = *ppCustomResource;
|
|
|
|
if (!(pCRN = MatchResource(ResHeader)))
|
|
{
|
|
QuitT( IDS_ENGERR_09, (LPTSTR)IDS_NOCUSTRES, NULL);
|
|
}
|
|
|
|
pCRT = pCRN->pTemplate;
|
|
|
|
while ( lpCustomResource )
|
|
{
|
|
if ( pCRT->iType != NOTLOCALIZABLE
|
|
&& pCRT->iType != NOTLOCALIZABLESZ
|
|
&& pCRT->iType != NOTLOCALIZABLEWSZ )
|
|
{
|
|
if ( PutTextData( lpCustomResource->pData,
|
|
pCRT->iType,
|
|
pCRT->uSize,
|
|
sz,
|
|
sizeof( sz)) )
|
|
{
|
|
QuitT( IDS_ENGERR_09, (LPTSTR)IDS_CUSTRES, NULL);
|
|
}
|
|
/* UNCOMMENT THIS WHEN STRING TYPES ARE SUPPORTED IN TOKENS
|
|
**********
|
|
Token.szType[0] = '\0';
|
|
if (!ResHeader.bTypeFlag)
|
|
{
|
|
Token.wType = IDFLAG;
|
|
_tcscpy( Token.szType, ResHeader.pszType);
|
|
}
|
|
else
|
|
**********
|
|
*/
|
|
Token.wType = ResHeader.wTypeID;
|
|
Token.wName = ResHeader.wNameID;
|
|
|
|
if ( ResHeader.bNameFlag == IDFLAG )
|
|
{
|
|
lstrcpy( Token.szName, ResHeader.pszName);
|
|
}
|
|
else
|
|
{
|
|
Token.szName[0] = '\0';
|
|
}
|
|
Token.wID = wID++;
|
|
Token.wReserved = (gbMaster ? ST_NEW : ST_TRANSLATED);
|
|
Token.wFlag = 0;
|
|
|
|
if ( (pCRT->iType == LT_UNSIGNED + LT_STRING)
|
|
|| (pCRT->iType == LT_STRING)
|
|
|| (pCRT->iType == LT_WSTRING) )
|
|
{
|
|
l = pCRT->uSize;
|
|
while( l > 1 && ! sz[l-1])
|
|
{
|
|
--l; // skip any trailing nulls
|
|
}
|
|
Token.szText = BinToText( sz, l);
|
|
}
|
|
else
|
|
{
|
|
Token.szText = BinToText( sz, lstrlen( sz));
|
|
}
|
|
PutToken( TokFile, &Token);
|
|
RLFREE( Token.szText);
|
|
}
|
|
pCRT = pCRT->pNext;
|
|
|
|
if ( ! pCRT )
|
|
{
|
|
pCRT = pCRN->pTemplate; //begin next structure
|
|
}
|
|
lpCustomResource = lpCustomResource->pNext;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function: PutCustomResource
|
|
* Writes custom resource information to the output resource
|
|
* file. If the information is localizable it is retrieved from the
|
|
* indicated token file.
|
|
*
|
|
* Arguments:
|
|
* OutResFile, handle to the target resource file
|
|
* TokFile, handle to the token file
|
|
* ResHeader, resource header for this resource
|
|
* ppCustomResource, address of a pointer to a filled out
|
|
* custom resource structure
|
|
*
|
|
* Returns:
|
|
* CustomResource written to OutResFile
|
|
*
|
|
* Error Codes:
|
|
* none
|
|
*
|
|
* History:
|
|
* ??/?? Created by ???
|
|
*
|
|
* 01/93 Added support for var length token texts. MHotchin
|
|
*
|
|
**/
|
|
|
|
void PutCustomResource(
|
|
|
|
FILE *OutResFile,
|
|
FILE *TokFile,
|
|
RESHEADER ResHeader,
|
|
FPCUSTOM_RESOURCE *ppCustomResource)
|
|
{
|
|
CUSTRESNODE far *pCRN = NULL;
|
|
CUSTRESTEMPLATE far *pCRT = NULL;
|
|
CUSTOM_RESOURCE far *lpCustomResource = NULL;
|
|
TCHAR sz[ MAXTEXTLEN] = TEXT("");
|
|
void far *pData = NULL;
|
|
TOKEN Token;
|
|
DWORD lSize = 0;
|
|
fpos_t ResSizePos;
|
|
WORD wID=0;
|
|
unsigned n;
|
|
|
|
|
|
lpCustomResource = *ppCustomResource;
|
|
|
|
if ( ! (pCRN = MatchResource( ResHeader)) )
|
|
{
|
|
QuitT( IDS_ENGERR_09, (LPTSTR)IDS_NOCUSTRES, NULL);
|
|
}
|
|
|
|
if ( PutResHeader( OutResFile, ResHeader, &ResSizePos, &lSize) )
|
|
{
|
|
QuitT( IDS_ENGERR_06, (LPTSTR)IDS_CUSTRES, NULL);
|
|
}
|
|
|
|
lSize = 0;
|
|
|
|
pCRT = pCRN->pTemplate;
|
|
|
|
while ( lpCustomResource )
|
|
{
|
|
BOOL fAlloced = FALSE;
|
|
|
|
if ( pCRT->iType != NOTLOCALIZABLE
|
|
&& pCRT->iType != NOTLOCALIZABLESZ
|
|
&& pCRT->iType != NOTLOCALIZABLEWSZ )
|
|
{
|
|
/* UNCOMMENT THIS WHEN STRING TYPES ARE SUPPORTED IN TOKENS
|
|
*
|
|
Token.szwType[0] = '\0';
|
|
if (!ResHeader.bTypeFlag)
|
|
{
|
|
Token.wType = IDFLAG;
|
|
_tcscpy(Token.szwType, ResHeader.pszType);
|
|
}
|
|
else
|
|
*
|
|
*/
|
|
Token.wType = ResHeader.wTypeID;
|
|
Token.wName = ResHeader.wNameID;
|
|
|
|
if ( ResHeader.bNameFlag == IDFLAG )
|
|
{
|
|
lstrcpy( Token.szName, ResHeader.pszName);
|
|
}
|
|
else
|
|
{
|
|
Token.szName[0] = '\0';
|
|
}
|
|
Token.wID = wID++;
|
|
Token.wFlag = 0;
|
|
Token.wReserved =(gbMaster ? ST_NEW : ST_TRANSLATED);
|
|
Token.szText = NULL;
|
|
|
|
if ( ! FindToken( TokFile, &Token, ST_TRANSLATED) )
|
|
{
|
|
QuitT( IDS_ENGERR_06, (LPTSTR)IDS_NOCUSTRES, NULL);
|
|
}
|
|
n = TextToBin( sz, Token.szText, sizeof( sz));
|
|
RLFREE( Token.szText);
|
|
|
|
while ( n < pCRT->uSize )
|
|
{
|
|
sz[n++]='\0'; // padd additional space with nulls
|
|
}
|
|
pData = GetTextData( pCRT->iType, pCRT->uSize, sz);
|
|
|
|
if ( ! pData)
|
|
{
|
|
QuitT( IDS_ENGERR_09, (LPTSTR)IDS_CUSTRES, NULL);
|
|
}
|
|
fAlloced = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pData = lpCustomResource->pData;
|
|
fAlloced = FALSE;
|
|
}
|
|
|
|
lSize += PutResData( pData, pCRT->iType, pCRT->uSize, OutResFile);
|
|
|
|
if ( fAlloced )
|
|
{
|
|
RLFREE( pData);
|
|
}
|
|
pCRT = pCRT->pNext;
|
|
|
|
if ( ! pCRT )
|
|
{
|
|
pCRT = pCRN->pTemplate; //begin next structure
|
|
}
|
|
lpCustomResource = lpCustomResource->pNext;
|
|
}
|
|
|
|
if( ! UpdateResSize( OutResFile, &ResSizePos, lSize) )
|
|
{
|
|
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_CUSTRES, NULL);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function: ClearCustomResource
|
|
* Frees memory allocated to a custom resource list.
|
|
*
|
|
* Arguments:
|
|
* ppCustomResource, address of a pointer to a filled out
|
|
* custom resource structure
|
|
*
|
|
* Returns:
|
|
* Memory allocatd to pCustomResource is freed.
|
|
*
|
|
* Error Codes:
|
|
* none
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
void ClearCustomResource( FPCUSTOM_RESOURCE *ppCustomResource)
|
|
{
|
|
CUSTOM_RESOURCE far *pCR;
|
|
CUSTOM_RESOURCE far *lpCustomResource;
|
|
|
|
lpCustomResource = *ppCustomResource;
|
|
|
|
while ( lpCustomResource )
|
|
{
|
|
pCR = lpCustomResource;
|
|
|
|
RLFREE( pCR->pData);
|
|
|
|
lpCustomResource = pCR->pNext;
|
|
RLFREE( pCR);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function:
|
|
* Tries to find a custom resource that matches the resource specified
|
|
* in the resource header.
|
|
*
|
|
* Arguments:
|
|
* Resheader, resource header.
|
|
*
|
|
* Returns:
|
|
* pointer to the resource template (or null)
|
|
*
|
|
* Error Codes:
|
|
* null -- resource not found
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
static CUSTRESNODE far * MatchResource( RESHEADER Resheader)
|
|
{
|
|
CUSTRESNODE far *pCR = pCustResList;
|
|
|
|
|
|
while ( pCR )
|
|
{
|
|
if ( (0==pCR->bTypeFlag) == (0==Resheader.bTypeFlag) )
|
|
{
|
|
if ( ((!pCR->bTypeFlag) && ! _tcscmp( pCR->pszType,
|
|
Resheader.pszType))
|
|
|| ((pCR->bTypeFlag) && pCR->wTypeID == Resheader.wTypeID))
|
|
{ // TYPES MATCH
|
|
/*************************************************************************
|
|
|
|
if (pCR->wNameID == IDFLAG)
|
|
{
|
|
pCRTypeMatch = pCR;
|
|
}
|
|
else
|
|
{
|
|
if ((0==pCR->bNameFlag) == (0==Resheader.bNameFlag))
|
|
{
|
|
if (((!pCR->bNameFlag)
|
|
&& ! _tcscmp(pCR->pszName, Resheader.pszName)) ||
|
|
((pCR->bNameFlag) &&
|
|
pCR->wNameID == Resheader.wNameID))
|
|
{ // NAMES MATCH
|
|
*************************************************************************/
|
|
return( pCR); // an exact match
|
|
/*************************************************************************
|
|
}
|
|
}
|
|
}
|
|
*************************************************************************/
|
|
}
|
|
}
|
|
pCR = pCR->pNext;
|
|
}
|
|
return( NULL); // either only the type matched or nothing matched
|
|
}
|
|
|
|
/**
|
|
* Function: GetResData
|
|
* Reads data of the specified type and size from a resource file.
|
|
*
|
|
* Arguments:
|
|
* wType, type of this resource (from resource template)
|
|
* uSize, size in bytes of resource (ignored for null terminated strings)
|
|
* f, resource file
|
|
* lSize, pointer to the number of bytes left in the resource
|
|
*
|
|
* Returns:
|
|
* pointer to the data, lSize is updated
|
|
*
|
|
* Error Codes:
|
|
* null pointer on error
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
static void far * GetResData(
|
|
|
|
enum LOCALIZABLE_TYPES wType,
|
|
unsigned uSize,
|
|
FILE *f,
|
|
DWORD *lSize)
|
|
{
|
|
BYTE *pData = NULL;
|
|
int i = 0;
|
|
|
|
|
|
if ( wType % LT_UNSIGNED == LT_SZ
|
|
|| wType == NOTLOCALIZABLESZ
|
|
|| wType % LT_UNSIGNED == LT_WSZ
|
|
|| wType == NOTLOCALIZABLEWSZ )
|
|
{ // read in the null terminated string
|
|
TCHAR ch = IDFLAG;
|
|
|
|
|
|
pData = FALLOC( MEMSIZE(*lSize) );
|
|
|
|
while ( *lSize && ch != TEXT('\0') )
|
|
{
|
|
#ifdef RLWIN32
|
|
|
|
if ( wType % LT_UNSIGNED == LT_WSZ
|
|
|| wType == NOTLOCALIZABLEWSZ )
|
|
{
|
|
((TCHAR *)pData)[i] = ch = GetWord( f, lSize);
|
|
}
|
|
else
|
|
{
|
|
char chTmp[2];
|
|
|
|
|
|
chTmp[0] = GetByte( f, lSize);
|
|
|
|
if ( IsDBCSLeadByte( chTmp[0]) )
|
|
{
|
|
chTmp[1] = GetByte( f, lSize);
|
|
_MBSTOWCS( &((TCHAR *)pData)[i], chTmp, 1, 2);
|
|
}
|
|
else
|
|
{
|
|
_MBSTOWCS( &((TCHAR *)pData)[i], chTmp, 1, 1);
|
|
}
|
|
ch = ((TCHAR *)pData)[i];
|
|
}
|
|
#else //RLWIN32
|
|
|
|
*(pData+i) = ch = GetByte( f, lSize);
|
|
|
|
#endif //RLWIN32
|
|
|
|
i++;
|
|
|
|
} // END while( *lSize ...
|
|
}
|
|
else
|
|
{
|
|
pData = FALLOC( uSize);
|
|
|
|
if ( ! pData )
|
|
{
|
|
QuitA( IDS_ENGERR_11, NULL, NULL);
|
|
}
|
|
|
|
while (uSize-- && *lSize)
|
|
{
|
|
*(pData+i) = GetByte(f, lSize);
|
|
i++;
|
|
}
|
|
}
|
|
return( pData);
|
|
}
|
|
|
|
/**
|
|
* Function: PutResData
|
|
* Writes data of the specified type to a resource file.
|
|
*
|
|
* Arguments:
|
|
* pData, pointer to data
|
|
* wType, type of this resource (from resource template)
|
|
* uSize, size in bytes of resource (ignored for null terminated strings)
|
|
* f, resource file
|
|
*
|
|
* Returns:
|
|
* Number of bytes written.
|
|
*
|
|
* Error Codes:
|
|
* -1 - error
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
static int PutResData(
|
|
|
|
void far *pData,
|
|
enum LOCALIZABLE_TYPES wType,
|
|
unsigned uSize,
|
|
FILE *f)
|
|
{
|
|
DWORD dw = 0;
|
|
|
|
if ( wType % LT_UNSIGNED == LT_SZ
|
|
|| wType == NOTLOCALIZABLESZ
|
|
|| wType % LT_UNSIGNED == LT_WSZ
|
|
|| wType == NOTLOCALIZABLEWSZ )
|
|
{
|
|
// write the null terminated string
|
|
|
|
#ifdef RLWIN32
|
|
|
|
TCHAR *pChar = (TCHAR *)pData;
|
|
|
|
if ( wType % LT_UNSIGNED == LT_WSZ
|
|
|| wType == NOTLOCALIZABLEWSZ )
|
|
{
|
|
while( *pChar )
|
|
{
|
|
PutWord( f, *pChar, &dw);
|
|
pChar++;
|
|
}
|
|
PutWord( f, 0, &dw);
|
|
}
|
|
else
|
|
{
|
|
_WCSTOMBS( szDHW, pChar, DHWSIZE, lstrlen( pChar) + 1);
|
|
|
|
while( szDHW[ dw] )
|
|
{
|
|
PutByte( f, szDHW[ dw], &dw);
|
|
}
|
|
PutByte( f, 0, &dw);
|
|
}
|
|
|
|
#else //RLWIN32
|
|
|
|
while( *((BYTE far *)pData+i) )
|
|
{
|
|
PutByte( f, *((BYTE far *)pData+dw), &dw);
|
|
}
|
|
PutByte( f, 0, &dw);
|
|
|
|
#endif //RLWIN32
|
|
|
|
}
|
|
else
|
|
{
|
|
while( dw < uSize)
|
|
{
|
|
PutByte( f, *((BYTE far *)pData+dw), &dw);
|
|
}
|
|
}
|
|
return( (int)dw);
|
|
}
|
|
|
|
/**
|
|
* Function: GetTextData
|
|
* Reads data of the specified type and size from a string.
|
|
*
|
|
* Arguments:
|
|
* wType, type of this resource (from resource template)
|
|
* uSize, size in bytes of resource (ignored for null terminated strings)
|
|
* sz, source string (always in Unicode if in NT version of tool)
|
|
*
|
|
* Returns:
|
|
* pointer to the data
|
|
*
|
|
* Error Codes:
|
|
* null pointer on error
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
static void far * GetTextData(
|
|
|
|
enum LOCALIZABLE_TYPES wType,
|
|
unsigned uSize,
|
|
TCHAR sz[])
|
|
{
|
|
PBYTE pData = NULL;
|
|
int i = 0;
|
|
|
|
|
|
if ( wType % LT_UNSIGNED == LT_WSZ
|
|
|| wType % LT_UNSIGNED == LT_SZ )
|
|
{
|
|
pData = FALLOC( MEMSIZE( MAXTEXTLEN));
|
|
}
|
|
else if ( wType % LT_UNSIGNED == LT_WSTRING
|
|
|| wType % LT_UNSIGNED == LT_STRING )
|
|
|
|
{
|
|
pData = FALLOC( MEMSIZE( uSize));
|
|
}
|
|
else
|
|
{
|
|
pData = FALLOC( uSize);
|
|
}
|
|
|
|
switch (wType)
|
|
{
|
|
case LT_CHAR:
|
|
case LT_UNSIGNED+LT_CHAR:
|
|
|
|
*pData = (BYTE) sz[0];
|
|
break;
|
|
|
|
case LT_WCHAR:
|
|
case LT_UNSIGNED+LT_WCHAR:
|
|
|
|
*((TCHAR *)pData) = sz[0];
|
|
break;
|
|
|
|
case LT_INTEGER:
|
|
|
|
if ( uSize == 2 )
|
|
{
|
|
sscanf( (PCHAR)sz, "%Fhi", pData);
|
|
}
|
|
else
|
|
{
|
|
sscanf( (PCHAR)sz, "%Fli", pData);
|
|
}
|
|
break;
|
|
|
|
case LT_UNSIGNED+LT_INTEGER:
|
|
|
|
if ( uSize == 2 )
|
|
{
|
|
sscanf( (PCHAR)sz, "%Fhu", pData);
|
|
}
|
|
else
|
|
{
|
|
sscanf( (PCHAR)sz, "%Flu", pData);
|
|
}
|
|
break;
|
|
|
|
case LT_FLOAT:
|
|
case LT_UNSIGNED+LT_FLOAT:
|
|
|
|
if ( uSize == 4 )
|
|
{
|
|
sscanf( (PCHAR)sz, "%Ff", pData);
|
|
}
|
|
else
|
|
{
|
|
sscanf( (PCHAR)sz, "%Flf", pData);
|
|
}
|
|
break;
|
|
|
|
case LT_STRING:
|
|
case LT_UNSIGNED+LT_STRING:
|
|
case LT_WSTRING:
|
|
case LT_UNSIGNED+LT_WSTRING:
|
|
|
|
for ( i = uSize; i--; )
|
|
{
|
|
*((TCHAR far *)pData + i) = sz[i];
|
|
}
|
|
break;
|
|
|
|
case LT_SZ:
|
|
case LT_UNSIGNED+LT_SZ:
|
|
case LT_WSZ:
|
|
case LT_UNSIGNED+LT_WSZ:
|
|
|
|
#ifdef RLWIN32
|
|
CopyMemory( pData, sz, MEMSIZE( min( lstrlen( sz) + 1, MAXTEXTLEN)));
|
|
#else
|
|
FSTRNCPY( (CHAR far *)pData, sz, MAXTEXTLEN);
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
|
|
RLFREE( pData);
|
|
}
|
|
return( pData);
|
|
}
|
|
|
|
/**
|
|
* Function: PutTextData
|
|
* Writes data of the specified type to a string.
|
|
*
|
|
* Arguments:
|
|
* pData, pointer to data
|
|
* wType, type of this resource (from resource template)
|
|
* uSize, size in bytes of resource (ignored for null terminated strings)
|
|
* sz, destination string
|
|
* l, length of destination string (in bytes)
|
|
*
|
|
* Returns:
|
|
* 0 - no errors
|
|
*
|
|
* Error Codes:
|
|
* 1 - error
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
*
|
|
**/
|
|
|
|
static int PutTextData(
|
|
|
|
void far *pData,
|
|
enum LOCALIZABLE_TYPES wType,
|
|
unsigned uSize,
|
|
TCHAR sz[],
|
|
int l)
|
|
{
|
|
switch (wType)
|
|
{
|
|
case LT_CHAR:
|
|
case LT_UNSIGNED+LT_CHAR:
|
|
case LT_WCHAR:
|
|
case LT_UNSIGNED+LT_WCHAR:
|
|
|
|
CopyMemory( sz, pData, min( uSize, (UINT)l));
|
|
break;
|
|
|
|
case LT_INTEGER:
|
|
|
|
if ( uSize == 2 )
|
|
{
|
|
wsprintf( sz, TEXT("%Fhi"), pData);
|
|
}
|
|
else
|
|
{
|
|
wsprintf( sz, TEXT("%Fli"), pData);
|
|
}
|
|
break;
|
|
|
|
case LT_UNSIGNED+LT_INTEGER:
|
|
|
|
if ( uSize == 2 )
|
|
{
|
|
wsprintf( sz, TEXT("%Fhu"), pData);
|
|
}
|
|
else
|
|
{
|
|
wsprintf( sz, TEXT("%Flu"), pData);
|
|
}
|
|
break;
|
|
|
|
case LT_FLOAT:
|
|
case LT_UNSIGNED+LT_FLOAT:
|
|
|
|
if ( uSize == 4 )
|
|
{
|
|
wsprintf( sz, TEXT("%Ff"), pData);
|
|
}
|
|
else
|
|
{
|
|
wsprintf( sz, TEXT("%Flf"), pData);
|
|
}
|
|
break;
|
|
|
|
case LT_STRING:
|
|
case LT_UNSIGNED+LT_STRING:
|
|
case LT_WSTRING:
|
|
case LT_UNSIGNED+LT_WSTRING:
|
|
|
|
CopyMemory( sz, pData, uSize);
|
|
break;
|
|
|
|
case LT_SZ:
|
|
case LT_UNSIGNED+LT_SZ:
|
|
|
|
CopyMemory( sz, pData, MEMSIZE(min( lstrlen( pData) + 1, l)));
|
|
((LPSTR)sz)[ l - 1] = '\0';
|
|
break;
|
|
|
|
case LT_WSZ:
|
|
case LT_UNSIGNED+LT_WSZ:
|
|
|
|
CopyMemory( sz, pData, min( MEMSIZE( lstrlen( pData) + 1), WCHARSIN( l)));
|
|
sz[ WCHARSIN( l) - 1] = TEXT('\0');
|
|
break;
|
|
|
|
//#ifdef RLWIN32
|
|
// CopyMemory( sz, pData, l > 0 ? l * sizeof( TCHAR) : 0);
|
|
//#else
|
|
// FSTRNCPY( (CHAR far *) sz, (CHAR far *)pData, l);
|
|
//#endif
|
|
break;
|
|
|
|
default:
|
|
|
|
return( 1);
|
|
}
|
|
return( 0);
|
|
}
|
|
|
|
/**
|
|
* Function: AddTo
|
|
* Adds a character to a string at position c.
|
|
* c is then incremented only if it is still less than the maximum
|
|
* length of the target string. This is to prevent runover.
|
|
*
|
|
* Arguments:
|
|
* sz, target string
|
|
* c, pointer to current position value
|
|
* lTarget, maximum length of the target string
|
|
* ch, character to be added to the string
|
|
*/
|
|
|
|
void AddTo( CHAR *sz, int *c, int lTarget, CHAR ch)
|
|
{
|
|
sz[*c] = ch;
|
|
|
|
if (*c < lTarget)
|
|
{
|
|
(*c)++;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef RLWIN32
|
|
|
|
|
|
void AddToW( TCHAR *sz, int *c, int lTarget, TCHAR ch)
|
|
{
|
|
sz[*c] = ch;
|
|
|
|
if (*c < lTarget)
|
|
{
|
|
(*c)++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function: BinToTextW
|
|
* Converts a binary string to it's c representation
|
|
* (complete with escape sequences). If the target string is NULL,
|
|
* space will be allocated for it.
|
|
*
|
|
* Arguments:
|
|
* rgc, source string
|
|
* lSource, length of source string
|
|
*
|
|
* Returns:
|
|
* nothing
|
|
*
|
|
* Error Codes:
|
|
* none
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
*
|
|
* 01/21/93 MHotchin - Made changes to allow this function to allocate
|
|
* the memory for the destination string. If the target string
|
|
* is NULL, then space will be allocated for it. The target
|
|
* string is returned to the caller.
|
|
**/
|
|
|
|
|
|
UINT _MBSTOWCS( WCHAR wszOut[], CHAR szIn[], UINT cOut, UINT cIn)
|
|
{
|
|
UINT n;
|
|
|
|
|
|
n = MultiByteToWideChar( gProj.uCodePage,
|
|
MB_PRECOMPOSED,
|
|
szIn,
|
|
cIn,
|
|
wszOut,
|
|
cOut);
|
|
|
|
return( n > 0 ? n - 1 : 0);
|
|
}
|
|
|
|
UINT _WCSTOMBS( CHAR szOut[], WCHAR wszIn[], UINT cOut, UINT cIn)
|
|
{
|
|
UINT n;
|
|
|
|
|
|
n = WideCharToMultiByte( gProj.uCodePage,
|
|
0,
|
|
wszIn,
|
|
cIn,
|
|
szOut,
|
|
cOut,
|
|
NULL,
|
|
NULL);
|
|
|
|
return( (cIn > 0 ) ? cIn - 1 : 0);
|
|
}
|
|
|
|
|
|
WCHAR * BinToTextW(
|
|
|
|
TCHAR *szInBuf, //... Input, binary, string
|
|
int lSource) //... Length of szInBuf
|
|
{
|
|
int i;
|
|
int cOutBufLen = 0;
|
|
int lTarget = 0; //... Max length of szOutBuf
|
|
TCHAR *szOutBuf = NULL; //... Output string with escape sequences
|
|
|
|
|
|
// If the target is NULL, allocate some memory. We set aside
|
|
// 5% more than the source length. MHotchin
|
|
// chngd to 5% or 5 chars if 10% is less than 50 davewi
|
|
|
|
lTarget = (lSource == 0) ? 0 : lSource + 1;
|
|
|
|
szOutBuf = (TCHAR *)FALLOC( MEMSIZE( lTarget));
|
|
|
|
for ( i = 0; i < lSource; i++ )
|
|
{
|
|
switch( szInBuf[i] )
|
|
{
|
|
case TEXT('\a'):
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('a'));
|
|
break;
|
|
|
|
case TEXT('\b'):
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('b'));
|
|
break;
|
|
|
|
case TEXT('\f'):
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('f'));
|
|
break;
|
|
|
|
case TEXT('\n'):
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('n'));
|
|
break;
|
|
|
|
case TEXT('\r'):
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('r'));
|
|
break;
|
|
|
|
case TEXT('\t'):
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('t'));
|
|
break;
|
|
|
|
case TEXT('\v'):
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('v'));
|
|
break;
|
|
|
|
case TEXT('\\'):
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
break;
|
|
|
|
default:
|
|
{
|
|
TCHAR wTmp = szInBuf[i];
|
|
|
|
if ( wTmp == 0 )
|
|
{
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('0'));
|
|
}
|
|
else if ( (wTmp >= 0 && wTmp < 32)
|
|
|| wTmp == 0x7f
|
|
|| wTmp == 0xa9
|
|
|| wTmp == 0xae )
|
|
{
|
|
CHAR szt[5];
|
|
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 4, szOutBuf);
|
|
sprintf( szt, "%#04hx", wTmp);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, TEXT('\\'));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, (TCHAR)(szt[0]));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, (TCHAR)(szt[1]));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, (TCHAR)(szt[2]));
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, (TCHAR)(szt[3]));
|
|
}
|
|
else
|
|
{
|
|
szOutBuf = CheckBufSizeW( &lTarget, cOutBufLen, 1, szOutBuf);
|
|
AddToW( szOutBuf, &cOutBufLen, lTarget, wTmp);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
szOutBuf[ cOutBufLen] = TEXT('\0');
|
|
|
|
return( szOutBuf);
|
|
}
|
|
|
|
|
|
#endif //RLWIN32
|
|
|
|
|
|
|
|
/** Function: atoihex
|
|
* Converts a string containing hex digits to an integer. String is
|
|
* assumed to contain nothing but legal hex digits. No error checking
|
|
* is performed.
|
|
*
|
|
* Arguments:
|
|
* sz, null terminated string containing hex digits
|
|
*
|
|
* Returns:
|
|
* value of hex digits in sz
|
|
*
|
|
* Error Codes:
|
|
* none
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
*
|
|
*/
|
|
|
|
int atoihex( CHAR sz[])
|
|
{
|
|
int r = 0;
|
|
int i = 0;
|
|
CHAR ch;
|
|
|
|
while (sz[i])
|
|
{
|
|
r *= 16;
|
|
ch = (CHAR)toupper(sz[i++]);
|
|
|
|
if (ch<='9' && ch>='0')
|
|
{
|
|
r += ch - '0';
|
|
}
|
|
else
|
|
{
|
|
if (ch <= 'F' && ch >= 'A')
|
|
{
|
|
r += ch - 'A' + 10;
|
|
}
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
|
|
#ifdef RLRES32
|
|
|
|
/**
|
|
* Function: TextToBinW
|
|
* Converts a string with c escape sequences to a true binary string.
|
|
*
|
|
* Arguments:
|
|
* rgc, target string
|
|
* sz, source string
|
|
* l, maximum length of target string
|
|
*
|
|
* Returns:
|
|
* length of target string
|
|
*
|
|
* Error Codes:
|
|
* none
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
* 9/92 -- changed to UNICODE-only version -- davewi
|
|
* 01/21/93 -- Changed to allow arb length strings MHotchin.
|
|
*
|
|
**/
|
|
|
|
int TextToBinW(
|
|
|
|
WCHAR szOutBuf[], //... Output, binary, string
|
|
WCHAR szInBuf[], //... Input string with escape sequences
|
|
int lTarget) //... Max length of szOutBuf
|
|
{
|
|
int i = 0;
|
|
int c = 0;
|
|
|
|
|
|
while ( szInBuf[ c] )
|
|
{
|
|
if ( szInBuf[ c] == TEXT('\\') )
|
|
{ // escape sequence!
|
|
c++;
|
|
|
|
switch ( szInBuf[ c++] )
|
|
{
|
|
case TEXT('a'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\a'));
|
|
break;
|
|
|
|
case TEXT('b'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\b'));
|
|
break;
|
|
|
|
case TEXT('f'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\f'));
|
|
break;
|
|
|
|
case TEXT('n'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\n'));
|
|
break;
|
|
|
|
case TEXT('r'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\r'));
|
|
break;
|
|
|
|
case TEXT('t'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\t'));
|
|
break;
|
|
|
|
case TEXT('v'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\v'));
|
|
break;
|
|
|
|
case TEXT('\''):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\''));
|
|
break;
|
|
|
|
case TEXT('\"'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\"'));
|
|
break;
|
|
|
|
case TEXT('\\'):
|
|
|
|
AddToW( szOutBuf, &i, lTarget, TEXT('\\'));
|
|
break;
|
|
|
|
case TEXT('0'):
|
|
case TEXT('1'):
|
|
case TEXT('2'):
|
|
{
|
|
CHAR szt[4];
|
|
|
|
|
|
szt[0] = szt[1] = szt[2] = szt[3] = '\0';
|
|
|
|
if ( szInBuf[c-1] == TEXT('0')
|
|
&& (szInBuf[c] < TEXT('0') || szInBuf[c] > TEXT('9'))
|
|
&& szInBuf[c] != TEXT('x') && szInBuf[c] != TEXT('X') )
|
|
{
|
|
// Must be '\0'
|
|
AddToW( szOutBuf, &i, lTarget, (TCHAR)0);
|
|
}
|
|
else if ( szInBuf[c] >= TEXT('0') && szInBuf[c] <= TEXT('9') )
|
|
{
|
|
szt[0] = (CHAR)(szInBuf[c-1]);
|
|
szt[1] = (CHAR)(szInBuf[c++]);
|
|
|
|
if ( szInBuf[c] >= TEXT('0') && szInBuf[c] <= TEXT('9'))
|
|
{
|
|
szt[2] = (CHAR)(szInBuf[c++]);
|
|
}
|
|
AddToW( szOutBuf, &i, lTarget, (TCHAR)atoi( szt));
|
|
}
|
|
else if ( szInBuf[c] == TEXT('X')
|
|
|| szInBuf[c] == TEXT('x') )
|
|
{
|
|
c++;
|
|
szt[0] = (CHAR)(szInBuf[c++]);
|
|
szt[1] = (CHAR)(szInBuf[c++]);
|
|
AddToW( szOutBuf, &i, lTarget, (TCHAR)atoihex( szt));
|
|
}
|
|
else
|
|
{
|
|
QuitT( IDS_INVESCSEQ, &szInBuf[c-2], NULL);
|
|
}
|
|
break;
|
|
}
|
|
case TEXT('x'):
|
|
case TEXT('X'):
|
|
{
|
|
CHAR szt[4];
|
|
|
|
|
|
szt[0] = szt[1] = szt[2] = szt[3] = '\0';
|
|
|
|
if ( (szInBuf[c] <= TEXT('9') && szInBuf[c] >= TEXT('0'))
|
|
|| (szInBuf[c] >= TEXT('A') && szInBuf[c] <= TEXT('F'))
|
|
|| (szInBuf[c] >= TEXT('a') && szInBuf[c] <= TEXT('f')) )
|
|
{
|
|
szt[0] = (CHAR)(szInBuf[c++]);
|
|
|
|
if ( (szInBuf[c] <= TEXT('9')
|
|
&& szInBuf[c] >= TEXT('0'))
|
|
|| (szInBuf[c] >= TEXT('A')
|
|
&& szInBuf[c] <= TEXT('F'))
|
|
|| (szInBuf[c] >= TEXT('a')
|
|
&& szInBuf[c] <= TEXT('f')) )
|
|
{
|
|
szt[1] = (CHAR)(szInBuf[c++]);
|
|
|
|
if ( (szInBuf[c] <= TEXT('9')
|
|
&& szInBuf[c] >= TEXT('0'))
|
|
|| (szInBuf[c] >= TEXT('A')
|
|
&& szInBuf[c] <= TEXT('F'))
|
|
|| (szInBuf[c] >= TEXT('a')
|
|
&& szInBuf[c] <= TEXT('f')) )
|
|
{
|
|
szt[2] = (CHAR)(szInBuf[c++]);
|
|
}
|
|
}
|
|
}
|
|
AddToW( szOutBuf, &i, lTarget, (TCHAR)atoihex( szt));
|
|
break;
|
|
}
|
|
default:
|
|
|
|
AddToW( szOutBuf, &i, lTarget, szInBuf[c-1]);
|
|
break;
|
|
} //... END switch
|
|
}
|
|
else
|
|
{
|
|
AddToW( szOutBuf, &i, lTarget, szInBuf[c++]);
|
|
}
|
|
} //... END while
|
|
szOutBuf[i++] = TEXT('\0');
|
|
|
|
return(i);
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
void ClearResourceDescriptions( void)
|
|
{
|
|
CUSTRESNODE far *pCR = pCustResList;
|
|
CUSTRESNODE far *pCRNext = NULL;
|
|
CUSTRESTEMPLATE far *pCRT = NULL;
|
|
CUSTRESTEMPLATE far *pCRTNext = NULL;
|
|
CUSTRESTEMPLATE far *pCRTTmp = NULL;
|
|
|
|
while ( pCR )
|
|
{
|
|
pCRNext = pCR->pNext;
|
|
|
|
if ( pCR->pszType )
|
|
{
|
|
RLFREE(pCR->pszType);
|
|
}
|
|
if ( pCR->pszName )
|
|
{
|
|
RLFREE(pCR->pszName);
|
|
}
|
|
pCRT = pCR->pTemplate;
|
|
while ( pCRT )
|
|
{
|
|
pCRTTmp = pCRT->pNext;
|
|
RLFREE( pCRT);
|
|
pCRT=pCRTTmp;
|
|
}
|
|
RLFREE( pCR);
|
|
pCR = pCRNext;
|
|
}
|
|
pCustResList = NULL;
|
|
}
|
|
|
|
// Check to see if we need more room. If we have less that 5 bytes
|
|
// left, grow the target by another 5%. MHotchin
|
|
// chngd to 10% or 10 chars if 10% is less than 10 davewi
|
|
|
|
static CHAR *CheckBufSize(
|
|
|
|
int *lTarget, //... Length of output buffer
|
|
int cOutBufLen, //... Bytes already used in output buffer
|
|
int cDelta, //... # characters we want to add to output buffer
|
|
CHAR *szOutBuf) //... ptr to output buffer
|
|
{
|
|
//... add 1 to allow for trailing nul
|
|
|
|
if ( *lTarget - cOutBufLen < cDelta + 1 )
|
|
{
|
|
*lTarget += cDelta;
|
|
|
|
szOutBuf = (CHAR *)FREALLOC( (BYTE *)szOutBuf, *lTarget);
|
|
}
|
|
return( szOutBuf);
|
|
}
|
|
|
|
#ifdef RLWIN32
|
|
|
|
static TCHAR *CheckBufSizeW(
|
|
|
|
int *lTarget, //... Length of output buffer
|
|
int cOutBufLen, //... Bytes already used in output buffer
|
|
int cDelta, //... # characters we want to add to output buffer
|
|
TCHAR *szOutBuf) //... ptr to output buffer
|
|
{
|
|
//... add 1 to allow for trailing nul
|
|
|
|
if ( *lTarget - cOutBufLen < (int)(MEMSIZE( cDelta + 1)) )
|
|
{
|
|
*lTarget += MEMSIZE( cDelta);
|
|
|
|
szOutBuf = (TCHAR *)FREALLOC( (BYTE *)szOutBuf, MEMSIZE(*lTarget));
|
|
}
|
|
return( szOutBuf);
|
|
}
|
|
|
|
#endif //RLWIN32
|
|
|
|
|
|
/**
|
|
* Function: BinToTextA
|
|
* Converts a binary string to it's c representation
|
|
* (complete with escape sequences)
|
|
*
|
|
* Arguments:
|
|
* rgc, source string
|
|
* lSource, length of source string
|
|
*
|
|
* Returns:
|
|
* nothing
|
|
*
|
|
* Error Codes:
|
|
* none
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
* 9/92 -- made this ANSII version-- DaveWi
|
|
* because err msg tables in NT are not UNICODE
|
|
* 01/19/93 -- Removed the string copies. They were not needed, and
|
|
* MHotchin broke anything that had embedded nulls in it.
|
|
* Also added support for allocating memory as needed.
|
|
**/
|
|
|
|
PCHAR BinToTextA(
|
|
|
|
PCHAR szInBuf, //... Input, binary, string
|
|
int lSource) //... Length of szInBuf
|
|
{
|
|
int i;
|
|
int cOutBufLen = 0;
|
|
int lTarget = 0; //... Max length of szOutBuf
|
|
PCHAR szOutBuf = NULL; //... Output string with escape sequences
|
|
|
|
|
|
// If the target is NULL, allocate some memory. We set aside
|
|
// 5% more than the source length. MHotchin
|
|
// chngd to 5% or 5 chars if 10% is less than 50 davewi
|
|
|
|
lTarget = (lSource == 0) ? 0 : lSource + 1;
|
|
|
|
szOutBuf = (PCHAR)FALLOC( lTarget);
|
|
|
|
for ( i = 0; i < lSource; i++ )
|
|
{
|
|
switch( szInBuf[i] )
|
|
{
|
|
case '\a':
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, 'a');
|
|
break;
|
|
|
|
case '\b':
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, 'b');
|
|
break;
|
|
|
|
case '\f':
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, 'f');
|
|
break;
|
|
|
|
case '\n':
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, 'n');
|
|
break;
|
|
|
|
case '\r':
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, 'r');
|
|
break;
|
|
|
|
case '\t':
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, 't');
|
|
break;
|
|
|
|
case '\v':
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, 'v');
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 2, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
break;
|
|
|
|
default:
|
|
{
|
|
unsigned char ucTmp = szInBuf[i];
|
|
|
|
if ( (ucTmp >= 0 && ucTmp < 32)
|
|
|| ucTmp == 0x7f
|
|
|| ucTmp == 0xa9
|
|
|| ucTmp == 0xae )
|
|
{
|
|
CHAR szt[5];
|
|
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 4, szOutBuf);
|
|
sprintf( szt, "%#04hx", (unsigned short)ucTmp);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, '\\');
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, szt[0]);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, szt[1]);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, szt[2]);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, szt[3]);
|
|
}
|
|
else
|
|
{
|
|
szOutBuf = CheckBufSize( &lTarget, cOutBufLen, 1, szOutBuf);
|
|
AddTo(szOutBuf, &cOutBufLen, lTarget, szInBuf[i]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
szOutBuf[ cOutBufLen] = '\0';
|
|
|
|
return( szOutBuf);
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Function: TextToBinA
|
|
* Converts a string with c escape sequences to a true binary string.
|
|
*
|
|
* Arguments:
|
|
* rgc, target string
|
|
* sz, source string
|
|
* l, maximum length of target string
|
|
*
|
|
* Returns:
|
|
* length of target string
|
|
*
|
|
* Error Codes:
|
|
* none
|
|
*
|
|
* History:
|
|
* 1/92 -- initial implementation -- SteveBl
|
|
* 9/92 -- made this ANSII version-- DaveWi
|
|
* because msg resource table strings are not UNICODE
|
|
* 01/21/93 - Removed the string copies - it breaks on embedded NULL's,
|
|
* and they aren't needed anyways. MHotchin
|
|
*
|
|
**/
|
|
|
|
int TextToBinA(
|
|
|
|
CHAR szOutBuf[], //... Output, binary, string
|
|
CHAR szInBuf[], //... Input string with escape sequences
|
|
int lTarget) //... Max length of szOutBuf
|
|
{
|
|
int i = 0;
|
|
int c = 0;
|
|
|
|
|
|
while (szInBuf[c])
|
|
{
|
|
if (szInBuf[c] == '\\')
|
|
{ // escape sequence!
|
|
c++;
|
|
|
|
switch (szInBuf[c++])
|
|
{
|
|
case 'a':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\a');
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\b');
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\f');
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\n');
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\r');
|
|
break;
|
|
|
|
case 't':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\t');
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\v');
|
|
break;
|
|
|
|
case '\'':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\'');
|
|
break;
|
|
|
|
case '\"':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\"');
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
AddTo(szOutBuf, &i, lTarget, '\\');
|
|
break;
|
|
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
{
|
|
CHAR szt[4];
|
|
|
|
|
|
szt[0] = szt[1] = szt[2] = szt[3] = '\0';
|
|
|
|
if ( szInBuf[c] >= '0' && szInBuf[c] <= '9' )
|
|
{
|
|
szt[0] = szInBuf[c-1];
|
|
szt[1] = szInBuf[c++];
|
|
|
|
if ( szInBuf[c] >= '0' && szInBuf[c] <= '9' )
|
|
{
|
|
szt[2] = (CHAR)szInBuf[c++];
|
|
}
|
|
AddTo(szOutBuf, &i, lTarget, (CHAR)atoi( szt));
|
|
}
|
|
else if ( toupper( szInBuf[c]) == 'X' )
|
|
{
|
|
c++;
|
|
szt[0] = szInBuf[c++];
|
|
szt[1] = szInBuf[c++];
|
|
AddTo(szOutBuf, &i, lTarget, (CHAR)atoihex( szt));
|
|
}
|
|
else
|
|
{
|
|
QuitA( IDS_INVESCSEQ, &szInBuf[c-2], NULL);
|
|
}
|
|
break;
|
|
}
|
|
case 'x':
|
|
{
|
|
CHAR szt[4];
|
|
|
|
|
|
// Changed letters we were comparing to - it used
|
|
// to be lower case. MHotchin
|
|
|
|
szt[0] = szt[1] = szt[2] = szt[3] = '\0';
|
|
|
|
if ((szInBuf[c] <= '9' && szInBuf[c] >= '0')
|
|
|| (toupper(szInBuf[c]) >= 'A'
|
|
&& toupper(szInBuf[c]) <= 'F'))
|
|
{
|
|
szt[0] = (CHAR)szInBuf[c++];
|
|
|
|
if ((szInBuf[c] <= '9' && szInBuf[c] >= '0')
|
|
|| (toupper(szInBuf[c]) >= 'A'
|
|
&& toupper(szInBuf[c]) <= 'F'))
|
|
{
|
|
szt[1] = szInBuf[c++];
|
|
|
|
if ((szInBuf[c] <= '9' && szInBuf[c] >= '0')
|
|
|| (toupper(szInBuf[c]) >= 'A'
|
|
&& toupper(szInBuf[c]) <= 'F'))
|
|
{
|
|
szt[2] = szInBuf[c++];
|
|
}
|
|
}
|
|
}
|
|
AddTo(szOutBuf, &i, lTarget, (CHAR)atoihex(szt));
|
|
break;
|
|
}
|
|
default:
|
|
|
|
AddTo(szOutBuf, &i, lTarget, szInBuf[c-1]);
|
|
break;
|
|
} //... END switch
|
|
}
|
|
else
|
|
{
|
|
AddTo(szOutBuf, &i, lTarget, (CHAR)szInBuf[c++]);
|
|
}
|
|
} //... END while
|
|
szOutBuf[i++] = '\0';
|
|
|
|
return(i);
|
|
}
|