windows-nt/Source/XPSP1/NT/sdktools/restools/rltools/common/restok.c

5049 lines
146 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//#include <assert.h>
#include <ctype.h>
#include <malloc.h>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
//#include <string.h>
#include <tchar.h>
#ifdef RLDOS
#include "dosdefs.h"
#else
#include <windows.h>
#include "windefs.h"
#endif
#include "restok.h"
#include "custres.h"
#include "ntmsgtbl.h"
#include "rlmsgtbl.h"
#include "resread.h"
#include "projdata.h"
//B_FormatMessage prototype
#include "showerrs.h"
#define SAME 0 //... Used in string comparisons
#define STRINGFILEINFO (TEXT("StringFileInfo"))
#define VARFILEINFO (TEXT("VarFileInfo"))
#define TRANSLATION (TEXT("Translation"))
#define LANGUAGEINFO (TEXT("Language Info"))
#define STRINGFILEINFOLEN (lstrlen( (TCHAR *)STRINGFILEINFO) + 1)
#define VARFILEINFOLEN (lstrlen( (TCHAR *)VARFILEINFO) + 1)
#define TRANSLATIONLEN (lstrlen( (TCHAR *)TRANSLATION) + 1)
#define LANGSTRINGLEN 8 //... # WCHARs in string denoting language
//... and code page in a Version resource.
#define TRANSDATALEN 2 //... # bytes in a Translation value
#define VERTYPEBINARY 0 //... Version data value is binary
#define VERTYPESTRING 1 //... Version data value is a string
#define VERMEM 2048 //... Fixed size of buffer for new version stamp
//... Decrement WORD at *pw by given amount w
#define DECWORDBY( pw,w) if (pw) { *(pw) = (*(pw) > (w)) ? *(pw) - (w) : 0;}
//... Increment WORD at *pw by given amount w
#define INCWORDBY( pw,w) if (pw) { *(pw) += (w);}
//... How many BYTES in the given string?
#define BYTESINSTRING(s) (lstrlen( (TCHAR *)s) * sizeof( TCHAR))
//... Dialog box controls (from RC.H)
#define BUTTON 0x80
#define EDIT 0x81
#define STATIC 0x82
PVERBLOCK MoveAlongVer( PVERBLOCK, WORD *, WORD *, WORD *);
BOOL FilterRes( WORD, RESHEADER *);
TCHAR *GetVerValue( PVERBLOCK);
void PutNameOrd( FILE *, BOOL, WORD , TCHAR *, DWORD *);
void GetNameOrd( FILE *,
BOOL UNALIGNED*,
WORD UNALIGNED*,
TCHAR *UNALIGNED*,
DWORD *);
void CopyRes( FILE *fpInResFile,
FILE *fpOutResFile,
RESHEADER *pResHeader,
fpos_t *pResSizePos);
BOOL fInThirdPartyEditer = FALSE;//.. Are we in a 3rd-party resource editor?
BOOL fInQuikEd = FALSE; //... Are we in RLQuiked? (see rlquiked.c)
BOOL gfShowClass = FALSE; //... Set TRUE to put dlg box elemnt class
//... in token file
#if defined(DBCS)
BOOL gfExtendedTok = TRUE; //... Set TRUE if -x is choosen
#else
BOOL gfExtendedTok = FALSE; //... Set TRUE if -x is choosen
#endif
#ifdef _DEBUG
extern PMEMLIST pMemList;
#endif
#ifdef RLRES32
#ifndef CAIRO
extern VOID *pResMsgData; // NT-specific Message Table resource
#endif //RLRES32
#endif //CAIRO
extern BOOL gbMaster; //... TRUE if we are working on a Master Project
extern BOOL gfReplace; //... FALSE if appending new language to existing resources
extern BOOL gbShowWarnings; //... Display warnining messages if TRUE
extern UCHAR szDHW[];
extern char * gszTmpPrefix;
MSTRDATA gMstr = //... Data from Master Project file (MPJ)
{ //... Fields filled in main (UI)
"",
"",
"",
"",
"",
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US),
CP_ACP //... System default Windows code page
};
PROJDATA gProj = //... Data from Project file (PRJ)
{ //... Fields filled in main (UI)
"",
"",
"",
"",
"",
"",
CP_ACP, //... System default Windows code page
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US),
FALSE,
FALSE
};
/**
* Function: ReadWinRes
*
* The main resource Read/Writer function to process the resource file to be
* localzied.
*
* ReadWinRes reads the resource header to determine the current resource type,
* then executes the corresponding Get/Put resource functions to extract and
* insert localized information contained in the resource file. ReadWinRes, is
* excuted in two modes, Tokenize, and Generate. During Tokenize mode,
* ReadWinRes writes all the localized information contained in the resouce to
* a token file. During Generate mode, ReadWinRes, replaces all the localized
* information in the input resource file, with the corresponding information
* in the token file to gernerate a localized resource file.
*
* Currently the following resouce types are supported.
*
* Version Stamping.
* Menus.
* Dialogs.
* Accelerators.
* String Tables.
* Version Stamps
* Message Tables (NT)
*
* Arguments:
*
* InResFile, Handle to binary input resource file.
* OutFesFile, Handle to binary output resouce file. Not used during tokenize
* mode.
* TokFile, Handle to text token file.
* BOOL, flag to indicate whether to build output resource file.
* BOOL, flag to indicate whether to build token file.
*
*
* Returns:
* ???
*
* Errors Codes:
* ???
*
* History:
* 10/91 Added Version stamping support. TerryRu
* 11/91, Completed Version stamping support. TerryRu
*
*
**/
int ReadWinRes(
FILE *InResFile,
FILE *OutResFile,
FILE *TokFile,
BOOL fBuildRes,
BOOL fBuildTok,
WORD wFilter)
{
BOOL fDoAccel = TRUE; // set FALSE to not build accelerators
MENUHEADER *pMenuHdr = NULL; // Linked list of Menu info.
static RESHEADER ResHeader; // Structure contain Resource Header info.
VERBLOCK *pVerBlk = NULL; // Memory block containing Version Stamping String File Block,
static VERHEAD VerHdr; // Memory block containing Version Stamping Header info
DIALOGHEADER *pDialogHdr = NULL; // Linked list of Dialog info
STRINGHEADER *pStrHdr = NULL; // Array of String Tables.
ACCELTABLEENTRY *pAccelTable = NULL;// Array of Accelerator Keys
WORD wcTableEntries = 0; // Number of Accelerator tables
fpos_t ResSizePos = 0; // Position of lSize field in the
// Resource Header, used to fixup
// the Header once the size of the
// localized information is determined.
CUSTOM_RESOURCE *pCustomResource = NULL;
LONG lEndOffset = 0L;
//... How large is the res file?
fseek( InResFile, 0L, SEEK_END);
lEndOffset = ftell( InResFile);
rewind( InResFile);
//... process until end of input file
while ( ! feof( InResFile) ) {
LONG lCurrOffset = 0L;
lCurrOffset = (LONG)ftell( InResFile);
if ( (lCurrOffset + (LONG)sizeof( RESHEADER)) >= lEndOffset ) {
return 0;
}
if ( GetResHeader( InResFile, &ResHeader, (DWORD *) NULL) == -1 ) {
return (1);
}
//... Is this the dummy, res32-identifying, res?
if ( ResHeader.lSize == 0L ) { //... Yes, we so simply copy the header if we
//... are building a res file.
if ( fBuildRes ) {
CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos);
}
#ifdef RLRES32
else {
if ( gbShowWarnings && OutResFile && ftell( OutResFile) != 0L ) {
lstrcpyA( szDHW, "type");
if ( ResHeader.wTypeID == IDFLAG ) {
sprintf( &szDHW[ lstrlenA( szDHW)],
" \"%s\"",
ResHeader.pszType);
} else {
sprintf( &szDHW[ lstrlenA( szDHW)],
" %hu,",
ResHeader.wTypeID);
}
strcat( szDHW, " name");
if ( ResHeader.wNameID == IDFLAG ) {
sprintf( &szDHW[ lstrlenA( szDHW)],
" \"%s\"",
ResHeader.pszName);
} else {
sprintf( &szDHW[ lstrlenA( szDHW)],
" %hu,",
ResHeader.wNameID);
}
sprintf( &szDHW[ lstrlenA( szDHW)],
" pri-lang %#hx sub-lang %#hx",
PRIMARYLANGID( ResHeader.wLanguageId),
SUBLANGID( ResHeader.wLanguageId));
ShowEngineErr( IDS_ZERO_LEN_RES, szDHW, NULL);
}
DWordUpFilePointer( InResFile, MYREAD, ftell( InResFile), NULL);
if (OutResFile != NULL) {
DWordUpFilePointer( OutResFile,
MYWRITE,
ftell(OutResFile),
NULL);
}
}
#endif
ClearResHeader( ResHeader);
continue; //... Ship this dummy header
}
//... Check to see if we want to filter out this
//... resource type.
if ( FilterRes( wFilter, &ResHeader) ) {
//... skip this resource type
SkipBytes( InResFile, (DWORD *)&ResHeader.lSize);
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell( InResFile), NULL);
#endif
ClearResHeader( ResHeader);
continue;
}
if ( fBuildTok ) {
if ( ResHeader.wLanguageId != (fInThirdPartyEditer
? gProj.wLanguageID
: gMstr.wLanguageID) ) {
//... Skip this resource (wrong lanugage)
if ( gbShowWarnings ) {
lstrcpyA( szDHW, "type");
if ( ResHeader.wTypeID == IDFLAG ) {
sprintf( &szDHW[ lstrlenA( szDHW)],
" \"%s\"",
ResHeader.pszType);
} else {
sprintf( &szDHW[ lstrlenA( szDHW)],
" %u,",
ResHeader.wTypeID);
}
strcat( szDHW, " name");
if ( ResHeader.wNameID == IDFLAG ) {
sprintf( &szDHW[ lstrlenA( szDHW)],
" \"%s\"",
ResHeader.pszName);
} else {
sprintf( &szDHW[ lstrlenA( szDHW)],
" %u,",
ResHeader.wNameID);
}
sprintf( &szDHW[ lstrlenA( szDHW)],
" pri-lang %#x sub-lang %#x",
PRIMARYLANGID( ResHeader.wLanguageId),
SUBLANGID( ResHeader.wLanguageId));
ShowEngineErr( IDS_SKIP_RES,
LongToPtr(ResHeader.lSize),
szDHW);
}
SkipBytes( InResFile, (DWORD *)&ResHeader.lSize);
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell(InResFile), NULL);
#endif
ClearResHeader( ResHeader);
continue;
}
} else if ( fBuildRes ) {
if ( gfReplace ) {
if ( ResHeader.wLanguageId == gMstr.wLanguageID ) {
ResHeader.wLanguageId = gProj.wLanguageID;
} else {
//... Copy this resource
CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos);
ClearResHeader( ResHeader);
continue;
}
} else { //... ! gfReplace
if ( ResHeader.wLanguageId == gMstr.wLanguageID ) {
fpos_t lFilePos = 0L;
DWORD lTmpSize = 0L;
lFilePos = ftell( InResFile); //... Save file position
lTmpSize = ResHeader.lSize; //... and resource size
//... Duplicate this resource
CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos);
fseek( InResFile, (long)lFilePos, SEEK_SET);
ResHeader.wLanguageId = gProj.wLanguageID;
ResHeader.lSize = lTmpSize;
} else {
//... Simply copy this resource if not target language
if ( ResHeader.wLanguageId == gProj.wLanguageID ) {
SkipBytes( InResFile, (DWORD *)&ResHeader.lSize);
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell( InResFile), NULL);
#endif
} else {
CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos);
}
ClearResHeader( ResHeader);
continue;
}
}
}
switch ( ResHeader.wTypeID ) {
case ID_RT_ACCELERATORS:
pAccelTable = GetAccelTable(InResFile,
&wcTableEntries,
(DWORD *)&ResHeader.lSize);
if (fBuildTok) {
TokAccelTable(TokFile,
ResHeader,
pAccelTable,
wcTableEntries);
}
if (fBuildRes) {
PutAccelTable(OutResFile,
TokFile,
ResHeader,
pAccelTable,
wcTableEntries);
}
ClearAccelTable (pAccelTable , wcTableEntries);
break;
case ID_RT_DIALOG:
pDialogHdr = GetDialog(InResFile, (DWORD *)&ResHeader.lSize);
if (fBuildTok == TRUE) {
TokDialog(TokFile, ResHeader, pDialogHdr);
}
if (fBuildRes == TRUE) {
PutDialog(OutResFile, TokFile, ResHeader, pDialogHdr);
}
ClearDialog (pDialogHdr);
break;
case ID_RT_DLGINIT:
{
PDLGINITDATA pDlgInit = GetDlgInit( InResFile, (DWORD *)&ResHeader.lSize);
if ( fBuildTok ) {
TokDlgInit( TokFile, ResHeader, pDlgInit);
}
if ( fBuildRes ) {
PutDlgInit( OutResFile, TokFile, ResHeader, pDlgInit);
}
ClearDlgInitData( pDlgInit);
break;
}
case ID_RT_MENU:
// allocate space for a new header
pMenuHdr = (MENUHEADER *)FALLOC( sizeof( MENUHEADER));
GetResMenu(InResFile, (DWORD *)&ResHeader.lSize, pMenuHdr);
if (fBuildTok == TRUE) {
TokMenu(TokFile, ResHeader, pMenuHdr);
}
if (fBuildRes == TRUE) {
PutMenu(OutResFile, TokFile, ResHeader, pMenuHdr);
}
ClearMenu(pMenuHdr);
break;
case ID_RT_STRING:
pStrHdr = GetString(InResFile, (DWORD *)&ResHeader.lSize);
if (fBuildTok == TRUE) {
TokString(TokFile, ResHeader, pStrHdr);
}
if (fBuildRes == TRUE) {
PutStrHdr(OutResFile, TokFile, ResHeader, pStrHdr);
}
ClearString(pStrHdr);
break;
#ifdef RLRES32
#ifndef CAIRO
// we currently only do Error tables under NT,
// under CAIRO we ignore them
case ID_RT_ERRTABLE: //... NT-specific Message Table resource
pResMsgData = GetResMessage(InResFile, (DWORD *)&ResHeader.lSize);
if (! pResMsgData) {
QuitT( IDS_ENGERR_13, (LPTSTR)IDS_MSGRESTBL, NULL);
}
if (fBuildTok == TRUE) {
TokResMessage(TokFile, ResHeader, pResMsgData);
}
if (fBuildRes == TRUE) {
PutResMessage(OutResFile, TokFile, ResHeader, pResMsgData);
}
ClearResMsg( &pResMsgData);
break;
#endif
#endif
#ifndef CAIRO
case ID_RT_VERSION:
{
WORD wRead = 0;
wRead = GetResVer(InResFile,
(DWORD *)&ResHeader.lSize,
&VerHdr,
&pVerBlk);
#ifdef RLRES32
if (wRead == (WORD)-1)
#else
if (wRead == FALSE)
#endif
{
QuitT( IDS_ENGERR_14, (LPTSTR)IDS_VERBLOCK, NULL);
}
// Building Tok file ?
// but only tokenize it if it contains a Version Block
if ( pVerBlk && fBuildTok == TRUE ) {
#ifdef RLRES32
TokResVer( TokFile, ResHeader, pVerBlk, wRead);
#else
TokResVer( TokFile, ResHeader, pVerBlk);
#endif
}
// Building Res file ?
if ( fBuildRes == TRUE ) {
PutResVer( OutResFile, TokFile, ResHeader,&VerHdr, pVerBlk);
}
RLFREE( pVerBlk);
}
break;
#else
case ID_RT_VERSION:
#endif
case ID_RT_CURSOR:
case ID_RT_BITMAP:
case ID_RT_ICON:
case ID_RT_FONTDIR:
case ID_RT_FONT:
case ID_RT_RCDATA:
#ifndef RLRES32
case ID_RT_ERRTABLE: //... NT-specific Message Table resourc
#endif
case ID_RT_GROUP_CURSOR:
case ID_RT_GROUP_ICON:
case ID_RT_NAMETABLE:
default:
if (GetCustomResource(InResFile,
(DWORD *)&ResHeader.lSize,
&pCustomResource,
ResHeader)) {
// Non localized resource type, skip or copy it
if (fBuildTok == TRUE) {
if ( gbShowWarnings
&& ( ResHeader.wTypeID == ID_RT_RCDATA
|| ResHeader.wTypeID > 16) ) {
static CHAR szType[256];
static CHAR szName[256];
if ( ResHeader.bTypeFlag == IDFLAG )
sprintf( szType, "%u", ResHeader.wTypeID);
else {
_WCSTOMBS( &szType[1], ResHeader.pszType, sizeof( szType), (UINT)-1);
szType[0] = '\"';
szType[ lstrlenA( szType)] = '\"';
}
if ( ResHeader.bNameFlag == IDFLAG )
sprintf( szName, "%u", ResHeader.wNameID);
else {
_WCSTOMBS( &szName[1], ResHeader.pszName, sizeof( szName), (UINT)-1);
szName[0] = '\"';
szName[ lstrlenA( szName)] = '\"';
}
ShowEngineErr( IDS_UNK_CUST_RES, (void *)szType, (void *)szName);
}
SkipBytes(InResFile, (DWORD *)&ResHeader.lSize);
} else if ( fBuildRes ) {
CopyRes( InResFile, OutResFile, &ResHeader, &ResSizePos);
}
} else {
if (fBuildTok == TRUE) {
TokCustomResource(TokFile, ResHeader, &pCustomResource);
}
if (fBuildRes == TRUE) {
PutCustomResource(OutResFile,
TokFile,
ResHeader,
&pCustomResource);
}
ClearCustomResource(&pCustomResource);
}
#ifdef RLRES32
DWordUpFilePointer(InResFile, MYREAD, ftell(InResFile), NULL);
if (OutResFile != NULL) {
DWordUpFilePointer(OutResFile,
MYWRITE,
ftell(OutResFile),
NULL);
}
#endif
break;
} //... END SWITCH
#ifndef RLRES32
// skip any extra bytes (Win 3.1 exes have
// alot of extra stuff!).
// No extra stuff in res extracted from NT exes
SkipBytes(InResFile, (DWORD *)&ResHeader.lSize);
#endif
ClearResHeader(ResHeader);
#ifdef RLRES32
DWordUpFilePointer(InResFile, MYREAD, ftell(InResFile), NULL);
if (OutResFile != NULL) {
DWordUpFilePointer(OutResFile, MYWRITE, ftell(OutResFile), NULL);
}
#endif
} // END while ( ! feof( InResFile)
return 0;
}
/**
*
*
* Function:ClearAccelTable
* Removes the accelerator table array from memory.
*
* Arguments:
* pAccelTable, pointer to arary of accelerators
* wctablesEntries, number of accelerators in arrary
*
* Returns:
* NA.
*
* Errors Codes:
* NA.
*
* History:
* 7/91, Implemented Terryru
*
*
**/
void ClearAccelTable(ACCELTABLEENTRY *pAccelTable, WORD wcTableEntries)
{
RLFREE( pAccelTable);
}
/**
*
*
* Function: ClearDialog
* Remove Dialog defintions from memory.
*
* Arguments:
* pDilaogHdr, Linked list of dialog information.
*
* Returns:
* NA.
*
* Errors Codes:
* NA.
*
* History:
* 7/91, Implemented TerryRu
*
*
**/
void ClearDialog (DIALOGHEADER * pDialogHdr)
{
BYTE i;
for (i = 0; i < (BYTE) pDialogHdr->wNumberOfItems; i ++) {
if (pDialogHdr->pCntlData[i].pszClass) {
RLFREE( pDialogHdr->pCntlData[i].pszClass);
}
if ( pDialogHdr->pCntlData[i].pExtraStuff ) {
RLFREE( pDialogHdr->pCntlData[i].pExtraStuff );
}
RLFREE( pDialogHdr->pCntlData[i].pszDlgText);
}
// now RLFREE fields in dialog header
RLFREE( pDialogHdr->pszDlgClass);
RLFREE( pDialogHdr->pszFontName);
RLFREE( pDialogHdr->pszDlgMenu);
RLFREE( pDialogHdr->pszCaption);
RLFREE( pDialogHdr->pCntlData);
// and finally clear header
RLFREE( pDialogHdr);
}
/**
*
*
* Function: ClearMenu
* Removes Menu defintions from memory.
*
* Arguments:
* pMenuHdr, linked list of Menu info
*
* Returns:
* NA.
*
* Errors Codes:
* NA.
*
* History:
* 7/91, Implemented. TerryRu
*
*
**/
void ClearMenu(MENUHEADER *pMenuHdr)
{
MENUITEM *pMenuItem;
MENUITEM *pMenuHead;
pMenuItem = pMenuHead = pMenuHdr->pMenuItem;
// remove all the menu items from the list
while (pMenuItem) {
pMenuItem = pMenuHead->pNextItem;
RLFREE( pMenuHead->szItemText);
RLFREE( pMenuHead);
pMenuHead = pMenuItem;
}
// now remove the menuheader
if (pMenuHdr->pExtraStuff)
RLFREE( pMenuHdr->pExtraStuff );
RLFREE( pMenuHdr);
}
/**
*
*
* Function: ClearResHeader
* Remove resheader name, and type fields from memory.
*
* Arguments:
* ResHdr, structure containing resheader info.
*
* Returns:
* NA.
*
* Errors Codes:
* NA.
*
* History:
* 7/91, Implemented TerryRu.
*
*
**/
void ClearResHeader(RESHEADER ResHdr)
{
RLFREE( ResHdr.pszType);
RLFREE( ResHdr.pszName);
}
/**
*
*
* Function: ClearString
* Removes the StringTable Defintions from memory.
*
* Arguments:
* pStrHdr, pointer to array of 16 string tables.
*
* Returns:
* NA.
*
* Errors Codes:
* NA.
*
* History:
* 7/91, Implemented. TerryRu
*
*
**/
void ClearString( STRINGHEADER *pStrHdr)
{
BYTE i;
for (i = 0; i < 16; i++) {
RLFREE( pStrHdr->pszStrings[i]);
}
RLFREE( pStrHdr);
}
/**
*
*
* Function: quit
* quit, Error Handling routine used to display error code and terminate program
*
* Arguments:
* error, number of error.
* pszError, descriptive error message.
*
* Returns:
* NA.
*
* Errors Codes:
*
*
* History:
* 7/91, Implemented TerryRu
* 10/91, Hacked to work under windows TerryRu
* ??? Need to add better win/dos support
*
**/
void QuitA( int error, LPSTR pszArg1, LPSTR pszArg2)
{
char szErrStr1[2048] = "*?*";
char szErrStr2[2048] = "*?*";
char *psz1 = pszArg1;
char *psz2 = pszArg2;
//... clean up after error and exit,
//... returning error code
_fcloseall();
if ( pszArg1 != NULL && pszArg1 <= (LPSTR)0x0000ffff ) {
B_FormatMessage( (FORMAT_MESSAGE_MAX_WIDTH_MASK & 78)
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_FROM_HMODULE,
NULL,
(DWORD)(DWORD_PTR)pszArg1,
szErrStr1,
sizeof( szErrStr1),
NULL);
psz1 = szErrStr1;
}
if ( pszArg2 != NULL && pszArg2 < (LPSTR)0x0000ffff ) {
B_FormatMessage( (FORMAT_MESSAGE_MAX_WIDTH_MASK & 78)
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_FROM_HMODULE,
NULL,
(DWORD)(DWORD_PTR)pszArg2,
szErrStr2,
sizeof( szErrStr2),
NULL);
psz2 = szErrStr2;
}
ShowEngineErr( error, psz1, psz2);
FreeLangList();
#ifdef _DEBUG
FreeMemList( NULL);
#endif // _DEBUG
DoExit( (error == 4) ? 0 : error);
}
#ifdef UNICODE
/* Handles errors, in UNICODE environments*/
LPSTR MakeMBMsgW(
LPWSTR pszArg, //... Msg ID# or msg text
LPSTR szBuf, //... Buffer for converted msg
USHORT usBufLen) //... #bytes in szBuf
{
char *pszRet = NULL;
if ( pszArg ) {
if ( pszArg >= (LPTSTR)0x0400 ) {
_WCSTOMBS( szBuf,
(WCHAR *)pszArg,
usBufLen,
lstrlen( pszArg ) + 1 );
} else {
B_FormatMessage( (FORMAT_MESSAGE_MAX_WIDTH_MASK & 78)
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_FROM_HMODULE,
NULL,
(DWORD)(DWORD_PTR)pszArg,
szBuf,
usBufLen,
NULL);
}
pszRet = szBuf;
}
return ( pszRet);
}
//...............................................................
void QuitW( int error, LPWSTR pszArg1, LPWSTR pszArg2)
{
char szErrStr1[2048] = "*?*";
char szErrStr2[2048] = "*?*";
QuitA( error,
MakeMBMsgW( pszArg1, szErrStr1, sizeof( szErrStr1)),
MakeMBMsgW( pszArg2, szErrStr2, sizeof( szErrStr2)));
}
#endif
/**
*
*
* Function: GetAccelTable,
* Reads the Accelerator key defintions from the resource file
*
* Arguments:
* InResFile, Handle to Resource file.
* pwcTableEntries, pointer to an array of accelerator key defintions.
* plSize, address of size of Resource.
*
* Returns:
* pwcTableEntries containing all the key defintions.
*
* Errors Codes:
*
* History:
* 8/91 Implemented TerryRu
* 4/92 Added RLRES32 support TerryRu
*
*
*
**/
ACCELTABLEENTRY * GetAccelTable(FILE *InResFile,
WORD *pwcTableEntries,
DWORD *plSize)
{
ACCELTABLEENTRY *pAccelTable;
BOOL quit = FALSE;
// need to use sizeof operator in memory
// allocation because of structure packing.
*pwcTableEntries = (WORD) 0;
pAccelTable = (ACCELTABLEENTRY *) FALLOC( ((WORD)*plSize * sizeof( WORD)));
while (*plSize && !quit) {
#ifdef RLRES32
pAccelTable[ *pwcTableEntries].fFlags = (WORD) GetWord( InResFile,
plSize);
#else
pAccelTable[ *pwcTableEntries].fFlags = (BYTE) GetByte( InResFile,
plSize);
#endif
pAccelTable[*pwcTableEntries].wAscii = GetWord (InResFile, plSize);
pAccelTable[*pwcTableEntries].wID = GetWord (InResFile, plSize);
#ifdef RLRES32
pAccelTable[ *pwcTableEntries].wPadding = GetWord( InResFile, plSize);
#endif
if ( pAccelTable[ *pwcTableEntries].fFlags & HIBITVALUE ) {
quit = TRUE;
}
++*pwcTableEntries;
}
if ( (long)*plSize <= 0 ) {
*plSize = 0;
}
return pAccelTable;
}
/**
*
*
* Function: GetDialog,
* Reads the dialog defintions from the res file, and places the info
* into a linked list.
*
*
* Arguments:
* InResFile, Handle to input resource handle, posistioned to begining
* of dialog defintion.
* plSize, pointer to size in bytes of the dialog information.
*
* Returns:
* pointer to DIALOGHEADER type containing the dialog information,
*
*
* Errors Codes:
* None ???
*
* History:
* 12/91, Cleaned up comments. TerryRu
* 04/92, Added RLRES32 support. TerryRu
*
*
**/
DIALOGHEADER *GetDialog( FILE *InResFile, DWORD * plSize)
{
DIALOGHEADER *pDialogHdr;
TCHAR *UNALIGNED*ptr;
WORD i;
LONG lStartingOffset;
static TCHAR szBuf[ 255];
LONG lExtra;
WORD j;
lStartingOffset = ftell(InResFile);
pDialogHdr = (DIALOGHEADER *)FALLOC( sizeof( DIALOGHEADER));
// lstyle
pDialogHdr->lStyle = GetdWord(InResFile, plSize);
#ifdef RLRES32
pDialogHdr->fDialogEx = (HIWORD(pDialogHdr->lStyle)==0xffff);
if (pDialogHdr->fDialogEx) {
pDialogHdr->wDlgVer = LOWORD(pDialogHdr->lStyle);
pDialogHdr->wSignature = HIWORD(pDialogHdr->lStyle);
pDialogHdr->dwHelpID = GetdWord(InResFile, plSize);
pDialogHdr->lExtendedStyle = GetdWord(InResFile, plSize);
pDialogHdr->lStyle = GetdWord(InResFile, plSize);
} else {
pDialogHdr->lExtendedStyle = GetdWord(InResFile, plSize);
}
pDialogHdr->wNumberOfItems = GetWord(InResFile, plSize);
#else
pDialogHdr->wNumberOfItems = (BYTE) GetByte(InResFile, plSize);
#endif
// allocate space to hold wNumberOfItems of pointers
// to Control Data structures
pDialogHdr->pCntlData = (CONTROLDATA *)
FALLOC( pDialogHdr->wNumberOfItems * sizeof( CONTROLDATA));
// read x, y, cx, cy dialog cordinates
pDialogHdr->x = GetWord(InResFile, plSize);
pDialogHdr->y = GetWord(InResFile, plSize);
pDialogHdr->cx = GetWord(InResFile, plSize);
pDialogHdr->cy = GetWord(InResFile, plSize);
//... Dialog Menu Name
GetNameOrd( InResFile,
(BOOL UNALIGNED *)&pDialogHdr->bMenuFlag, // 9/11/91 (PW)
(WORD UNALIGNED *)&pDialogHdr->wDlgMenuID,
(TCHAR *UNALIGNED*)&pDialogHdr->pszDlgMenu,
plSize);
//... Dialog Class Name
GetNameOrd( InResFile,
(BOOL UNALIGNED *)&pDialogHdr->bClassFlag, // 9/11/91 (PW)
(WORD UNALIGNED *)&pDialogHdr->wDlgClassID,
(TCHAR *UNALIGNED*)&pDialogHdr->pszDlgClass,
plSize);
// Dialog caption name
GetName( InResFile, szBuf, plSize);
ptr = (TCHAR *UNALIGNED*)&pDialogHdr->pszCaption;
AllocateName( *ptr, szBuf);
lstrcpy( (TCHAR *)*ptr, (TCHAR *)szBuf);
// does dialog define a font.
if ( pDialogHdr->lStyle & DS_SETFONT ) {
// extract this info.
pDialogHdr->wPointSize = GetWord( InResFile, plSize);
if (pDialogHdr->fDialogEx) {
pDialogHdr->wWeight = GetWord( InResFile, plSize);
pDialogHdr->wItalic = GetWord( InResFile, plSize);
}
GetName( InResFile, szBuf, plSize);
ptr = (TCHAR *UNALIGNED*)&pDialogHdr->pszFontName;
AllocateName(*ptr, szBuf);
lstrcpy( (TCHAR *)*ptr, (TCHAR *)szBuf);
} else {
pDialogHdr->pszFontName = (TCHAR*)FALLOC( 0);
}
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell(InResFile), plSize);
#endif
//... read each dialog control
for (i = 0; i < pDialogHdr->wNumberOfItems ; i++) {
#ifdef RLRES32
if (pDialogHdr->fDialogEx) {
pDialogHdr->pCntlData[i].dwHelpID = GetdWord(InResFile, plSize);
pDialogHdr->pCntlData[i].lExtendedStyle = GetdWord(InResFile, plSize);
pDialogHdr->pCntlData[i].lStyle = GetdWord(InResFile, plSize);
} else {
pDialogHdr->pCntlData[i].lStyle = GetdWord(InResFile, plSize);
pDialogHdr->pCntlData[i].lExtendedStyle = GetdWord(InResFile, plSize);
}
#endif // RLRES32
pDialogHdr->pCntlData[i].x = GetWord(InResFile, plSize);
pDialogHdr->pCntlData[i].y = GetWord(InResFile, plSize);
pDialogHdr->pCntlData[i].cx = GetWord(InResFile, plSize);
pDialogHdr->pCntlData[i].cy = GetWord(InResFile, plSize);
// wId
if (pDialogHdr->fDialogEx)
pDialogHdr->pCntlData[i].dwID = GetdWord (InResFile, plSize);
else
pDialogHdr->pCntlData[i].dwID = (DWORD)GetWord (InResFile, plSize);
#ifdef RLRES16
// lStyle
pDialogHdr->pCntlData[i].lStyle = GetdWord(InResFile, plSize);
pDialogHdr->pCntlData[i].bClass = (BYTE) GetByte(InResFile, plSize);
// does dialog have a class?
if (!(pDialogHdr->pCntlData[i].bClass & 0x80)) {
GetName(InResFile, szBuf, plSize);
ptr = &pDialogHdr->pCntlData[i].pszClass;
AllocateName(*ptr, szBuf);
lstrcpy ((TCHAR *)*ptr, (TCHAR *)szBuf);
} else {
pDialogHdr->pCntlData[i].pszClass = NULL;
}
#else
GetNameOrd (InResFile,
(BOOL UNALIGNED *)&pDialogHdr->pCntlData[i].bClass_Flag, // 9/11/91 (PW)
(WORD UNALIGNED *)&pDialogHdr->pCntlData[i].bClass,
(TCHAR *UNALIGNED*)&pDialogHdr->pCntlData[i].pszClass,
plSize);
#endif
GetNameOrd (InResFile,
(BOOL UNALIGNED *)&pDialogHdr->pCntlData[i].bID_Flag, // 9/11/91 (PW)
(WORD UNALIGNED *)&pDialogHdr->pCntlData[i].wDlgTextID,
(TCHAR *UNALIGNED*)&pDialogHdr->pCntlData[i].pszDlgText,
plSize);
#ifdef RLRES16
pDialogHdr->pCntlData[i].unDefined = (BYTE) GetByte(InResFile, plSize);
#else
pDialogHdr->pCntlData[i].wExtraStuff = (WORD) GetWord(InResFile, plSize);
if (pDialogHdr->fDialogEx && pDialogHdr->pCntlData[i].wExtraStuff) {
lExtra = pDialogHdr->pCntlData[i].wExtraStuff;
j = 0;
pDialogHdr->pCntlData[i].pExtraStuff = (BYTE *)FALLOC( pDialogHdr->pCntlData[i].wExtraStuff );
while ( lExtra-- )
pDialogHdr->pCntlData[i].pExtraStuff[j++] = GetByte( InResFile, plSize );
} else
pDialogHdr->pCntlData[i].pExtraStuff = NULL;
#endif // RLRES16
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell(InResFile), plSize);
#endif // RLRES32
}
// watch for overflow of plsize
if ((long) *plSize <= 0) {
*plSize = 0;
}
return (pDialogHdr);
}
/**
*
*
* Function: GetResMenu,
* Reads the Menu defintions from the resrouce file, and insert the info
* into a linked list..
*
* Arguments:
* InResFile, Input res handle, positioned at being of Menu Definition.
* lSize, pointer to size of Menu Defintion.
* pMenuHeader, pointer to structure to contain menu info.
*
* Returns:
* pMenuHeader containing linkd list of Menu info.
*
* Errors Codes:
* None.
*
* History:
* 7/91, implemented Terryru
* 12/91, cleaned up comments Terryru
* 4/92, Added PDK2 support Terryru
* 4/92, Added RLRES32 support Terryru
*
**/
void GetResMenu(FILE *InResFile, DWORD *lSize , MENUHEADER *pMenuHeader)
{
static TCHAR szItemText[255];
BOOL fStart = TRUE;
BOOL fQuit = FALSE;
LONG lExtra = 0;
WORD i = 0;
WORD wPopItems = 0, wMenuID = 0;
MENUITEM * pcMenuItem;
TCHAR *UNALIGNED*ptr;
WORD wNestingLevel = 0;
WORD wFlags;
LONG lStartingOffset; // used to dword align file
lStartingOffset = ftell(InResFile);
pMenuHeader->wVersion = GetWord(InResFile, lSize);
pMenuHeader->cbHeaderSize = GetWord(InResFile, lSize);
pMenuHeader->fMenuEx = (pMenuHeader->wVersion == 1);
if (pMenuHeader->fMenuEx && pMenuHeader->cbHeaderSize) {
lExtra = pMenuHeader->cbHeaderSize;
pMenuHeader->pExtraStuff = (BYTE *)FALLOC( pMenuHeader->cbHeaderSize );
while ( lExtra-- )
pMenuHeader->pExtraStuff[i++] = GetByte( InResFile, lSize);
} else
pMenuHeader->pExtraStuff = NULL;
// add all the items to the list
while ( (((signed long) *lSize) >= 0) && !fQuit) {
if (fStart) {
// start the menu item list
pcMenuItem = pMenuHeader->pMenuItem =
(MENUITEM *)FALLOC( sizeof( MENUITEM));
pcMenuItem->pNextItem = NULL;
fStart = FALSE;
} else {
// add space to the menu list
// allocate space for next Item
pcMenuItem->pNextItem = (MENUITEM *)FALLOC (sizeof( MENUITEM));
pcMenuItem = pcMenuItem->pNextItem;
pcMenuItem->pNextItem = NULL;
}
if (pMenuHeader->fMenuEx) {
pcMenuItem->dwType = GetdWord( InResFile, lSize);
pcMenuItem->dwState = GetdWord( InResFile, lSize);
pcMenuItem->dwMenuID = GetdWord( InResFile, lSize);
pcMenuItem->fItemFlags = wFlags = GetWord(InResFile,lSize); // read type of menu item
if ( (wFlags & MFR_POPUP) ) {
wFlags &= ~MFR_POPUP; // Normalize the menu
wFlags |= MF_POPUP;
}
//pcMenuItem->fItemFlags = wFlags;
} else {
wFlags = GetWord(InResFile,lSize); // read type of menu item
pcMenuItem->fItemFlags = wFlags;
// is it a popup?
if ( ! (pcMenuItem->fItemFlags & POPUP) ) {
pcMenuItem->dwMenuID = (DWORD)GetWord( InResFile, lSize);
}
}
GetName( InResFile, szItemText, lSize);
ptr = (TCHAR *UNALIGNED*)&pcMenuItem->szItemText;
* ptr = (TCHAR *)FALLOC( MEMSIZE( lstrlen( szItemText) + 1));
lstrcpy( (TCHAR *)*ptr, (TCHAR *)szItemText);
if (pMenuHeader->fMenuEx) {
DWordUpFilePointer( InResFile, MYREAD, ftell(InResFile), lSize);
if ( (wFlags & POPUP) ) {
pcMenuItem->dwHelpID = GetdWord( InResFile, lSize);
}
}
if (wFlags & POPUP) {
++wNestingLevel;
}
if (wFlags & ENDMENU) {
if (wNestingLevel) {
--wNestingLevel;
} else {
fQuit = TRUE;
}
}
}
#ifdef RLRES32
WordUpFilePointer( InResFile,
MYREAD,
lStartingOffset,
ftell( InResFile), lSize);
#endif
}
int MyEOF(FILE *fPtr)
{
#ifdef RLRES32
LONG lCurOffset;
LONG lEndOffset;
lCurOffset = ftell(fPtr);
lEndOffset = fseek(fPtr, SEEK_END, 0);
// reset file pointer
fseek( fPtr, lCurOffset, SEEK_SET);
return ((lEndOffset - lCurOffset) < sizeof (DWORD));
#else
return ( feof(fPtr));
#endif
}
void WordUpFilePointer(FILE *fPtr,
BOOL bMode,
LONG lStartingOffset,
LONG lCurrentOffset ,
LONG *plPos)
{
LONG lDelta;
LONG lOffset;
char buffer[]="\0\0\0\0\0\0\0\0";
lDelta = lCurrentOffset - lStartingOffset ;
lOffset = WORDUPOFFSET( lDelta);
if ( bMode == MYREAD ) {
fseek( fPtr, lOffset , SEEK_CUR);
*plPos -= lOffset;
} else {
fwrite( buffer, 1, (size_t) lOffset, fPtr);
*plPos += lOffset;
}
}
void DWordUpFilePointer(
FILE *fPtr,
BOOL bMode,
LONG lCurrentOffset,
DWORD *plPos) //... New file position
{
LONG lOffset;
lOffset = DWORDUPOFFSET( lCurrentOffset);
if ( bMode == MYREAD ) {
fseek( fPtr, lOffset, SEEK_CUR);
if ( plPos != NULL ) {
*plPos -= lOffset;
}
} else {
char buffer[]="\0\0\0\0\0\0\0";
fwrite( buffer, 1, (size_t)lOffset, fPtr);
if ( plPos != NULL ) {
*plPos += lOffset;
}
}
}
//
// Function: FilterRes, Public
//
// Synopsis: Determine whether the resource type is to be filtered
// The non filtered resource are OR together, thus several
// resource types can pass through the filter. Zero indicates
// no resources are to be filterd, 0xFFFF indicates to not filter
// custom resource.
//
//
// Arguments: [wFilter] Indicates the resources which we are to pass thru.
// [pRes] Ptr to Resource header struct
//
//
// Effects:
//
// Returns: TRUE Skip the current resource
// FALSE Use the current resource
//
// Modifies:
//
// History:
// 18-Oct-92 Created TerryRu
//
//
// Notes:
//
BOOL FilterRes( WORD wFilter, RESHEADER *pRes)
{
WORD wCurRes;
wCurRes = pRes->wTypeID;
if ( wFilter == 0 ) {
return ( FALSE);
}
if ( wCurRes == 0 ) {
return ( FALSE);
}
// check for special case for custom resources
if ( wFilter == (WORD)0xFFFF ) {
if ( wCurRes > 16) {
return ( FALSE);
} else {
return ( TRUE);
}
}
return ( ! (wFilter == wCurRes));
}
/**
*
*
* Function: GetResVer
*
* Extracts the version stamping information that
* requires loclization from the resource file. The resource
* information is containd is a USER defined resource
* (ID = 16, Type = 1).
*
* The resource block format:
* WORD wTotLen
* WORD wValLen
* BYTE szKey
* BYTE szVal
*
* All information in the version stampling is contained in
* repeating patters of this block type. All Key, and Value
* fields are padded to start on DWORD boundaries. The
* padding necessary to allign the blocks is not included in
* the wTotLen field, but the padding to allign the fields inside
* the block is.
*
* The following information in the Resource block needs to be
* tokenized:
*
*
* Key Field in StringFileInfo Block
* Value Fields in StringFileInfo String Blocks.
* Code Page and Language ID Fields of VarFileInfo
* Standard Var Blocks.
*
* By defintion, any value string contained in the String requires
* in be localized. It is assumed that there will be two
* StringFileInfo Blocks in each international resource. The first
* one, is to remain in English, while the second Block, is to be
* localized in the language specified by the StingFileInfo Key Field.
* The VarFileInfo Code Page and Language ID Fields localized to
* indicate which StringFileInfo block the file supports.
*
*
* Arguments:
* FILE *InResFile
* File to extracte version stamping from
*
* DWORD *lSize
* Size of version stamping information
*
* VERHEADER *pVerHeader
* pointer to structure to contain parsed version info.
*
* Returns:
*
* pVerHead Buffer contain version stamping resource
* pVerBlock starting location of children blocks
*
* Errors Codes:
* TRUE, Read of Resource sucessfull.
* FALSE, Read of Resource failed.
*
* History:
*
* 11/91. Created TerryRu.
* 10/92. Added Support for NULL Version Blocks TerryRu
* 10/92. Added RLRES32 version DaveWi
**/
#ifdef RLRES32
WORD GetResVer(
FILE *InResFile,
DWORD *plSize,
VERHEAD *pVerHead,
VERBLOCK **pVerBuf)
{
WORD wVerHeadSize;
WORD wcRead;
*pVerBuf = NULL;
//... Read the fixed info that will not change
wVerHeadSize = (WORD)(3 * sizeof(WORD)
+ MEMSIZE( lstrlen( TEXT( "VS_VERSION_INFO")) + 1)
+ sizeof( VS_FIXEDFILEINFO));
wVerHeadSize = DWORDUP(wVerHeadSize);
if ( ResReadBytes( InResFile,
(CHAR *)pVerHead,
(size_t)wVerHeadSize,
plSize) == FALSE ) {
return ( (WORD)-1);
}
//... check for the special case where
//... there is no version block.
if ( wVerHeadSize >= pVerHead->wTotLen) {
return ( 0);
}
//... Version header information read okay
//... so make a buffer for the rest of the res.
*pVerBuf = (VERBLOCK *)FALLOC( DWORDUP( pVerHead->wTotLen) - wVerHeadSize);
//... Now Read Value Information
wcRead = DWORDUP( pVerHead->wTotLen) - wVerHeadSize;
return ( ResReadBytes( InResFile,
(CHAR *)*pVerBuf,
(size_t)wcRead,
plSize) == FALSE ? (WORD)-1 : wcRead);
}
#else //... RLRES32
BOOL GetResVer(
FILE *InResFile,
DWORD *plSize,
VERHEAD *pVerHead,
VERBLOCK **pVerBuf)
{
size_t wcRead = sizeof( VERHEAD);
if ( ResReadBytes( InResFile, (CHAR *) pVerHead, wcRead, plSize) == FALSE ) {
return ( FALSE);
}
// check for the special case where there is no version block
if ( (size_t)pVerHead->wTotLen == wcRead ) {
*pVerBuf = NULL;
return ( TRUE);
}
// Version header information read okay.
*pVerBuf = (VERBLOCK *)FALLOC( DWORDUP( pVerHead->wTotLen) - wcRead);
// Now Read Value Information
return ( ResReadBytes( InResFile,
(CHAR *) *pVerBuf,
(size_t)(DWORDUP( pVerHead->wTotLen) - wcRead),
plSize));
}
#endif //... RLRES32
/**
*
*
* Function: GetNameOrd
* Function to read either the string name, or ordinal number of a
* resource ID. If the ID begins with a 0xff, the resource ID
* is a ordinal number, otherwise the ID is a string.
*
*
* Arguments:
* InResFile, File handle positioned to location of resource
* ID information.
* cFlag, pointer to flag indicating which ID type is used.
* pwID, pointer of ordinal ID number
* pszText pointer, to address of ID string.
*
* Returns:
* cFlag to indicate if ID is string or ordinal number.
* pwID, pszText containing actual ID info.
*
* Errors Codes:
*
* History:
*
* 7/91, Implemented TerryRu
* 9/91, Inserted cFlag as a indicator for ID or string PeterW
* 4/92, Added RLRES32 support TerryRu
**/
void GetNameOrd(
FILE *fpInResFile, //... File to retrieve header from
BOOL UNALIGNED*pbFlag,//... For IDFLAG or 1st byte (WORD in RLRES32) of name/ord
WORD UNALIGNED*pwID, //... For retrieved resource ID (if not a string)
TCHAR *UNALIGNED*pszText, // For retrieved resource name if it is a string
DWORD *plSize) // Keeps count of bytes read (or NULL)
{
WORD fFlag;
//... get type info
#ifdef RLRES16
fFlag = GetByte( fpInResFile, plSize);
#else
fFlag = GetWord( fpInResFile, plSize);
#endif
*pbFlag = fFlag;
if ( fFlag == IDFLAG ) {
//... field is a numbered item
#ifdef RLRES16
*pwID = GetByte( fpInResFile , plSize);
#else
*pwID = GetWord( fpInResFile , plSize);
#endif
*pszText = (TCHAR *)FALLOC( 0);
} else {
static TCHAR szBuf[ 255];
//... field is a named item.
//... put fFlag byte(s) back into stream
//... because it is part of the name.
*pwID = IDFLAG;
#ifdef RLRES16
UnGetByte( fpInResFile, (BYTE) fFlag, plSize);
#else
UnGetWord( fpInResFile, (WORD) fFlag, plSize);
#endif
GetName( fpInResFile, szBuf, plSize);
*pszText = (TCHAR *)FALLOC( MEMSIZE( lstrlen( szBuf) + 1));
lstrcpy( (TCHAR *)*pszText, (TCHAR *)szBuf);
}
}
/**
*
*
* Function: GetResHeader
* Reads the Resource Header information, and stores it in a structure.
*
* Arguments:
* InResFile, File handle positioned to location of Resource Header.
* pResHeader, pointer to Resource Header structure.
*
* Returns:
* pResHeader, containing resource header info.
* plSize, contining size of remaining resource info.
*
* Errors Codes:
* -1, Read of resource header failed.
*
* History:
* 7/91, Implemented TerryRu
* 4/92, Added RLRES32 Support Terryru
*
*
**/
int GetResHeader(
FILE *InResFile, //... File to get header from
RESHEADER UNALIGNED*pResHeader, //... buffer for the retrieved header
DWORD *plSize) //... keeps track of the bytes read from the file
{
#ifdef RLRES32
pResHeader->lSize = GetdWord( InResFile, plSize);
pResHeader->lHeaderSize = GetdWord( InResFile, plSize);
#endif
//... get name ID and type ID
GetNameOrd( InResFile,
(BOOL UNALIGNED*)&pResHeader->bTypeFlag,
(WORD UNALIGNED*)&pResHeader->wTypeID,
(TCHAR *UNALIGNED*)&pResHeader->pszType,
plSize);
GetNameOrd( InResFile,
(BOOL UNALIGNED*)&pResHeader->bNameFlag,
(WORD UNALIGNED*)&pResHeader->wNameID,
(TCHAR *UNALIGNED*)&pResHeader->pszName,
plSize);
#ifdef RLRES32
DWordUpFilePointer( InResFile, MYREAD, ftell( InResFile), plSize);
pResHeader->lDataVersion = GetdWord( InResFile, plSize);
#endif
pResHeader->wMemoryFlags = GetWord( InResFile, plSize);
#ifdef RLRES32
pResHeader->wLanguageId = GetWord( InResFile, plSize);
pResHeader->lVersion = GetdWord( InResFile, plSize);
pResHeader->lCharacteristics = GetdWord( InResFile, plSize);
#else // RLRES32
pResHeader->lSize = (DWORD)GetdWord( InResFile, plSize);
#endif // RLRES32
return ( 0);
}
/**
*
*
* Function: isdup
* Used to determine if the current dialog control id is a duplicate
* of an earlyier control id. If so, isdup returns a flag indicating the
* ID is a duplicate.
*
* Arguments:
* wcCurrent, ID of current dialog control.
* wpIdBuf, array of dialog control ID's processed so far.
* wcItems, number of ID's in wpIdBuf
*
* Returns:
* TRUE, ID is a duplicate
* FALSE, ID is not a duplicate
*
* Errors Codes:
* None.
*
* History:
* 7/91, Implemented TerryRu
*
*
**/
BOOL isdup(WORD wCurrent, WORD *wpIdBuf, WORD wcItems)
{
WORD i;
for (i = 0; i < wcItems; i++) {
if (wCurrent == wpIdBuf[i]) {
return TRUE;
}
}
return FALSE;
}
/**
*
*
* Function: ParseTokCrd
* Places dialog coordinates into a buffer.
*
* Arguments:
* pszCrd, buffer to hold dialog control cordinates.
* pwX, pwY, pwCX, pwCY, dialog control cordiantes.
*
* Returns:
* NA.
*
* Errors Codes:
* NA.
*
* History:
* 7/91, implemented TerryRu
*
*
**/
void ParseTokCrd(
TCHAR *pszCrd,
WORD UNALIGNED * pwX,
WORD UNALIGNED * pwY,
WORD UNALIGNED * pwCX,
WORD UNALIGNED * pwCY)
{
#ifdef RLRES32
int x = 0;
int y = 0;
int cx = 0;
int cy = 0;
_stscanf( pszCrd, TEXT("%d %d %d %d"), &x, &y, &cx, &cy);
*pwX = (WORD) x;
*pwY = (WORD) y;
*pwCX = (WORD) cx;
*pwCY = (WORD) cy;
#else //RLRES32
sscanf( pszCrd, "%hd %hd %hd %hd", pwX, pwY, pwCX, pwCY);
#endif //RLRES32
}
int GetAlignFromString( TCHAR *pszStr)
{
TCHAR *pStyle;
if ( !(pStyle = _tcschr( pszStr, TEXT('('))) ) {
return (-1);
}
while ( *pStyle ) {
if ( *pStyle == TEXT('L') ) {
if ( ! _tcsnicmp( pStyle, TEXT("LEFT"), 4) ) {
return (0);
}
} else if ( *pStyle == TEXT('C') ) {
if ( ! _tcsnicmp( pStyle, TEXT("CENTER"), 6)) {
return (1);
}
} else if ( *pStyle == TEXT('R') ) {
if ( ! _tcsnicmp( pStyle, TEXT("RIGHT"), 5) ) {
return (2);
}
}
pStyle++;
}
return ( -1 ); //none
}
void ParseTokCrdAndAlign(
TCHAR *pszCrd,
CONTROLDATA *pCntrl)
{
int align = 0;
if ( (pCntrl->bClass_Flag == IDFLAG)
&& ((pCntrl->bClass == STATIC)
|| (pCntrl->bClass == EDIT)) ) {
if ( (align = GetAlignFromString( pszCrd)) >= 0 ) {
if ( pCntrl->bClass == STATIC ) {
pCntrl->lStyle &= ~(SS_LEFT|SS_RIGHT|SS_CENTER);
if ( align == 2 )
pCntrl->lStyle |= SS_RIGHT;
else if ( align == 1 )
pCntrl->lStyle |= SS_CENTER;
else
pCntrl->lStyle |= SS_LEFT;
} else {
pCntrl->lStyle &= ~(ES_LEFT|ES_RIGHT|ES_CENTER);
if ( align == 2 )
pCntrl->lStyle |= ES_RIGHT;
else if ( align == 1 )
pCntrl->lStyle |= ES_CENTER;
else
pCntrl->lStyle |= ES_LEFT;
}
}
}
ParseTokCrd( pszCrd,
(WORD UNALIGNED *)&pCntrl->x,
(WORD UNALIGNED *)&pCntrl->y,
(WORD UNALIGNED *)&pCntrl->cx,
(WORD UNALIGNED *)&pCntrl->cy);
}
/**
*
*
* Function: PutResHeader
* Writes Resource Header information contained in the ResHeader structure
* to the ouput resfile. Note, the value of the size field, is not yet
* know, so it is left blank, to be fixed up once the size resource
* determined.
*
* Arguments:
* OutResFile, File handle to Output Resource File.
* ResHeader, Structure containing resource header information.
* pResSizePos, file position buffer
*
* Returns:
* pResSizePos, position at localization of the OutResFile to insert
* the resource size.
*
* Errors Codes:
* None.
*
* History:
* 7/91, Implemented Terryru
* 9/91, Added bTypeFlag to handle case where ID is 255. Peterw
* 4/92, Added RLRES32 support Terryru
*
*
**/
int PutResHeader(
FILE *OutResFile, //... File to write to
RESHEADER ResHeader, //... Header to be written out
fpos_t *pResSizePos, //... For offset at which to write the adjusted res size
DWORD *plSize) //... Keeps track of bytes written
{
int rc;
DWORD ltSize = *plSize;
#ifdef RLRES32
//... save position to res size
rc = fgetpos( OutResFile, pResSizePos);
//... this size is bogus, will fill in later
//... unless we are called in the mail loop
PutdWord( OutResFile, ResHeader.lSize, plSize);
PutdWord( OutResFile, ResHeader.lHeaderSize, plSize);
#endif // RLRES32
PutNameOrd( OutResFile,
ResHeader.bTypeFlag,
ResHeader.wTypeID,
ResHeader.pszType,
plSize);
PutNameOrd( OutResFile,
ResHeader.bNameFlag,
ResHeader.wNameID,
ResHeader.pszName,
plSize);
#ifdef RLRES32
DWordUpFilePointer( OutResFile, MYWRITE, ftell( OutResFile), plSize);
PutdWord( OutResFile, ResHeader.lDataVersion, plSize);
#endif // RLRES32
PutWord( OutResFile, ResHeader.wMemoryFlags, plSize);
#ifdef RLRES32
PutWord( OutResFile, ResHeader.wLanguageId, plSize);
PutdWord( OutResFile, ResHeader.lVersion, plSize);
PutdWord( OutResFile, ResHeader.lCharacteristics, plSize);
#else // RLRES32
//... save position to res size
rc = fgetpos( OutResFile, pResSizePos);
//... this size is bogus, will fill in later
//... unless we are called in the mail loop
PutdWord( OutResFile, ltSize, plSize);
#endif // RLRES32
/////////////////// ??????? why? *plSize = ltSize;
return ( rc);
}
/**
*
*
* Function: PutDialog
* PutDialog writes dialog information to the output resource file as
* it traveres through the linked list of dialog info. If the info
* is of the type that needs to be localized, the corresponding translated
* info is read from the token file, and writen to the resource file.
*
* Arguments:
* OutResFile, The file handle of the res file being generated.
* TokFile, The file handle of the token file containing tokenized dialog info,
* typically this file has been localized.
* ResHeader, Structure containg Dialog resource header information.
* pDialogHdr, Linked list of unlocalized Dialog information.
*
* Returns:
* Translated dialog information written to the Output Resource file.
*
* Errors Codes:
* None,
*
* History:
* 7/91, Implemented. TerryRu
* 1/93, Now tokenize dlg fontnames TerryRu
* 01/93 Support for var length token text MHotchin
*
**/
void PutDialog(FILE *OutResFile,
FILE *TokFile,
RESHEADER ResHeader,
DIALOGHEADER *pDialogHdr)
{
static TOKEN tok;
int found = 0;
WORD wcDup = 0;
WORD *pwIdBuf;
static TCHAR pErrBuf[MAXINPUTBUFFER];
WORD i, j = 0, k = 0;
fpos_t ResSizePos;
CONTROLDATA *pCntlData = pDialogHdr->pCntlData;
DWORD lSize = 0;
LONG lStartingOffset; // used to dword align file
WORD y = 0;
LONG lExtra = 0;
lStartingOffset = ftell(OutResFile);
// Prep for find token call
tok.wType = ResHeader.wTypeID;
tok.wName = ResHeader.wNameID;
tok.wID = 0;
tok.wReserved = ST_TRANSLATED;
lstrcpy( (TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName);
tok.szText = (TCHAR *)FALLOC( MEMSIZE( lstrlen( pDialogHdr->pszCaption) + 1));
lstrcpy( (TCHAR *)tok.szText, (TCHAR *)pDialogHdr->pszCaption);
// write the Dialog Res Header
if ( PutResHeader( OutResFile, ResHeader , &ResSizePos, &lSize)) {
RLFREE( tok.szText);
QuitT( IDS_ENGERR_06, (LPTSTR)IDS_DLGBOX, NULL);
}
// write the dialog header
lSize = 0L;
#ifdef RLRES32
if (pDialogHdr->fDialogEx) {
PutWord( OutResFile, pDialogHdr->wDlgVer, &lSize);
PutWord( OutResFile, pDialogHdr->wSignature, &lSize);
PutdWord( OutResFile, pDialogHdr->dwHelpID, &lSize);
PutdWord( OutResFile, pDialogHdr->lExtendedStyle, &lSize);
PutdWord( OutResFile, pDialogHdr->lStyle, &lSize);
} else {
PutdWord( OutResFile, pDialogHdr->lStyle, &lSize);
PutdWord( OutResFile, pDialogHdr->lExtendedStyle, &lSize);
}
PutWord( OutResFile, pDialogHdr->wNumberOfItems, &lSize);
#else // RLRES32
PutdWord( OutResFile, pDialogHdr->lStyle, &lSize);
PutByte( OutResFile, (BYTE)pDialogHdr->wNumberOfItems, &lSize);
#endif // RLRES32
// check to see if caption was localized
// but don't put it in the res file yet
// order of token is caption, cordinates,
// while in res its cordinates, caption
tok.wFlag = ISCAP;
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) {
// can not find token, terminate
ParseTokToBuf( pErrBuf, &tok);
RLFREE( tok.szText);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
tok.wReserved = ST_TRANSLATED;
// token found, continue
RLFREE( pDialogHdr->pszCaption);
pDialogHdr->pszCaption =
(TCHAR *)FALLOC( MEMSIZE( lstrlen( tok.szText) + 1));
TextToBin( pDialogHdr->pszCaption,
tok.szText,
lstrlen( tok.szText));
RLFREE( tok.szText);
// Now get the cordinates of the token
tok.wFlag = (ISCAP) | (ISCOR);
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) {
// token not found, terminate
ParseTokToBuf(pErrBuf, &tok);
RLFREE( tok.szText);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
tok.wReserved = ST_TRANSLATED;
// token found continue
ParseTokCrd( tok.szText,
(WORD UNALIGNED *)&pDialogHdr->x,
(WORD UNALIGNED *)&pDialogHdr->y,
(WORD UNALIGNED *)&pDialogHdr->cx,
(WORD UNALIGNED *)&pDialogHdr->cy);
RLFREE( tok.szText);
// put cordindates in new res file
PutWord(OutResFile, pDialogHdr->x , &lSize);
PutWord(OutResFile, pDialogHdr->y , &lSize);
PutWord(OutResFile, pDialogHdr->cx , &lSize);
PutWord(OutResFile, pDialogHdr->cy , &lSize);
PutNameOrd(OutResFile,
pDialogHdr->bMenuFlag, // 9/11/91 (PW)
pDialogHdr->wDlgMenuID,
pDialogHdr->pszDlgMenu,
&lSize);
PutNameOrd( OutResFile,
pDialogHdr->bClassFlag, // 9/11/91 (PW)
pDialogHdr->wDlgClassID,
pDialogHdr->pszDlgClass,
&lSize);
PutString(OutResFile, pDialogHdr->pszCaption, &lSize);
if ( pDialogHdr->lStyle & DS_SETFONT ) {
if (gfExtendedTok) {
static CHAR szTmpBuf[30];
// find dialog font size
tok.wFlag = ISDLGFONTSIZE;
tok.wReserved = ST_TRANSLATED;
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) {
// token not found, terminate
ParseTokToBuf(pErrBuf, &tok);
RLFREE( tok.szText);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
#ifdef RLRES32
_WCSTOMBS( szTmpBuf,
tok.szText,
sizeof( szTmpBuf),
lstrlen( tok.szText) + 1);
PutWord (OutResFile, (WORD) atoi(szTmpBuf), &lSize);
if (pDialogHdr->fDialogEx) {
PutWord( OutResFile, pDialogHdr->wWeight , &lSize);
PutWord( OutResFile, pDialogHdr->wItalic , &lSize);
}
#else // RLRES32
PutWord( OutResFile, (WORD) atoi( tok.szText), &lSize);
#endif // RLRES32
RLFREE( tok.szText);
// find dialog font name
tok.wFlag = ISDLGFONTNAME;
tok.wReserved = ST_TRANSLATED;
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) {
// token not found, terminate
ParseTokToBuf(pErrBuf, &tok);
RLFREE( tok.szText);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
PutString( OutResFile, tok.szText, &lSize);
RLFREE( tok.szText);
} else {
PutWord( OutResFile, pDialogHdr->wPointSize , &lSize);
if (pDialogHdr->fDialogEx) {
PutWord( OutResFile, pDialogHdr->wWeight , &lSize);
PutWord( OutResFile, pDialogHdr->wItalic , &lSize);
}
PutString( OutResFile, pDialogHdr->pszFontName, &lSize);
}
}
#ifdef RLRES32
DWordUpFilePointer( OutResFile, MYWRITE, ftell(OutResFile), &lSize);
#endif // RLRES32
//... That was the end of the DialogBoxHeader
//... Now we start with the ControlData's
pwIdBuf = (WORD *)FALLOC( (DWORD)pDialogHdr->wNumberOfItems
* sizeof( WORD));
tok.wReserved = ST_TRANSLATED;
// now place each of the dialog controls in the new res file
for (i = 0; i < pDialogHdr->wNumberOfItems; i ++) {
if (isdup ((WORD)pDialogHdr->pCntlData[i].dwID, pwIdBuf, (WORD)j)) {
tok.wID = (USHORT)wcDup++;
tok.wFlag = ISDUP;
} else {
// wid is unique so store in buffer for dup check
pwIdBuf[j++] = (USHORT)pDialogHdr->pCntlData[i].dwID;
tok.wID = (USHORT)pDialogHdr->pCntlData[i].dwID;
tok.wFlag = 0;
}
if (pDialogHdr->pCntlData[i].pszDlgText[0]) {
tok.szText = NULL;
if (!FindToken(TokFile, &tok, ST_TRANSLATED)) {
// can not find the token, terminate program
ParseTokToBuf(pErrBuf, &tok);
RLFREE( tok.szText);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
tok.wReserved = ST_TRANSLATED;
// token found, continue
RLFREE( pDialogHdr->pCntlData[i].pszDlgText);
pDialogHdr->pCntlData[i].pszDlgText =
(TCHAR *)FALLOC( MEMSIZE( lstrlen( tok.szText) + 1));
if ( pDialogHdr->pCntlData[i].pszDlgText ) {
TextToBin(pDialogHdr->pCntlData[i].pszDlgText,
(TCHAR *)tok.szText,
lstrlen((TCHAR *)tok.szText) + 1);
}
RLFREE( tok.szText);
}
tok.wFlag |= ISCOR;
if ( ! FindToken( TokFile, &tok, ST_TRANSLATED) ) {
ParseTokToBuf( pErrBuf, &tok);
RLFREE( tok.szText);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
tok.wReserved = ST_TRANSLATED;
ParseTokCrdAndAlign( tok.szText, &pDialogHdr->pCntlData[i] );
RLFREE( tok.szText);
#ifdef RLRES32
if (pDialogHdr->fDialogEx) {
PutdWord( OutResFile, pDialogHdr->pCntlData[i].dwHelpID, &lSize);
PutdWord( OutResFile, pDialogHdr->pCntlData[i].lExtendedStyle, &lSize);
PutdWord( OutResFile, pDialogHdr->pCntlData[i].lStyle, &lSize);
} else {
PutdWord( OutResFile, pDialogHdr->pCntlData[i].lStyle, &lSize);
PutdWord( OutResFile, pDialogHdr->pCntlData[i].lExtendedStyle, &lSize);
}
#endif // RLRES32
// now put control info into res file
PutWord (OutResFile, pDialogHdr->pCntlData[i].x , &lSize);
PutWord (OutResFile, pDialogHdr->pCntlData[i].y , &lSize);
PutWord (OutResFile, pDialogHdr->pCntlData[i].cx , &lSize);
PutWord (OutResFile, pDialogHdr->pCntlData[i].cy , &lSize);
if (pDialogHdr->fDialogEx)
PutdWord (OutResFile, pDialogHdr->pCntlData[i].dwID , &lSize);
else
PutWord (OutResFile, (WORD)pDialogHdr->pCntlData[i].dwID , &lSize);
#ifdef RLRES16
// lStyle
PutdWord (OutResFile, pDialogHdr->pCntlData[i].lStyle , &lSize);
PutByte(OutResFile, (BYTE) pDialogHdr->pCntlData[i].bClass, &lSize);
if (! (pDialogHdr->pCntlData[i].bClass & 0x80)) {
PutString (OutResFile, pDialogHdr->pCntlData[i].pszClass , &lSize);
}
#else // RLRES16
PutNameOrd(OutResFile,
pDialogHdr->pCntlData[i].bClass_Flag, // 9/11/91 (PW)
pDialogHdr->pCntlData[i].bClass,
pDialogHdr->pCntlData[i].pszClass,
&lSize);
#endif // RLRES16
PutNameOrd(OutResFile,
pDialogHdr->pCntlData[i].bID_Flag, // 9/11/91 (PW)
pDialogHdr->pCntlData[i].wDlgTextID,
pDialogHdr->pCntlData[i].pszDlgText,
&lSize);
#ifdef RLRES16
PutByte(OutResFile, (BYTE) pDialogHdr->pCntlData[i].unDefined, &lSize);
#else
PutWord(OutResFile, (WORD)pDialogHdr->pCntlData[i].wExtraStuff, &lSize);
if (pDialogHdr->fDialogEx && pDialogHdr->pCntlData[i].wExtraStuff) {
lExtra = pDialogHdr->pCntlData[i].wExtraStuff;
y = 0;
while ( lExtra-- )
PutByte (OutResFile, pDialogHdr->pCntlData[i].pExtraStuff[y++] , &lSize);
}
if ( i < pDialogHdr->wNumberOfItems - 1 ) {
DWordUpFilePointer( OutResFile, MYWRITE, ftell(OutResFile), &lSize);
}
#endif // RLRES16
}
RLFREE( pwIdBuf );
if (!UpdateResSize (OutResFile, &ResSizePos , lSize)) {
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_DLGBOX, NULL);
}
DWordUpFilePointer( OutResFile, MYWRITE, ftell( OutResFile), NULL);
}
/**
*
*
* Function: PutMenu
* Traveres through the linked list of Menu information and writes the info to the
* output resource file. If the infortion is the type that requires localization,
* the translated info is read from the token file and writen to the resource.
* call PutMenuItem to do the actual write of the menu info to the resource.
*
* Arguments:
* OutResFile, File handle of output resource file.
* TokFile, File handle of token file.
* ResHeader, Sturcture contain Menu Resource header information.
* pMenuHdr, Linked list of menu info.
*
* Returns:
* Translated Menu Info written to output resource file.
*
* Errors Codes:
* None.
*
* History:
* 7/91, Implemented. TerryRu.
* 01/93 Changes to allow var length token text. MHotchin
*
**/
void PutMenu(FILE *OutResFile,
FILE *TokFile,
RESHEADER ResHeader,
MENUHEADER *pMenuHdr)
{
DWORD lSize = 0;
static TOKEN tok;
static WORD wcPopUp = 0;
fpos_t ResSizePos;
MENUITEM *pMenuItem = pMenuHdr->pMenuItem;
static TCHAR pErrBuf[ MAXINPUTBUFFER];
LONG lExtra = 0;
WORD i = 0;
// write the Menu Res header
if ( PutResHeader (OutResFile, ResHeader , &ResSizePos, &lSize)) {
QuitT( IDS_ENGERR_06, (LPTSTR)IDS_MENU, NULL);
}
lSize = 0;
// write the Menu header
PutWord (OutResFile, pMenuHdr->wVersion, &lSize);
PutWord (OutResFile, pMenuHdr->cbHeaderSize , &lSize);
if (pMenuHdr->fMenuEx && pMenuHdr->cbHeaderSize) {
lExtra = pMenuHdr->cbHeaderSize;
while ( lExtra-- )
PutByte (OutResFile, pMenuHdr->pExtraStuff[i++] , &lSize);
}
// prep for findtoken call
tok.wType = ResHeader.wTypeID;
tok.wName = ResHeader.wNameID;
tok.wReserved = ST_TRANSLATED;
// for all menu items,
// find translated token if item was tokenized
// write out that menu item, using new translation if available.
while (pMenuItem) {
// if Menu Item is a seperator skip it
if ( *pMenuItem->szItemText ) {
// check for the popup menu items
if ((pMenuItem->fItemFlags & MFR_POPUP) && pMenuHdr->fMenuEx) {
tok.wID = (pMenuItem->dwMenuID == 0 ||
pMenuItem->dwMenuID == 0x0000ffff) ?
(USHORT)pMenuItem->dwMenuID : 0x8000 + wcPopUp++;
tok.wFlag = ISPOPUP;
} else if (pMenuItem->fItemFlags & POPUP) {
tok.wID = wcPopUp++;
tok.wFlag = ISPOPUP;
} else {
tok.wID = (USHORT)pMenuItem->dwMenuID;
tok.wFlag = 0;
}
lstrcpy((TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName);
tok.szText = NULL;
if ( ! FindToken( TokFile, &tok,ST_TRANSLATED) ) {
// can not find token, terminate
ParseTokToBuf(pErrBuf, &tok);
RLFREE( tok.szText);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
tok.wReserved = ST_TRANSLATED;
// token found, continue
RLFREE( pMenuItem->szItemText);
pMenuItem->szItemText=
(TCHAR *)FALLOC( MEMSIZE( lstrlen( tok.szText) + 1));
TextToBin(pMenuItem->szItemText,
(TCHAR *)tok.szText,
lstrlen((TCHAR *)tok.szText)+1);
RLFREE( tok.szText);
}
PutMenuItem (OutResFile, pMenuItem , &lSize, pMenuHdr->fMenuEx);
pMenuItem = pMenuItem->pNextItem;
}
if (!UpdateResSize (OutResFile, &ResSizePos , lSize)) {
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_MENU, NULL);
}
}
/**
*
*
* Function: PutMenuItem
* Called by PutMenu to write a menu item info to the ouput resoruce file.
*
*
* Arguments:
* OutResFile, File handle of output resfile, positioned at location to
* write menu item info.
* pMenuItem, pointer to struture containing menu item info.
* plSize, pointer of variable to count the number of bytes written to
* the resource file. Used later to fixup the resource field in the
* header.
*
*
*
* Returns:
* OutReFile, containing translated menu item info, and plSize containing
* number of bytes written to resource file.
*
* Errors Codes:
* None.
*
* History:
* 7//91, Implemented TerryRu
*
*
**/
void PutMenuItem(FILE * OutResFile, MENUITEM * pMenuItem, DWORD * plSize, BOOL fMenuEx)
{
if (fMenuEx) {
PutdWord( OutResFile, pMenuItem->dwType, plSize);
PutdWord( OutResFile, pMenuItem->dwState, plSize);
PutdWord( OutResFile, pMenuItem->dwMenuID, plSize);
PutWord( OutResFile, pMenuItem->fItemFlags, plSize);
} else {
PutWord( OutResFile, pMenuItem->fItemFlags, plSize);
if ( ! (pMenuItem->fItemFlags & POPUP) ) {
PutWord( OutResFile, (WORD)pMenuItem->dwMenuID, plSize);
}
}
PutString( OutResFile, pMenuItem->szItemText, plSize);
if (fMenuEx) {
DWordUpFilePointer( OutResFile, MYWRITE, ftell(OutResFile), plSize);
if (pMenuItem->fItemFlags & MFR_POPUP) {
PutdWord( OutResFile, pMenuItem->dwHelpID, plSize);
}
}
}
/**
*
*
* Function: PutNameOrd
* Writes either the string or ordinal ID of the resource class or type.
*
*
* Arguments:
* OutResFile, File handle of resource file being generated.
* bFlag, Flag indicating whether ID is a string or ordinal.
* pszText, string ID, if used.
* wId, Ordinal ID if used.
* pLsize, pointer to DWORD counter var.
*
* Returns:
* OutResFile, containing ID info, and plSize containing the number of
* bytes written to the file.
*
* Errors Codes:
* None.
*
* History:
* 7/91, Implemented. TerryRu.
*
*
**/
void PutNameOrd(
FILE *fpOutResFile,
BOOL bFlag,
WORD wID,
TCHAR *pszText,
DWORD *plSize)
{
if ( bFlag == IDFLAG ) {
#ifdef RLRES16
PutByte( fpOutResFile, (BYTE)IDFLAG, plSize);
#else
PutWord( fpOutResFile, (WORD)IDFLAG, plSize);
#endif
PutWord( fpOutResFile, wID, plSize);
} else {
PutString( fpOutResFile, pszText, plSize);
}
}
/**
*
*
* Function: MyAtow,
* Special Ascii to WORD function that works on 4 digit, hex strings.
*
*
* Arguments:
* pszNum, 4 digit hex string to convert to binary.
*
*
* Returns:
* Binary value of pszNumString
*
* Errors Codes:
* None.
*
* History:
* 12//91, Implemented. TerryRu.
*
*
**/
WORD MyAtoX(
CHAR *pszNum, //... array of bytes to scan
int nLen) //... # oc bytes in pszNum to scan
{
WORD wNum = 0;
WORD i;
WORD nPower = 1;
if ( nLen > 4 ) {
QuitT( IDS_ENGERR_16, (LPTSTR)IDS_CHARSTOX, NULL);
}
for ( i = 0; i < nLen; i++, nPower *= 16 ) {
if ( isdigit( pszNum[ i]) ) {
wNum += nPower * (pszNum[i] - '0');
} else {
wNum += nPower * (toupper( pszNum[i]) - 'A' + 10);
}
}
return ( wNum);
}
WORD MyAtoW( CHAR *pszNum)
{
return ( MyAtoX( pszNum, 4));
}
/**
*
*
* Function: PutResVer.
* Writes the Version stamping info to the Resourc file. Unlike most
* put functions, PutResVer writes all the localized version stamping info
* into a memory block, then writes the complete version stamping info to
* the resource file. This was done because of large number of size
* fixups needed for the version stamping info.
*
*
* Arguments:
* OutResFile, file pointer of resource file being generated.
* TokeFile, file pointer of input token file containing localized info.
* ResHeader, Structure containing Resource Header info of the
* version stamping block.
* pVerHdr, address of Version Header. Note this is different the ResHdr.
* pVerBlk, address of Version stamping info, which is contained in
* a series of StringFile, and VarFile info blocks. The number of
* such blocks is determined by the size fields.
*
* Returns:
* OutResFile, containing localized version stamping info.
*
* Errors Codes:
* None.
*
* History:
* 11/91, Implemented. TerryRu.
* 12/91, Various fixes to work with different padding. TerryRu.
* 01/92, Size of Version block updated PeterW.
* 10/92, Now handles NULL Version Blocks TerryRu.
* 10/92, Added RLRES32 version DaveWi
* 01/93, Added var length token text support. MHotchin
**/
#ifdef RLRES32
int PutResVer(
FILE *fpOutResFile,
FILE *fpTokFile,
RESHEADER ResHeader,
VERHEAD *pVerHdr,
VERBLOCK *pVerBlk)
{
TOKEN Tok;
BOOL fInStringInfo = FALSE; //... TRUE if reading StringFileInfo
WORD wTokNum = 0; //... Put into Tok.wID field
WORD wTokContinueNum = 0; //... Put into Tok.wFlag field
WORD wDataLen = 0; //... Length of old resource data
WORD wVerHeadSize; //... Sizeof of the VERHEAD struct
fpos_t lResSizePos;
DWORD lSize = 0L;
int nWritten = 0;
int nNewVerBlockSize = 0;
PVERBLOCK pNewVerStamp = NULL;
PVERBLOCK pNewBlk = NULL;
wVerHeadSize = (WORD)(3 * sizeof(WORD)
+ MEMSIZE( lstrlen( TEXT( "VS_FIXEDFILEINFO")) + 1)
+ sizeof( VS_FIXEDFILEINFO));
wVerHeadSize = DWORDUP(wVerHeadSize);
//... write the Version resouce header
if ( PutResHeader(fpOutResFile, ResHeader, &lResSizePos, &lSize) ) {
QuitT( IDS_ENGERR_06, (LPTSTR)IDS_VERSTAMP, NULL);
}
lSize = 0L;
if ( pVerBlk == NULL ) {
//... We have no version block to write
//... just write the version header and return
nWritten = fwrite((void *)pVerHdr,
sizeof(char),
wVerHeadSize,
fpOutResFile);
if (! UpdateResSize(fpOutResFile, &lResSizePos, (DWORD)nWritten)) {
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_VERSTAMP, NULL);
}
return (1);
}
wDataLen = pVerHdr->wTotLen;
if ( wDataLen == 0 || wDataLen == (WORD)-1 ) {
return (-1); //... No resource data
}
//... Allocate buffer to hold New Version
//... Stamping Block (make ne buffer large to
//... account for expansion of strings during
//... localization).
pNewVerStamp = (PVERBLOCK)FALLOC( (nNewVerBlockSize = wDataLen * 4));
//... Fill new memory block with zeros
memset((void *)pNewVerStamp, 0, nNewVerBlockSize);
//... Copy version header into buffer
memcpy((void *)pNewVerStamp, (void *)pVerHdr, wVerHeadSize);
pNewVerStamp->wLength = wVerHeadSize;
//... Move to start of new version info block
pNewBlk = (PVERBLOCK)((PBYTE)pNewVerStamp + wVerHeadSize);
wDataLen -= wVerHeadSize;
//... Fill in static part of TOKEN struct
Tok.wType = ResHeader.wTypeID;
Tok.wName = IDFLAG;
Tok.szName[0] = TEXT('\0');
Tok.szType[0] = TEXT('\0');
Tok.wReserved = ST_TRANSLATED;
//... Get a token for each string found in res
while (wDataLen > 0) {
WORD wRC;
//... Start of a StringFileInfo block?
#ifdef UNICODE
wRC = (WORD)CompareStringW( MAKELCID( MAKELANGID( LANG_ENGLISH,
SUBLANG_ENGLISH_US),
SORT_DEFAULT),
0,
pVerBlk->szKey,
min( wDataLen, (WORD)STRINGFILEINFOLEN),
STRINGFILEINFO,
min( wDataLen, (WORD)STRINGFILEINFOLEN));
if ( wRC == 2 )
#else
wRC = strncmp( pVerBlk->szKey,
STRINGFILEINFO,
min( wDataLen, (WORD)STRINGFILEINFOLEN));
if ( wRC == SAME )
#endif
{
WORD wStringInfoLen = 0; //... # of bytes in StringFileInfo
WORD wLen = 0;
PVERBLOCK pNewStringInfoBlk; //... Start of this StringFileInfo blk
pNewStringInfoBlk = pNewBlk;
pNewStringInfoBlk->wLength = 0; //... Gets fixed up later
pNewStringInfoBlk->wValueLength = 0;
pNewStringInfoBlk->wType = pVerBlk->wType;
lstrcpy( (TCHAR *)pNewStringInfoBlk->szKey, (TCHAR *)pVerBlk->szKey);
//... Get # of bytes in this StringFileInfo
//... (Length of value is always 0 here)
wStringInfoLen = pVerBlk->wLength;
//... Move to start of first StringTable blk.
wLen = (WORD)(DWORDUP(sizeof(VERBLOCK)
- sizeof(TCHAR)
+ MEMSIZE( STRINGFILEINFOLEN)));
pVerBlk = (PVERBLOCK)((PBYTE)pVerBlk + wLen);
pNewBlk = (PVERBLOCK)((PBYTE)pNewStringInfoBlk + wLen);
DECWORDBY(&wDataLen, wLen);
DECWORDBY(&wStringInfoLen, wLen);
INCWORDBY(&pNewVerStamp->wLength, wLen);
INCWORDBY(&pNewStringInfoBlk->wLength, wLen);
while (wStringInfoLen > 0) {
WORD wStringTableLen = 0;
PVERBLOCK pNewStringTblBlk = NULL;
//... Get # of bytes in this StringTable
//... (Length of value is always 0 here)
wStringTableLen = pVerBlk->wLength;
//... Copy StringFileInfo key into Token name
Tok.wID = wTokNum++;
Tok.wFlag = wTokContinueNum = 0;
lstrcpy((TCHAR *)Tok.szName, (TCHAR *)LANGUAGEINFO);
Tok.szText = NULL;
//... Find token for this
if ( ! FindToken( fpTokFile, &Tok, ST_TRANSLATED) ) {
//... token not found, flag error and exit.
ParseTokToBuf( (TCHAR *)szDHW, &Tok);
RLFREE( pNewVerStamp);
RLFREE( Tok.szText);
QuitT( IDS_ENGERR_05, (TCHAR *)szDHW, NULL);
}
Tok.wReserved = ST_TRANSLATED;
//... Copy lang string into buffer
pNewStringTblBlk = pNewBlk;
pNewStringTblBlk->wLength = 0; //... fixed up later
pNewStringTblBlk->wValueLength = 0;
pNewStringTblBlk->wType = pVerBlk->wType;
CopyMemory( pNewStringTblBlk->szKey,
Tok.szText,
MEMSIZE( LANGSTRINGLEN));
RLFREE( Tok.szText);
//... Move to start of first String.
wLen = DWORDUP( sizeof(VERBLOCK)
- sizeof(TCHAR)
+ MEMSIZE( LANGSTRINGLEN));
pVerBlk = (PVERBLOCK)((PBYTE)pVerBlk + wLen);
pNewBlk = (PVERBLOCK)((PBYTE)pNewBlk + wLen);
DECWORDBY(&wDataLen, wLen);
DECWORDBY(&wStringInfoLen, wLen);
DECWORDBY(&wStringTableLen, wLen);
INCWORDBY(&pNewVerStamp->wLength, wLen);
INCWORDBY(&pNewStringInfoBlk->wLength, wLen);
INCWORDBY(&pNewStringTblBlk->wLength, wLen);
while ( wStringTableLen > 0 ) {
//... Is value a string?
if (pVerBlk->wType == VERTYPESTRING) {
wTokContinueNum = 0;
Tok.wID = wTokNum++;
Tok.wReserved = ST_TRANSLATED;
lstrcpy( (TCHAR *)pNewBlk->szKey,
(TCHAR *)pVerBlk->szKey);
pNewBlk->wLength =
DWORDUP(sizeof(VERBLOCK) +
MEMSIZE(lstrlen((TCHAR *)pNewBlk->szKey)));
Tok.wFlag = wTokContinueNum++;
lstrcpy( (TCHAR *)Tok.szName, (TCHAR *)pVerBlk->szKey);
//... Find token for this
if ( ! FindToken( fpTokFile, &Tok, ST_TRANSLATED) ) {
//... token not found, flag error and exit.
ParseTokToBuf( (TCHAR *)szDHW, &Tok);
RLFREE( pNewVerStamp);
QuitT( IDS_ENGERR_05, (TCHAR *)szDHW, NULL);
}
Tok.wReserved = ST_TRANSLATED;
pNewBlk->wValueLength = (WORD)TextToBinW(
(TCHAR *)((PCHAR)pNewBlk + pNewBlk->wLength),
Tok.szText,
2048);
pNewBlk->wType = VERTYPESTRING;
pNewBlk->wLength += MEMSIZE( pNewBlk->wValueLength);
INCWORDBY(&pNewVerStamp->wLength,
DWORDUP(pNewBlk->wLength));
INCWORDBY(&pNewStringInfoBlk->wLength,
DWORDUP(pNewBlk->wLength));
INCWORDBY(&pNewStringTblBlk->wLength,
DWORDUP(pNewBlk->wLength));
pNewBlk = MoveAlongVer(pNewBlk, NULL, NULL, NULL);
RLFREE( Tok.szText);
}
//... Move to start of next String.
pVerBlk = MoveAlongVer(pVerBlk,
&wDataLen,
&wStringInfoLen,
&wStringTableLen);
} //... END while wStringTableLen
} //... END while wStringInfoLen
} else {
if (_tcsncmp((TCHAR *)pVerBlk->szKey,
(TCHAR *)VARFILEINFO,
min(wDataLen, (WORD)VARFILEINFOLEN)) == SAME) {
WORD wVarInfoLen = 0; //... # of bytes in VarFileInfo
WORD wNewVarInfoLen = 0; //... # of bytes in new VarFileInfo
WORD wLen = 0;
PVERBLOCK pNewVarStart = NULL; //... Start of VarInfo block
wVarInfoLen = pVerBlk->wLength;
pNewVarStart = pNewBlk;
//... Get # of bytes in this VarFileInfo
//... (Length of value is always 0 here)
wLen = (WORD)(DWORDUP(sizeof(VERBLOCK)
- sizeof(TCHAR)
+ MEMSIZE( VARFILEINFOLEN)));
//... Copy non-localized header
//... pNewVarStart->wLength field fixed up later
memcpy((void *)pNewVarStart, (void *)pVerBlk, wLen);
pNewVarStart->wLength = wLen;
//... Move to start of first Var.
pVerBlk = (PVERBLOCK)((PBYTE)pVerBlk + wLen);
pNewBlk = (PVERBLOCK)((PBYTE)pNewBlk + wLen);
DECWORDBY(&wDataLen, wLen);
DECWORDBY(&wVarInfoLen, wLen);
INCWORDBY(&pNewVerStamp->wLength, wLen);
while (wDataLen > 0 && wVarInfoLen > 0) {
if (_tcsncmp((TCHAR *)pVerBlk->szKey,
(TCHAR *)TRANSLATION,
min(wDataLen, (WORD)TRANSLATIONLEN)) == SAME) {
WORD wTransLen = 0;
PBYTE pValue = NULL;
wTokContinueNum = 0;
//... Copy VarFileInfo key into Token
Tok.wID = wTokNum;
Tok.wFlag = wTokContinueNum++;
Tok.szText = NULL;
lstrcpy((TCHAR *)Tok.szName, (TCHAR *)TRANSLATION);
Tok.wReserved = ST_TRANSLATED;
pNewBlk->wLength =
DWORDUP(sizeof(VERBLOCK) +
MEMSIZE(lstrlen((TCHAR *)TRANSLATION)));
INCWORDBY(&pNewVerStamp->wLength, pNewBlk->wLength);
INCWORDBY(&pNewVarStart->wLength, pNewBlk->wLength);
pNewBlk->wValueLength = 0; //... fixed up later
pNewBlk->wType = VERTYPEBINARY;
lstrcpy( (TCHAR *)pNewBlk->szKey, (TCHAR *)TRANSLATION);
lstrcpy((TCHAR *)Tok.szName, (TCHAR *)TRANSLATION);
//... Find token for this
if ( ! FindToken( fpTokFile, &Tok, ST_TRANSLATED) ) {
//... token not found, flag error and exit.
ParseTokToBuf((TCHAR *)szDHW, &Tok);
RLFREE( pNewVerStamp);
RLFREE( Tok.szText);
QuitT( IDS_ENGERR_05, (TCHAR *)szDHW, NULL);
} else {
PCHAR pszLangIDs = NULL;
PCHAR pszLangStart = NULL;
WORD wLangIDCount = 0;
size_t nChars;
//... Get # chars in input string (token text)
wTransLen = (WORD)lstrlen( Tok.szText);
pszLangIDs = (PCHAR)FALLOC( MEMSIZE( wTransLen + 1));
nChars = _WCSTOMBS( pszLangIDs,
Tok.szText,
MEMSIZE( wTransLen + 1),
wTransLen + 1);
RLFREE( Tok.szText);
if ( ! nChars ) {
RLFREE( pNewVerStamp);
RLFREE( pszLangIDs);
QuitT( IDS_ENGERR_14,
(LPTSTR)IDS_INVVERCHAR,
NULL);
}
//... Where to put these bytes?
pValue = (PBYTE)GetVerValue( pNewBlk);
//... Get each lang ID in the token
for ( wLangIDCount = 0, pszLangStart = pszLangIDs;
wTransLen >= 2 * TRANSDATALEN;
++wLangIDCount ) {
USHORT uByte1 = 0;
USHORT uByte2 = 0;
WORD wIndex = 0;
if ( sscanf( pszLangStart,
"%2hx%2hx",
&uByte2,
&uByte1) != 2 ) {
QuitA( IDS_ENGERR_16,
(LPSTR)IDS_ENGERR_21,
pszLangStart);
}
wIndex = wLangIDCount * TRANSDATALEN;
pValue[ wIndex] = (BYTE)uByte1;
pValue[ wIndex + 1] = (BYTE)uByte2;
INCWORDBY(&pNewVerStamp->wLength, TRANSDATALEN);
INCWORDBY(&pNewVarStart->wLength, TRANSDATALEN);
INCWORDBY(&pNewBlk->wLength, TRANSDATALEN);
INCWORDBY(&pNewBlk->wValueLength, TRANSDATALEN);
//... Set up to get next lang ID in token
wTransLen -= 2 * TRANSDATALEN;
pszLangStart += 2 * TRANSDATALEN;
while ( wTransLen > 2 * TRANSDATALEN
&& *pszLangStart != '\0'
&& isspace( *pszLangStart) ) {
wTransLen--;
pszLangStart++;
}
} //... END for ( wLangIDCount = 0 ...
RLFREE( pszLangIDs);
}
Tok.wReserved = ST_TRANSLATED;
} //... END if (_tcsncmp((TCHAR *)pVerBlk->szKey))
//... Move to start of next Var info block.
pVerBlk = MoveAlongVer(pVerBlk,
&wDataLen,
&wVarInfoLen,
NULL);
pNewBlk = MoveAlongVer(pNewBlk, NULL, NULL, NULL);
} //... END while (wDataLen > 0 && wVarInfoLen)
} else {
RLFREE( pNewVerStamp);
QuitT( IDS_ENGERR_14, (LPTSTR)IDS_INVVERBLK, NULL);
}
}
} //... END while (wDataLen)
//... write new version stamping information
//... to the resource file
nWritten = fwrite((void *)pNewVerStamp,
sizeof(char),
(WORD)lSize + pNewVerStamp->wLength,
fpOutResFile);
if ( ! UpdateResSize( fpOutResFile,
&lResSizePos,
lSize + pNewVerStamp->wLength) ) {
RLFREE( pNewVerStamp);
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_VERSTAMP, NULL);
}
RLFREE( pNewVerStamp);
return (0);
}
#else //... #ifdef RLRES32
int PutResVer(
FILE *OutResFile,
FILE *TokFile,
RESHEADER ResHeader,
VERHEAD *pVerHdr,
VERBLOCK *pVerBlk)
{
TCHAR *pszBuf;
fpos_t ResSizePos;
WORD wcLang = 0,
wcBlock = 0;
TOKEN tok;
VERBLOCK *pCurBlk;
VERBLOCK *pNewBlk,
*pNewBlkStart;
TCHAR *pszStr,
pErrBuf[ 128];
WORD *pwVal;
DWORD lTotBlkSize,
lSize = 0;
int wTotLen,
wcCurBlkLen,
wcTransBlkLen,
wcRead;
WORD *pStrBlkSizeLoc,
wStrBlkSize = 0;
int wcBlkLen;
// write the Version resouce header
if ( PutResHeader( OutResFile, ResHeader, &ResSizePos, &lSize) ) {
QuitT( IDS_ENGERR_06, MAKEINTRESOURCE( IDS_VERSTAMP), NULL);
}
lSize = 0L;
if ( pVerBlk == NULL ) {
//... We have no version block to write
//... just write the version header and return
wcRead = fwrite( (void *)pVerHdr,
sizeof( char),
sizeof( VERHEAD),
OutResFile);
if ( ! UpdateResSize( OutResFile, &ResSizePos, (DWORD)wcRead) ) {
QuitT( IDS_ENGERR_07, MAKEINTRESOURCE( IDS_VERSTAMP), NULL);
}
return ( 1);
}
wTotLen = pVerBlk->nTotLen;
// Allocate buffer to hold New Version Stamping Block
pNewBlk = (VERBLOCK *)FALLOC( VERMEM));
// Set new memory block to NULLS
memset( (void *)pNewBlk, 0, VERMEM);
// save start of new version info block
pNewBlkStart = pNewBlk;
wcTransBlkLen = sizeof(VERHEAD);
lSize += wcTransBlkLen;
// Insert version header info into new version info bluffer
memcpy((void *)pNewBlk, (void *)pVerHdr, wcTransBlkLen);
// Position pNewBlk point at location to insert next piece of version info
pNewBlk = (VERBLOCK *) ((char *) pNewBlk + wcTransBlkLen);
// File in static part of TOKEN struct
tok.wType = ResHeader.wTypeID;
tok.wName = IDFLAG;
tok.wReserved = ST_TRANSLATED;
wTotLen = pVerBlk->nTotLen;
pCurBlk = pVerBlk;
tok.wID = wcLang++;
pszStr = pCurBlk->szKey;
wcCurBlkLen = 4 + DWORDUP(lstrlen((TCHAR *)pszStr) + 1);
wTotLen -= wcCurBlkLen;
// Insert StringFileInfo Header into new version info buffer
// this info is not localized
memcpy((void *)pNewBlk, (void *)pCurBlk, wcCurBlkLen);
pszStr=pNewBlk->szKey;
// reposition pointers
pCurBlk = (VERBLOCK *) ((char *) pCurBlk + wcCurBlkLen);
pNewBlk = (VERBLOCK *) ((char *) pNewBlk + wcCurBlkLen);
lSize += wcCurBlkLen;
// Read All the StringTableBlocks
while (wTotLen > 8) {
// For String tables blocks we localizes the key field
tok.wFlag = ISKEY;
wcBlkLen = pCurBlk->nTotLen;
lstrcpy((TCHAR *)tok.szName, TEXT("Language Info"));
tok.wID = wcBlock;
tok.szText = NULL;
if ((pszStr = FindTokenText (TokFile,&tok,ST_TRANSLATED)) == NULL) {
// token not found, flag error and exit.
ParseTokToBuf(pErrBuf, &tok);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
RLFREE(tok.szText);
tok.szText = NULL;
tok.wReserved = ST_TRANSLATED;
// Do not know length of the translated StringTable block
// so set the nValLen to zero , and save location
// of string file block size field, to be fixed up latter.
pNewBlk->nValLen = 0;
pStrBlkSizeLoc = (WORD *) &pNewBlk->nTotLen;
// copy the translated key into that location
TextToBin(pNewBlk->szKey,pszStr,VERMEM-2*sizeof(int));
RLFREE( pszStr);
// Update localized string block count
wStrBlkSize = (WORD) DWORDUP (4 + lstrlen((TCHAR *)pNewBlk->szKey) + 1);
// get the length of the current block, note the
// translated length does not change.
wcCurBlkLen = 4 + pVerBlk->nValLen + DWORDUP(lstrlen((TCHAR *)pCurBlk->szKey) + 1);
lSize += wStrBlkSize;
// Update counter vars
wTotLen -= DWORDUP(wcBlkLen);
wcBlkLen -= wcCurBlkLen;
// repostion pointers
pCurBlk = (VERBLOCK *) ((char *)pCurBlk + DWORDUP(wcCurBlkLen));
pNewBlk = (VERBLOCK *) ((char *)pNewBlk + DWORDUP(wcCurBlkLen)) ;
// Read the String Blocks
// For String Blocks we localize the value fields.
tok.wFlag = ISVAL;
while (wcBlkLen > 0) {
// for string blocks we translate the value fields.
pszStr = pCurBlk->szKey;
lstrcpy((TCHAR *)tok.szName, (TCHAR *)pszStr);
tok.szText = NULL;
if ((pszStr= FindTokenText(TokFile,&tok,ST_TRANSLATED)) == NULL) {
//token not found, flag error and exit.
ParseTokToBuf(pErrBuf, &tok);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
RLFREE(tok.szText);
tok.szText = NULL;
tok.wReserved = ST_TRANSLATED;
lstrcpy((TCHAR *)pNewBlk->szKey, (TCHAR *)pCurBlk->szKey);
// position pointer to location to insert translated token text into pCurBlk
pszBuf = (TCHAR*) pNewBlk + 4 +
DWORDUP(lstrlen((TCHAR *)pNewBlk->szKey) + 1);
// now insert the token text
TextToBin(pszBuf,
pszStr ,
VERMEM - (4+DWORDUP(lstrlen((TCHAR *)pNewBlk->szKey)+1)));
RLFREE( pszStr);
// fix up counter fields in pNewBlk
pNewBlk->nValLen = lstrlen((TCHAR *)pszBuf) + 1;
pNewBlk->nTotLen = 4 + pNewBlk->nValLen +
DWORDUP(lstrlen((TCHAR *)pNewBlk->szKey) + 1);
wcBlkLen -= DWORDUP(pCurBlk->nTotLen);
lSize += DWORDUP(pNewBlk->nTotLen);
wStrBlkSize += DWORDUP(pNewBlk->nTotLen);
pCurBlk = (VERBLOCK *) ((char *) pCurBlk + DWORDUP(pCurBlk->nTotLen));
pNewBlk = (VERBLOCK *) ((char *) pNewBlk + DWORDUP(pNewBlk->nTotLen));
} // while
wcBlock ++;
*pStrBlkSizeLoc = wStrBlkSize ;
}
// this stuff is not translated so just copy it straight over
// Skip past Head of VarInfoBlock
pszStr = pCurBlk->szKey;
wTotLen = pCurBlk->nTotLen;
wcCurBlkLen = 4 + DWORDUP(pVerBlk->nValLen) +
DWORDUP(lstrlen((TCHAR *)pszStr) + 1);
wTotLen -= wcCurBlkLen;
// Insert Head of Var Info Into new block buffer
memcpy((void *)pNewBlk, (void *)pCurBlk, wcCurBlkLen);
pCurBlk = (VERBLOCK *) ((char *) pCurBlk + wcCurBlkLen);
pNewBlk = (VERBLOCK *) ((char *) pNewBlk + wcCurBlkLen);
lTotBlkSize = lSize; // Save the size value for the total Version blk (PW)
lSize += wcCurBlkLen;
wcLang = 0;
// Read the Var Info Blocks
// For Var Info Blocks we localize the Translation Value field.
tok.wFlag = ISVAL;
while (wTotLen > 0) {
pszStr = pCurBlk->szKey;
lstrcpy((TCHAR *)tok.szName, TEXT("Translation"));
tok.wID = wcLang;
tok.szText = NULL;
// Read Language ID
if ((pszStr = FindTokenText(TokFile, &tok,ST_TRANSLATED)) == NULL) {
//token not found, flag error and exit.
ParseTokToBuf(pErrBuf, &tok);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
RLFREE(tok.szText);
tok.szText = NULL;
tok.wReserved = ST_TRANSLATED;
// Found ascii translation string,
// convert it to binary and insert into pCurBlk
pwVal = (WORD *)((char *)pCurBlk +
DWORDUP(4 + lstrlen((TCHAR *)pCurBlk->szKey) + 1));
*pwVal = MyAtoW((CHAR *)pszStr);
pwVal++;
*pwVal = MyAtoW((CHAR *)&pszStr[4]);
wcLang ++;
wTotLen -= DWORDUP(pCurBlk->nTotLen );
memcpy((void *)pNewBlk, (void *)pCurBlk, pCurBlk->nTotLen);
lSize += pCurBlk->nTotLen;
// reposition pointers
pCurBlk = (VERBLOCK *) ((char *) pCurBlk + DWORDUP(pCurBlk->nTotLen) + 4);
pNewBlk = (VERBLOCK *) ((char *) pNewBlk + DWORDUP(pNewBlk->nTotLen) + 4);
RLFREE( pszStr);
}
// Now fixup VerHeader Size. header not localized so
// we do not need to update the value size.
pVerHdr = (VERHEAD *) pNewBlkStart;
pVerHdr->wTotLen = (WORD) lSize;
// Update first size value of Version block (PW)
wcTransBlkLen = sizeof (VERHEAD);
pNewBlk = (VERBLOCK *) ((char *) pNewBlkStart + wcTransBlkLen);
pNewBlk->nTotLen = (WORD) (lTotBlkSize - wcTransBlkLen);
// write new version stamping information to the resource file
wcRead = fwrite( (void *)pNewBlkStart,
sizeof(char),
(size_t)lSize,
OutResFile);
if (!UpdateResSize (OutResFile, &ResSizePos, lSize)) {
QuitT( IDS_ENGERR_07, MAKEINTRESOURCE( IDS_VERSTAMP), NULL);
}
RLFREE( pNewBlkStart);
}
#endif //... RLRES32
/**
*
*
* Function: PutStrHdr.
* Writes the string block info to the resource file.
*
*
* Arguments:
* OutResFile, pointer to resource file being generated.
* TokFile, pointer to token file containing localized string blocks.
* ResHeader, structure containing Resource Header info for the string block.
* pStrHder, Array of strings defined in the string block.
*
*
* Returns:
* OutResFile, containing localized string blocks.
*
* Errors Codes:
* None.
*
*
* History:
* 7/91. Implemented. TerryRu.
* 01/93 Added support for var length token text strings. MHotchin
*
**/
void PutStrHdr( FILE * OutResFile,
FILE * TokFile,
RESHEADER ResHeader,
STRINGHEADER *pStrHdr)
{
static TOKEN tok;
WORD i, j, k;
static TCHAR pErrBuf[MAXINPUTBUFFER];
fpos_t ResSizePos;
DWORD lSize = 0;
// write the Menu Res header
if ( PutResHeader (OutResFile, ResHeader , &ResSizePos, &lSize)) {
QuitT( IDS_ENGERR_06, (LPTSTR)IDS_MENU, NULL);
}
lSize = 0L;
for (i = 0; i < 16; i++) {
tok.wType = ResHeader.wTypeID;
tok.wName = ResHeader.wNameID;
tok.wID = i;
tok.wFlag = 0;
tok.wReserved = ST_TRANSLATED;
tok.szText = NULL;
tok.szName[0] = 0;
lstrcpy((TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName);
if ( ! FindToken(TokFile, &tok, ST_TRANSLATED) ) {
// can not find token, terminate
ParseTokToBuf( pErrBuf, &tok);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
tok.wReserved = ST_TRANSLATED;
// token text found continue
{
static TCHAR szTmp[4160];
int cChars = 0; //... # chars in token text, including nul
cChars = lstrlen( tok.szText) + 1;
j = TextToBin( szTmp, tok.szText, cChars) - 1;
RLFREE( tok.szText);
#ifdef RLRES16
PutByte( OutResFile, (BYTE) j, &lSize);
#else
PutWord( OutResFile, j, &lSize);
#endif
for (k = 0; k < j; k++) {
#ifdef RLRES16
PutByte( OutResFile, szTmp[k], &lSize);
#else
PutWord( OutResFile, szTmp[k], &lSize);
#endif
}
}
}
if (!UpdateResSize (OutResFile, &ResSizePos , lSize)) {
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_MENU, NULL);
}
}
/**
*
*
* Function: GetString.
* Read a block of 16 strings from string block in the resource file.
*
* Arguments:
* InResFile, file pointer to location of string block in the
* resource file.
* lSize, dummy var not used.
*
* Returns:
* pStrHdr containing 16 strings.
*
*
* Errors Codes:
* None.
*
* History:
* 7/91. Implemented. TerryRu.
*
*
**/
STRINGHEADER *GetString( FILE *InResFile, DWORD *lSize)
{
WORD wCharsLeft = 0; // Count of remaining characters in the string
WORD i = 0, j = 0; // Indexes into current block of 16 strings
STRINGHEADER *pStrHdr;
pStrHdr = (STRINGHEADER *)FALLOC( sizeof( STRINGHEADER));
for (j = 0; j < 16; j ++) {
#ifdef RLRES16
wCharsLeft = pStrHdr->sChars[j] = (WORD)GetByte( InResFile, lSize);
#else
wCharsLeft = pStrHdr->wChars[j] = GetWord( InResFile, lSize);
#endif
pStrHdr->pszStrings[j] = (TCHAR *)FALLOC( MEMSIZE( wCharsLeft + 1));
while ( wCharsLeft-- ) {
#ifdef RLRES32
pStrHdr->pszStrings[j][i] = GetWord( InResFile, lSize);
#else //RLRES32
pStrHdr->pszStrings[j][i] = GetByte( InResFile, lSize);
#endif //RLRES32
++i;
}
pStrHdr->pszStrings[j][i] = TEXT('\0');
i = 0;
}
return (pStrHdr);
}
/**
*
*
* Function: ReadInRes.
* Reads a block of info from the input resource file, and
*. then writes the same info to the ouput resource file.
*
*
* Arguments:
* InFile, handle of input file.
* OutFile, handle of ouput file.
* lSize, number of bytes to Copy.
*
*
* Returns:
*
*
* Errors Codes:
* 8, read error.
* 9, write error.
*
* History:
* 7/91, Implemented. TerryRu.
* 11/91, Bug fix to copy more then 64k blocks. PeterW.
* 4/92, Bug fix to copy blocks in smaller chunks to save memory. SteveBl
*
**/
#define CHUNK_SIZE 5120
void ReadInRes( FILE *InFile, FILE *ResFile, DWORD *plSize )
{
if ( *plSize > 0L ) {
PBYTE pBuf;
size_t cNum;
size_t cAmount;
pBuf = (PBYTE)FALLOC( CHUNK_SIZE);
do {
cAmount = (*plSize > (DWORD)CHUNK_SIZE ? CHUNK_SIZE : *plSize);
cNum = fread( (void *)pBuf, sizeof( BYTE), cAmount, InFile);
if ( cNum != cAmount ) {
QuitT( IDS_ENGERR_09, (LPTSTR)IDS_READ, NULL);
}
cNum = fwrite( (void *)pBuf, sizeof( BYTE), cAmount, ResFile);
if ( cNum != cAmount) {
QuitT( IDS_ENGERR_09, (LPTSTR)IDS_WRITE, NULL);
}
*plSize -= cAmount;
} while ( *plSize);
RLFREE( pBuf);
}
}
/**
*
*
* Function: TokAccelTable
* Reads array of accelerator keys, and writes info to be localized
* to the token file.
*
*
* Arguments:
* TokeFile, file pointer of token file.
* ResHeader, Resource Header for Accelerator resource. This info
* is need to generate token id.
* pAccelTable, array of accelerator keys.
* wcTableEntries, number of key definition in Accelerator table
*
*
* Returns:
* Accelerator info to be localized writen to token file.
*
* Errors Codes:
* None.
*
* History:
* 7/91, Implemented. TerryRu.
* 01/93 Added support for var length token text strings. MHotchin
*
**/
void TokAccelTable (FILE *TokFile ,
RESHEADER ResHeader,
ACCELTABLEENTRY * pAccelTable,
WORD wcTableEntries)
{
TOKEN tok;
WORD i, l;
char szBuf[10];
tok.wType = ResHeader.wTypeID;
tok.wName = ResHeader.wNameID;
tok.wFlag = 0;
tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
lstrcpy( tok.szName, ResHeader.pszName);
for (i = 0; i < wcTableEntries ; i ++) {
tok.wFlag = (WORD) pAccelTable[i].fFlags;
tok.wID = i;
// The order of wID and wAscii is reverse to the
// oder in the accelerator structure and the .rc file
sprintf( szBuf, "%hu %hu", pAccelTable[i].wID, pAccelTable[i].wAscii);
l = lstrlenA( szBuf) + 1;
tok.szText = (TCHAR *)FALLOC( MEMSIZE( l));
#ifdef RLRES32
_MBSTOWCS( (TCHAR *)tok.szText, szBuf, l, l);
#else
lstrcpyA(tok.szText, szBuf);
#endif
PutToken(TokFile, &tok);
RLFREE( tok.szText);
}
}
/**
*
*
* Function: TokDialog.
* Travers through linked list of the Dialog defintion, and writes any info
* which requires localization to the token file.
*
*
* Arguments:
* TokFile, file pointer of token file.
* ResHeader, Resource header info of dialog resource. This info is needed
* to generate the token id.
* pDialogHdr, linked list of dialog info. Each dialog control is a node
* in the linked list.
*
*
* Returns:
* The info requiring localization written to the tok file.
*
* Errors Codes:
* None.
*
* History:
* 7/91. Implemented. TerryRu.
* 7/91. Now tokenize all control cordiantes, so they are
* maintained during updates. TerryRu.
* 8/91. Supported signed coordinates. TerryRu.
* 1/93. Now tokenize dlg font names. TerryRu
* 01/93 Add support for var length token text MHotchin
**/
void TokDialog( FILE * TokFile, RESHEADER ResHeader, DIALOGHEADER *pDialogHdr)
{
WORD wcDup = 0;
WORD *pwIdBuf;
WORD i, j = 0, k = 0, l = 0;
static CHAR szTmpBuf[256];
static TCHAR szBuf[256];
static TOKEN tok;
*szTmpBuf = '\0';
*szBuf = TEXT('\0');
// tok the dialog caption
tok.wType = ResHeader.wTypeID;
tok.wName = ResHeader.wNameID;
tok.wID = 0;
tok.wFlag = ISCAP;
tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
lstrcpy ((TCHAR *)tok.szName , (TCHAR *)ResHeader.pszName);
tok.szText = BinToText( pDialogHdr->pszCaption,
lstrlen( pDialogHdr->pszCaption));
PutToken(TokFile, &tok);
RLFREE( tok.szText);
// tok the dialog cordinates
// bug fix, cordinates can be signed.
tok.wFlag = (ISCAP) | (ISCOR);
#ifdef RLRES32
sprintf( szTmpBuf, "%4hd %4hd %4hd %4hd",
pDialogHdr->x,
pDialogHdr->y,
pDialogHdr->cx,
pDialogHdr->cy);
if ( gfShowClass ) {
sprintf( &szTmpBuf[ strlen( szTmpBuf)], " : TDB");
}
_MBSTOWCS( szBuf,
szTmpBuf,
WCHARSIN( sizeof( szBuf)),
ACHARSIN( lstrlenA( szTmpBuf ) + 1 ));
#else
sprintf( szBuf, "%4hd %4hd %4hd %4hd",
pDialogHdr->x,
pDialogHdr->y,
pDialogHdr->cx,
pDialogHdr->cy);
#endif
tok.szText = BinToText( szBuf, lstrlen( szBuf));
PutToken(TokFile, &tok);
RLFREE( tok.szText);
if (gfExtendedTok) {
// toknize dialog fontname, and size
if ( pDialogHdr->lStyle & DS_SETFONT ) {
tok.wFlag = ISDLGFONTSIZE;
sprintf(szTmpBuf, "%hu", pDialogHdr->wPointSize);
l = lstrlenA( szTmpBuf) + 1;
tok.szText = (TCHAR *)FALLOC( MEMSIZE( l));
#ifdef RLRES32
_MBSTOWCS( (TCHAR*) tok.szText, szTmpBuf, l, l);
#else
strcpy(tok.szText, szTmpBuf);
#endif
PutToken(TokFile, &tok);
RLFREE( tok.szText);
tok.wFlag = ISDLGFONTNAME;
tok.szText = (TCHAR *)FALLOC( MEMSIZE( lstrlen( pDialogHdr->pszFontName) + 1));
lstrcpy( tok.szText, pDialogHdr->pszFontName);
PutToken( TokFile, &tok);
RLFREE( tok.szText);
tok.szText = NULL;
}
}
// allocate buffer for for duplicate check
pwIdBuf = (WORD *) FALLOC((DWORD) pDialogHdr->wNumberOfItems * sizeof(WORD));
for (i = 0; i < (WORD) pDialogHdr->wNumberOfItems; i ++) {
if (isdup ((WORD)pDialogHdr->pCntlData[i].dwID, pwIdBuf, (WORD)j)) {
tok.wID = (USHORT)wcDup++;
tok.wFlag = ISDUP;
} else {
// wid is unique so store in buffer for dup check
pwIdBuf[j++] = (USHORT)pDialogHdr->pCntlData[i].dwID;
tok.wID = (USHORT)pDialogHdr->pCntlData[i].dwID;
tok.wFlag = 0;
}
if (pDialogHdr->pCntlData[i].pszDlgText[0]) {
tok.szText = BinToText( pDialogHdr->pCntlData[i].pszDlgText,
lstrlen( (TCHAR *)pDialogHdr->pCntlData[i].pszDlgText));
PutToken(TokFile, &tok);
RLFREE( tok.szText);
}
// now do the dialog corrdinates,
// bug fix, cordinates can be signed.
#ifdef RLRES32
sprintf( szTmpBuf,
"%4hd %4hd %4hd %4hd",
pDialogHdr->pCntlData[i].x,
pDialogHdr->pCntlData[i].y,
pDialogHdr->pCntlData[i].cx,
pDialogHdr->pCntlData[i].cy);
_MBSTOWCS( szBuf,
szTmpBuf,
WCHARSIN( sizeof ( szBuf)),
ACHARSIN( lstrlenA( szTmpBuf ) + 1));
if (gfExtendedTok)
if ( (pDialogHdr->pCntlData[i].bClass_Flag == IDFLAG)
&& ((pDialogHdr->pCntlData[i].bClass == STATIC)
|| (pDialogHdr->pCntlData[i].bClass == EDIT) ) ) {
TCHAR *pszCtrl[3] =
{
TEXT("LEFT"),
TEXT("CENTER"),
TEXT("RIGHT")
};
TCHAR *pszAlign = NULL;
DWORD dwStyle = pDialogHdr->pCntlData[i].lStyle;
if ( pDialogHdr->pCntlData[i].bClass == STATIC ) {
// STATIC class alignment values are constants
// not flags, so we handle them differently
// than we do for the EDIT class below.
dwStyle &= (SS_LEFT|SS_CENTER|SS_RIGHT);
if ( dwStyle == SS_RIGHT ) {
pszAlign = pszCtrl[2];
} else if ( dwStyle == SS_CENTER ) {
pszAlign = pszCtrl[1];
} else if ( dwStyle == SS_LEFT ) {
pszAlign = pszCtrl[0];
}
} else { // Dealing with an EDIT class
if ( dwStyle & ES_RIGHT ) {
pszAlign = pszCtrl[2];
} else if ( dwStyle & ES_CENTER ) {
pszAlign = pszCtrl[1];
} else if ( dwStyle & ES_LEFT ) {
pszAlign = pszCtrl[0];
}
}
if ( pszAlign ) {
_stprintf( &szBuf[ _tcslen( szBuf)], TEXT(" ( %s ) "), pszAlign);
}
}
if ( gfShowClass ) {
if ( pDialogHdr->pCntlData[i].bClass_Flag == IDFLAG ) {
TCHAR *pszCtrl = TEXT("???"); //... DLG box control class
switch ( pDialogHdr->pCntlData[i].bClass ) {
case BUTTON:
{
WORD wTmp;
wTmp = (WORD)(pDialogHdr->pCntlData[i].lStyle & 0xffL);
switch ( wTmp ) {
case BS_PUSHBUTTON:
case BS_DEFPUSHBUTTON:
pszCtrl = TEXT("BUT");
break;
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
case BS_3STATE:
case BS_AUTO3STATE:
pszCtrl = TEXT("CHX");
break;
case BS_RADIOBUTTON:
case BS_AUTORADIOBUTTON:
pszCtrl = TEXT("OPT");
break;
case BS_GROUPBOX:
case BS_USERBUTTON:
case BS_OWNERDRAW:
case BS_LEFTTEXT:
default:
pszCtrl = TEXT("DIA");
break;
} //... END switch( wTmp )
break;
}
case STATIC:
#ifdef DBCS
//Special hack
//I will remove this code later.
//This code is for fix code between 1.84 and 1.85(STATIC alignment problem)
{
WORD wTmp;
wTmp = (WORD)(pDialogHdr->pCntlData[i].lStyle & (SS_LEFT|SS_CENTER|SS_RIGHT));
if ( (wTmp==SS_CENTER)
|| (wTmp==SS_LEFT) || (wTmp==SS_RIGHT) ) {
pszCtrl = TEXT("TXB");
} else {
pszCtrl = TEXT("ICO");
}
break;
}
#else // not DBCS
pszCtrl = TEXT("TXB");
break;
#endif // DBCS
default:
pszCtrl = TEXT("DIA");
break;
} //... END switch ( pDialogHdr->pCntlData[i].bClass )
wsprintf( &szBuf[ lstrlen( szBuf)], TEXT(" : %s"), pszCtrl);
} else {
wsprintf( &szBuf[ lstrlen( szBuf)],
TEXT(" : \"%s\""),
pDialogHdr->pCntlData[i].pszClass);
}
}
#else
sprintf(szBuf, "%4hd %4hd %4hd %4hd",
pDialogHdr->pCntlData[i].x,
pDialogHdr->pCntlData[i].y,
pDialogHdr->pCntlData[i].cx,
pDialogHdr->pCntlData[i].cy);
#endif
tok.wFlag |= ISCOR;
tok.szText = BinToText( szBuf, lstrlen( (TCHAR *)szBuf));
PutToken(TokFile, &tok);
RLFREE( tok.szText);
tok.szText = NULL;
}
RLFREE( pwIdBuf);
pwIdBuf = NULL;
}
/**
*
*
* Function: TokMenu,
* Travers the linked list of the Menu definition, and writes any info
* requiring localization to the token file.
*
*
* Arguments:
* TokFile, file pointer of token file.
* ResHeader, Resource header of Menu info. Need to generate token ids.
* pMenuHdr, Header of the menu used to access the linked list of token info.
*
* Returns:
* TokenFile contain all info requiring localization.
*
* Errors Codes:
* None.
*
* History:
* 7/91, Implemented. TerryRu.
* 01/93 Added support for var length token text strings. MHotchin
*
**/
void TokMenu(FILE *TokFile , RESHEADER ResHeader, MENUHEADER *pMenuHdr)
{
TOKEN tok;
static WORD wcPopUp = 0;
MENUITEM *pMenuItem;
pMenuItem = pMenuHdr->pMenuItem;
tok.wReserved = (gbMaster? ST_NEW : ST_NEW | ST_TRANSLATED);
while (pMenuItem) {
// if Menu Item is a seperator skip it
if (*pMenuItem->szItemText) {
tok.wType = ResHeader.wTypeID;
tok.wName = ResHeader.wNameID;
// check for the popup menu items
if ((pMenuItem->fItemFlags & MFR_POPUP) && pMenuHdr->fMenuEx) {
tok.wID = (pMenuItem->dwMenuID == 0 ||
pMenuItem->dwMenuID == 0x0000ffff) ?
(USHORT)pMenuItem->dwMenuID : 0x8000 + wcPopUp++;
tok.wFlag = ISPOPUP;
} else if (pMenuItem->fItemFlags & POPUP) {
tok.wID = wcPopUp++;
tok.wFlag = ISPOPUP;
} else {
tok.wID = (USHORT)pMenuItem->dwMenuID;
tok.wFlag = 0;
}
lstrcpy ((TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName);
tok.szText = BinToText( pMenuItem->szItemText,
lstrlen( (TCHAR *)pMenuItem->szItemText));
PutToken (TokFile, &tok);
RLFREE( tok.szText);
}
pMenuItem = pMenuItem->pNextItem;
}
}
/**
*
*
* Function: TokString
* Write the 16 strings contained in the string block.
*
*
* Arguments:
* TokFile, file pointer of Token File.
* ResHeader, Resource header info of String block.
* pStrHdr, Array of 16 strings making up portion of the string table.
*
* Returns:
* Strings written to the Token File.
*
* Errors Codes:
* None.
*
* History:
* 7/91, Implemented. TerryRu.
* 01/93 Added support for var length token text strings. MHotchin
*
**/
void TokString( FILE * TokFile, RESHEADER ResHeader, STRINGHEADER * pStrHdr)
{
// int nLen;
TOKEN tok;
BYTE i;
for ( i = 0; i < 16; i++ ) {
tok.wType = ResHeader.wTypeID;
tok.wName = ResHeader.wNameID;
tok.wID = i;
tok.wFlag = 0;
tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
lstrcpy( (TCHAR *)tok.szName, (TCHAR *)ResHeader.pszName);
// nLen = lstrlen( (TCHAR *)pStrHdr->pszStrings[i]); //DHW_TOOLONG
tok.szText = BinToText( (TCHAR *)pStrHdr->pszStrings[i], pStrHdr->wChars[i]);
PutToken( TokFile, &tok);
RLFREE( tok.szText);
}
}
#ifdef RLRES32
//................................................................
//...
//... Move to start of value field in version resource blocks
//... and adjust remaining-data-sizes accordingly.
PVERBLOCK MoveAlongVer(
PVERBLOCK pVerData, //... Start of current version block
WORD *pw1, //... First word to decrement
WORD *pw2, //... Second word to decrement
WORD *pw3) //... Third word to decrement
{
WORD wLen;
PBYTE pData = (PBYTE)pVerData;
wLen = DWORDUP( pVerData->wLength);
pData += DWORDUP( wLen);
DECWORDBY( pw1, wLen);
DECWORDBY( pw2, wLen);
DECWORDBY( pw3, wLen);
return ( (PVERBLOCK)pData);
}
//....................................................................
TCHAR *GetVerValue( PVERBLOCK pVerData)
{
WORD wLen = sizeof( VERBLOCK);
//... sizeof(VERBLOCK) already includes
//... the size of a WCHAR so we do not
//... need to add 1 to length of the key.
wLen += (WORD) (BYTESINSTRING( pVerData->szKey));
wLen = DWORDUP( wLen); //... Possible DWORD padding
return ( (TCHAR *)((PBYTE)pVerData + wLen));
}
//....................................................................
#endif //... RLRES32
/**
*
*
* Function: TokResVer
* Reads through the Version Info blocks, and writes any info requiring
* localization to the token file.
*
*
* Arguments:
* TokeFile, file pointer of token file.
* ResHeader, Resource Header info for version stamping. Need to generate
* the token IDs.
*
* Returns:
*
* Errors Codes:
* 1, info written to token file.
*
* History:
* 11/91. Implemented. TerryRu.
* 10/92. Added RLRES32 version DaveWi
* 01/93 Added support for var length token text strings. MHotchin
*
**/
#ifdef RLRES32
int TokResVer(
FILE *fpTokFile, //... Output token file
RESHEADER ResHeader, //... Resource header of version resource
VERBLOCK *pVerData, //... Data to tokenize
WORD wDataLen) //... # bytes in pVerData
{
TOKEN Tok;
BOOL fInStringInfo = FALSE; //... TRUE if reading StringFileInfo
WORD wTokNum = 0; //... Put into Tok.wID field
WORD wTokContinueNum = 0; //... Put into Tok.wFlag field
if (wDataLen == 0 || wDataLen == (WORD)-1) {
return (-1); //... No data to tokenize
}
//... Fill in static part of TOKEN struct
Tok.wType = ResHeader.wTypeID;
Tok.wName = IDFLAG;
Tok.szName[0] = TEXT('\0');
Tok.szType[0] = TEXT('\0');
Tok.wReserved = (gbMaster? ST_NEW : ST_NEW | ST_TRANSLATED);
//... Make a token for each string found
while (wDataLen > 0) {
WORD wRC;
//... Start of a StringFileInfo block?
wRC =(WORD)_tcsncmp((TCHAR *)pVerData->szKey,
(TCHAR *)STRINGFILEINFO,
min(wDataLen, (WORD)STRINGFILEINFOLEN));
if (wRC == SAME) {
WORD wStringInfoLen = 0; //... # of bytes in StringFileInfo
WORD wLen = 0;
//... Get # of bytes in this StringFileInfo
//... (Length of value is always 0 here)
wStringInfoLen = pVerData->wLength;
//... Move to start of first StringTable blk.
wLen = (WORD)(DWORDUP(sizeof(VERBLOCK)
- sizeof(WCHAR)
+ MEMSIZE( STRINGFILEINFOLEN)));
pVerData = (PVERBLOCK)((PBYTE)pVerData + wLen);
DECWORDBY(&wDataLen, wLen);
DECWORDBY(&wStringInfoLen, wLen);
while (wStringInfoLen > 0) {
WORD wStringTableLen = 0;
//... Get # of bytes in this StringTable
//... (Length of value is always 0 here)
wStringTableLen = pVerData->wLength;
//... Copy Language BLOCK Info key
//... into Token name
lstrcpy((TCHAR *)Tok.szName, (TCHAR *)LANGUAGEINFO);
//... Copy lang string into token
Tok.szText = (TCHAR *) FALLOC(MEMSIZE(LANGSTRINGLEN+1));
CopyMemory( Tok.szText,
pVerData->szKey,
LANGSTRINGLEN * sizeof ( TCHAR));
Tok.szText[ LANGSTRINGLEN] = TEXT('\0');
Tok.wID = wTokNum++;
Tok.wFlag = 0;
PutToken(fpTokFile, &Tok);
RLFREE( Tok.szText);
//... Move to start of first String.
wLen = DWORDUP(sizeof(VERBLOCK)
- sizeof(WCHAR)
+ MEMSIZE( LANGSTRINGLEN));
pVerData = (PVERBLOCK)((PBYTE)pVerData + wLen);
DECWORDBY(&wDataLen, wLen);
DECWORDBY(&wStringInfoLen, wLen);
DECWORDBY(&wStringTableLen, wLen);
while (wStringTableLen > 0) {
//... Is value a string?
if (pVerData->wType == VERTYPESTRING) {
Tok.wID = wTokNum++;
lstrcpy( (TCHAR *)Tok.szName, (TCHAR *)pVerData->szKey);
Tok.szText = BinToText( GetVerValue( pVerData),
lstrlen( GetVerValue( pVerData)));
PutToken(fpTokFile, &Tok);
RLFREE( Tok.szText);
}
//... Move to start of next String.
pVerData = MoveAlongVer(pVerData,
&wDataLen,
&wStringInfoLen,
&wStringTableLen);
} //... END while (wStringTableLen)
} //... END while (wStringInfoLen)
} else {
if (_tcsncmp((TCHAR *)pVerData->szKey,
(TCHAR *)VARFILEINFO,
min(wDataLen, (WORD)VARFILEINFOLEN)) == SAME) {
WORD wVarInfoLen = 0; //... # of bytes in VarFileInfo
WORD wLen = 0;
//... Get # of bytes in this VarFileInfo
//... (Length of value is always 0 here)
wVarInfoLen = pVerData->wLength;
//... Move to start of first Var.
wLen = (WORD)(DWORDUP(sizeof(VERBLOCK)
- sizeof(WCHAR)
+ MEMSIZE( VARFILEINFOLEN)));
pVerData = (PVERBLOCK)((PBYTE)pVerData + wLen);
DECWORDBY(&wDataLen, wLen);
DECWORDBY(&wVarInfoLen, wLen);
while (wVarInfoLen > 0) {
if (_tcsncmp(pVerData->szKey,
TRANSLATION,
min( wDataLen, (WORD)TRANSLATIONLEN)) == SAME) {
PBYTE pValue = NULL;
WORD wTransLen = 0;
USHORT uByte1 = 0;
USHORT uByte2 = 0;
UINT uLen = 0;
wTokContinueNum = 0;
//... How many bytes are we to tokenize?
wTransLen = pVerData->wValueLength;
//... Where are those bytes?
pValue = (PBYTE)GetVerValue(pVerData);
//... Copy VarFileInfo into Token
lstrcpy((TCHAR *)Tok.szName, (TCHAR *)pVerData->szKey);
//... Allocate a buffer for a space-separated
//... list of the lang ID's in this vresion res.
*szDHW = '\0';
while ( wTransLen >= TRANSDATALEN ) {
//... Write translation language id by
//... reversing byte pairs so the id looks
//... like the language id string. This will
//... have to be undone in PutResVer().
uByte1 = *pValue;
uByte2 = *(pValue + 1);
sprintf( &szDHW[ lstrlenA( szDHW)],
"%02hx%02hx",
uByte2, //... Reverses byte order to
uByte1); //... be like transltn str.
//... Move to next possible translation value
wTransLen -= TRANSDATALEN;
if ( wTransLen >= TRANSDATALEN ) {
pValue += TRANSDATALEN;
strcat( szDHW, " "); //... white-space sep
}
} //... END while ( wTransLen ...
uLen = lstrlenA( szDHW) + 1;
Tok.szText = (TCHAR *)FALLOC( MEMSIZE( uLen));
_MBSTOWCS( (TCHAR *)Tok.szText, szDHW, uLen, (UINT)-1);
Tok.wID = wTokNum;
Tok.wFlag = wTokContinueNum++;
PutToken( fpTokFile, &Tok);
RLFREE( Tok.szText);
} //... END if (_tcsncmp( ...
//... Move to start of next Var info block.
pVerData = MoveAlongVer(pVerData,
&wDataLen,
&wVarInfoLen,
NULL);
} //... END while (wVarInfoLen)
} else {
QuitT( IDS_ENGERR_14, (LPTSTR)IDS_INVVERBLK, NULL);
}
}
} //... END while (wDataLen)
return (0);
}
#else //... RLRES32
int TokResVer(FILE * TokFile, RESHEADER ResHeader, VERBLOCK *pVerBlk)
{
TCHAR szLangIdBuf[20];
TCHAR szCodePageIdBuf[20];
#ifdef RLRES32
CHAR szTmpBuf[20];
#endif
WORD wcLang = 0, wcBlock = 0;
TOKEN tok;
VERBLOCK *pCurBlk;
TCHAR *pszStr;
DWORD *pdwVal;
int wTotLen, nHeadLen, wBlkLen;
// the count fields are int because count may go negative
// because the last DWORD alignment is not counted in the
// byte count.
// Fill in static part of TOKEN struct
tok.wType = ResHeader.wTypeID;
tok.wName = IDFLAG;
tok.wReserved = (gbMaster? ST_NEW : ST_NEW | ST_TRANSLATED);
wTotLen = DWORDUP(pVerBlk->nTotLen);
tok.wID = wcBlock;
pszStr = pVerBlk->szKey;
nHeadLen = 4 + DWORDUP(pVerBlk->nValLen) + DWORDUP(lstrlen((TCHAR *)pszStr) + 1);
wTotLen -= nHeadLen;
pCurBlk = (VERBLOCK *) ((TCHAR *) pVerBlk + nHeadLen);
while (wTotLen > 0) {
// For string file tables we localize the key field
tok.wFlag = ISKEY;
wBlkLen = DWORDUP(pCurBlk->nTotLen);
pszStr = pCurBlk->szKey;
tok.szText = BinToText( pszStr, lstrlen((TCHAR *)pszStr));
lstrcpy((TCHAR *)tok.szName, TEXT("Language Info"));
tok.wID = wcBlock;
PutToken(TokFile, &tok);
RLFREE(tok.szText);
// Get offset to next block;
nHeadLen = 4 +
DWORDUP(pVerBlk->nValLen) +
DWORDUP(lstrlen((TCHAR *)pszStr) + 1);
// Update counter vars
wTotLen -= wBlkLen;
wBlkLen -= nHeadLen;
// set pointer to next ver block
pCurBlk = (VERBLOCK*) ((TCHAR *) pCurBlk + nHeadLen);
// For string blocks we localize the value field.
tok.wFlag = ISVAL;
// Now output the tokens in String Block
while (wBlkLen>0) {
pszStr = pCurBlk->szKey;
lstrcpy((TCHAR *)tok.szName, (TCHAR *)pszStr);
pszStr = (TCHAR *) pCurBlk+4+DWORDUP(lstrlen((TCHAR *)pszStr)+1);
tok.szText = BinToText( pszStr, lstrlen((TCHAR *)pszStr));
PutToken(TokFile, &tok);
RLFREE(tok.szText);
wBlkLen -= DWORDUP(pCurBlk->nTotLen);
pCurBlk = (VERBLOCK *) ((TCHAR *) pCurBlk + DWORDUP(pCurBlk->nTotLen));
}
wcBlock++;
}
// Skip past Head of VarInfoBlock
wTotLen = DWORDUP(pCurBlk->nTotLen);
pszStr = pCurBlk->szKey;
nHeadLen = 4 + DWORDUP(pVerBlk->nValLen) + DWORDUP(lstrlen((TCHAR *)pszStr) + 1);
wTotLen -= nHeadLen;
pCurBlk = (VERBLOCK *)((TCHAR *) pCurBlk + nHeadLen);
wcLang = 0;
// In Var File blocks we localize the value fields.
tok.wFlag = ISVAL;
while (wTotLen > 0) {
TCHAR szTemp[256];
pszStr = pCurBlk->szKey;
tok.wID = wcLang;
lstrcpy((TCHAR *)tok.szName, TEXT("Translation"));
pdwVal = (DWORD *)((TCHAR *) pCurBlk + 4 + DWORDUP(lstrlen((TCHAR *)pszStr) + 1));
#ifdef RLRES32
_itoa(HIWORD(*pdwVal) , szTmpBuf, 16);
_MBSTOWCS( szLangIdBuf,
szTmpBuf,
WCHARSIN( sizeof( szLangIdBuf)),
ACHARSIN( strlen( szTmpBuf ) + 1));
#else
_itoa(HIWORD(*pdwVal) , szLangIdBuf, 16);
#endif
#ifdef RLRES32
_itoa(LOWORD(*pdwVal), szTmpBuf, 16);
_MBSTOWCS( szCodePageIdBuf,
szTmpBuf,
WCHARSIN( sizeof( szCodePageIdBuf)),
ACHARSIN( strlen( szTmpBuf ) + 1));
#else
_itoa(LOWORD(*pdwVal), szCodePageIdBuf, 16);
#endif
// Construct Token Text
// Note leading zeros gets lost in itoa translation
lstrcpy((TCHAR *)szTemp, TEXT("0"));
_tcscat((TCHAR *)szTemp, _tcsupr((TCHAR *)szCodePageIdBuf));
_tcscat((TCHAR *)szTemp, TEXT("0"));
_tcscat((TCHAR *)szTemp, _tcsupr((TCHAR *)szLangIdBuf));
tok.szText = BinToText( szTemp, lstrlen((TCHAR *)szTemp));
PutToken(TokFile, &tok);
RLFREE(tok.szText);
wcLang ++;
wTotLen -= DWORDUP(pCurBlk->nTotLen);
pCurBlk = (VERBLOCK *) ((BYTE *) pCurBlk + DWORDUP(pCurBlk->nTotLen));
}
return (1);
}
#endif //... RLRES32
/**
*
*
* Function: UpdateResSize
* Preforms the Resource Header size fixup, once the size of
* the localized resource block is determined.
*
*
* Arguments:
* OutResFile, File pointer of localized resource file.
* pResSizePos, file location of size file, of the resoure header.
* lSize, size of the localized resource.
*
* Returns:
* The size field fixed up to the value specfied in the lsize.
*
* Errors Codes:
* TRUE, fixup sucessfull.
* Result of fsetpos, and fgetpos call.
*
* History:
*
*
**/
WORD UpdateResSize (FILE * OutResFile, fpos_t *pResSizePos, DWORD lSize)
{
WORD rc;
fpos_t tResSizePos;
if ((rc = (WORD) fgetpos (OutResFile, &tResSizePos)) != 0) {
return (rc);
}
if ((rc = (WORD) fsetpos (OutResFile, pResSizePos)) != 0) {
return (rc);
}
PutdWord(OutResFile, lSize, NULL);
if ((rc = (WORD) fsetpos (OutResFile, &tResSizePos)) != 0) {
return (rc);
}
return (TRUE) ;
}
/**
*
*
* Function:
*
*
* Arguments:
*
* Returns:
*
* Errors Codes:
*
* History:
* 01/93 Added support for var length token text strings. MHotchin
*
**/
void PutAccelTable(FILE *OutResFile,
FILE *TokFile,
RESHEADER ResHeader,
ACCELTABLEENTRY *pAccelTable,
WORD wcAccelEntries)
{
fpos_t ResSizePos = 0;
TOKEN tok;
WORD wcCount = 0;
DWORD lSize = 0L;
TCHAR pErrBuf[MAXINPUTBUFFER];
#ifdef RLRES32
CHAR szTmpBuf[30];
#endif
TCHAR *cpAscii, *cpID;
if ( PutResHeader (OutResFile, ResHeader , &ResSizePos, &lSize)) {
QuitT( IDS_ENGERR_06, (LPTSTR)IDS_ACCELKEY, NULL);
}
lSize = 0L;
// Prep for find token call
tok.wType = ResHeader.wTypeID;
tok.wName = ResHeader.wNameID;
tok.wID = 0;
tok.wFlag = 0;
tok.wReserved = ST_TRANSLATED;
lstrcpy( tok.szName, ResHeader.pszName);
for (wcCount = 0; wcCount < wcAccelEntries; wcCount++) {
tok.wID = wcCount;
tok.wFlag = (WORD) pAccelTable[wcCount].fFlags;
tok.szText = NULL;
if (!FindToken(TokFile, &tok, ST_TRANSLATED)) {
ParseTokToBuf(pErrBuf, &tok);
QuitT( IDS_ENGERR_05, pErrBuf, NULL);
}
tok.wReserved = ST_TRANSLATED;
cpID = (TCHAR *)tok.szText;
cpAscii = _tcschr((TCHAR *)tok.szText, TEXT(' '));
(*cpAscii) = '\0';
cpAscii++;
#ifdef RLRES16
#ifndef PDK2
PutByte (OutResFile, (BYTE) pAccelTable[wcCount].fFlags, &lSize);
#else // PDK2
PutWord (OutResFile, (WORD) pAccelTable[wcCount].fFlags, &lSize);
#endif // PDK2
#else // RLRES16
PutWord (OutResFile, (WORD) pAccelTable[wcCount].fFlags, &lSize);
#endif // RLRES16
#ifdef RLRES32
_WCSTOMBS( szTmpBuf,
cpAscii,
ACHARSIN( sizeof( szTmpBuf)),
lstrlen( cpAscii ) + 1 );
PutWord (OutResFile, (WORD) atoi(szTmpBuf), &lSize);
_WCSTOMBS( szTmpBuf,
cpID,
ACHARSIN( sizeof( szTmpBuf)),
lstrlen( cpID ) + 1 );
PutWord (OutResFile, (WORD) atoi(szTmpBuf), &lSize);
#else // RLRES32
PutWord (OutResFile, (WORD) atoi(cpAscii), &lSize);
PutWord (OutResFile, (WORD) atoi(cpID), &lSize);
#endif // RLRES32
#ifdef RLRES32
PutWord (OutResFile, pAccelTable[wcCount].wPadding, &lSize);
#endif
RLFREE( tok.szText);
} // for
if (!UpdateResSize (OutResFile, &ResSizePos , lSize)) {
QuitT( IDS_ENGERR_07, (LPTSTR)IDS_ACCELKEY, NULL);
}
} // PutAccelTable
void CopyRes(
FILE *fpInResFile,
FILE *fpOutResFile,
RESHEADER *pResHeader,
fpos_t *pResSizePos)
{
DWORD dwTmp = 0L;
PutResHeader( fpOutResFile, *pResHeader, pResSizePos, &dwTmp);
ReadInRes( fpInResFile, fpOutResFile, (DWORD *)&(pResHeader->lSize));
#ifdef RLRES32
DWordUpFilePointer( fpInResFile, MYREAD, ftell( fpInResFile), NULL);
DWordUpFilePointer( fpOutResFile, MYWRITE, ftell( fpOutResFile), NULL);
#endif
}
/////////////////////////////
// GetDlgInit
//
// VC++ uses a new resource type, DLGINIT (#240) when storing the
// initial contents of a list box. The data for this resource type
// is unaligned and containg non-Unicode strings. This function will
// read the resource data from the resource file pfInRes into a linked
// list of structures and will return a pointer to the head of that list.
// The parameter pdwSize contains the size of the resource as read from
// the resources associated resource header prior to this function
// being called.
// NOTE: The first entry in the list is aligned so it is treated
// slightly differently than are the remaining entries.
PDLGINITDATA GetDlgInit( FILE * pfInRes, DWORD *pdwSize)
{
PDLGINITDATA pList = NULL;
PDLGINITDATA pListEntry = NULL;
WORD wTmp = 0;
while ( *pdwSize > sizeof( DWORD) + 2 * sizeof( WORD) ) {
if ( pList ) { // allocate the next entry in the list
pListEntry->pNext = (PDLGINITDATA)FALLOC( sizeof( DLGINITDATA));
pListEntry = pListEntry->pNext;
} else { // allocate the head of the list
pList = (PDLGINITDATA)FALLOC( sizeof( DLGINITDATA));
pListEntry = pList;
}
// save the first two WORD fields of the data
pListEntry->wControlID = GetWord( pfInRes, pdwSize);
pListEntry->wMessageNumber = GetWord( pfInRes, pdwSize);
// get the string's length (incl nul terminator)
pListEntry->dwStringLen = GetdWord( pfInRes, pdwSize);
// get the string
pListEntry->pszString = FALLOC( pListEntry->dwStringLen);
for ( wTmp = 0; (pListEntry->pszString[ wTmp] = GetByte( pfInRes, pdwSize)); ++wTmp )
; // empty loop
}
// Skip the trailing zero-value WORD
SkipBytes( pfInRes, pdwSize);
#ifdef RLRES32
DWordUpFilePointer( pfInRes, MYREAD, ftell( pfInRes), NULL);
#endif
return ( pList);
}
//////////////////////////////
// TokDlgInit
//
// Make tokens in pTokFile out of the data in the pDlgInit linked list.
void TokDlgInit( FILE *pfTokFile, RESHEADER ResHeader, PDLGINITDATA pDlgInit)
{
int nLen = 0;
WORD wCount = 0;
static TOKEN Tok;
#ifdef UNICODE
static TCHAR szTmpBuf[ 256];
#else
PCHAR szTmpBuf = NULL;
#endif
ZeroMemory( &Tok, sizeof( Tok));
Tok.wType = ResHeader.wTypeID;
Tok.wName = ResHeader.wNameID;
Tok.wReserved = (gbMaster ? ST_NEW : ST_NEW | ST_TRANSLATED);
lstrcpy( Tok.szName, ResHeader.pszName);
while ( pDlgInit ) {
Tok.wID = wCount++;
Tok.wFlag = 0;
#ifdef UNICODE
nLen = _MBSTOWCS( szTmpBuf,
pDlgInit->pszString,
WCHARSIN( sizeof( szTmpBuf)),
(UINT)-1);
#else
nLen = strlen( pDlgInit->pszString);
szTmpBuf = pDlgInit->pszString;
#endif
Tok.szText = BinToTextW( szTmpBuf, nLen);
PutToken( pfTokFile, &Tok);
RLFREE( Tok.szText);
pDlgInit = pDlgInit->pNext;
}
}
////////////////////////////
// PutDlgInit
//
// Create a new resource in pfOutRes using the data stored in pDlgInit
// and the token text in the pfTokFile.
void PutDlgInit( FILE *pOutResFile, FILE *pTokFile, RESHEADER ResHeader, PDLGINITDATA pDlgInit)
{
fpos_t ResSizePos = 0;
TOKEN Tok;
DWORD lSize = 0L;
PCHAR pszTmp = NULL;
if ( PutResHeader( pOutResFile, ResHeader , &ResSizePos, &lSize)) {
QuitT( IDS_ENGERR_06, TEXT("DLGINIT"), NULL);
}
lSize = 0L;
// Prep for find token call
Tok.wType = ResHeader.wTypeID;
Tok.wName = ResHeader.wNameID;
Tok.wID = 0;
Tok.wFlag = 0;
Tok.wReserved = ST_TRANSLATED;
lstrcpy( Tok.szName, ResHeader.pszName);
while ( pDlgInit ) {
Tok.szText = NULL;
if ( ! FindToken( pTokFile, &Tok, ST_TRANSLATED)) {
ParseTokToBuf( (LPTSTR)szDHW, &Tok);
QuitT( IDS_ENGERR_05, (LPTSTR)szDHW, NULL);
}
Tok.wReserved = ST_TRANSLATED;
Tok.wID++;
// Write out the two unchanged WORD fields
PutWord( pOutResFile, pDlgInit->wControlID, &lSize);
PutWord( pOutResFile, pDlgInit->wMessageNumber, &lSize);
// write the length of the new string (incl nul)
_WCSTOMBS( szDHW, Tok.szText, DHWSIZE, (UINT)-1);
PutdWord( pOutResFile, strlen( szDHW) + 1, &lSize);
// write the new string (incl nul)
for ( pszTmp = szDHW; *pszTmp; ++pszTmp ) {
PutByte( pOutResFile, *pszTmp, &lSize);
}
PutByte( pOutResFile, '\0', &lSize);
pDlgInit = pDlgInit->pNext;
}
// write the trailing zero-value WORD
PutWord( pOutResFile, 0, &lSize);
if ( ! UpdateResSize( pOutResFile, &ResSizePos, lSize) ) {
QuitT( IDS_ENGERR_07, TEXT("DLGINIT"), NULL);
}
#ifdef RLRES32
DWordUpFilePointer( pOutResFile, MYWRITE, ftell( pOutResFile), NULL);
#endif
}
//////////////////////////////
// ClearDlgInitData
//
// Free the memory allocated for the DlgInitData linked list in GetDlgInit().
void ClearDlgInitData( PDLGINITDATA pDlgInit)
{
while ( pDlgInit ) {
PDLGINITDATA pTmp = pDlgInit->pNext;
RLFREE( pDlgInit->pszString);
RLFREE( pDlgInit);
pDlgInit = pTmp;
}
}