windows-nt/Source/XPSP1/NT/printscan/ui/compstui/resource.c

1026 lines
22 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1990-1995 Microsoft Corporation
Module Name:
resource.c
Abstract:
This module contains functions to load resources
Author:
29-Aug-1995 Tue 12:29:27 created -by- Daniel Chou (danielc)
[Environment:]
NT Windows - Common Printer Driver UI DLL.
[Notes:]
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define DBG_CPSUIFILENAME DbgResource
#define DBG_GETSTR0 0x00000001
#define DBG_GETSTR1 0x00000002
#define DBG_GETICON 0x00000004
#define DBG_COMPOSESTR 0x00000008
#define DBG_ADD_SPACE 0x00000010
#define DBG_ADD_WCHAR 0x00000020
#define DBG_AMPERCENT 0x00000040
DEFINE_DBGVAR(0);
extern HINSTANCE hInstDLL;
//
// Remove Ampercent will remove a '&' sign, if two '&' signs (ie. '&&') then
// only one is removed, ALSO if a '(&X)' (ie. SPACE + & + Left Parenthesis +
// Single Character + Right Parenthesis) then it consider to be a Localization
// hot key indicator, then the whole ' (&X)' will be removed
//
#define REMOVE_AMPERCENT(CHTYPE) \
{ \
CHTYPE *pOrg; \
CHTYPE *pCopy; \
UINT cRemoved; \
CHTYPE ch; \
\
\
cRemoved = 0; \
pOrg = \
pCopy = pStr; \
\
CPSUIDBG(DBG_AMPERCENT, ("RemoveAmpercent (ORG)='%ws'", pOrg)); \
\
do { \
\
while ((ch = *pStr++) && (ch != (CHTYPE)'&')) { \
\
if (cRemoved) { \
\
*pCopy = ch; \
} \
\
++pCopy; \
} \
\
if (ch) { \
\
++cRemoved; \
\
if (*pStr == (CHTYPE)'&') { \
\
*pCopy++ = *pStr++; \
\
} else if ((*(pCopy - 1) == (CHTYPE)'(') && \
(*(pStr + 1) == (CHTYPE)')')) { \
\
cRemoved += 3; \
ch = (CHTYPE)')'; \
pCopy -= 1; \
pStr += 2; \
\
if ((*pStr == (CHTYPE)' ') && \
((pCopy == pOrg) || \
((pCopy > pOrg) && \
(*(pCopy - 1) == (CHTYPE)' ')))) { \
\
CPSUIDBG(DBG_AMPERCENT, ("Extra SPACE")); \
\
if (pCopy == pOrg) { \
\
++pStr; \
\
} else { \
\
--pCopy; \
} \
\
++cRemoved; \
} \
} \
} \
\
} while (ch); \
\
if (cRemoved) { \
\
*pCopy = (CHTYPE)'\0'; \
\
CPSUIDBG(DBG_AMPERCENT, (" RemoveAmpercent (%3ld)='%ws'", \
cRemoved, pOrg)); \
} \
\
return(cRemoved); \
}
UINT
RemoveAmpersandA(
LPSTR pStr
)
/*++
Routine Description:
This function remove ampersand from a string, the string must be writable
Arguments:
pStr - string to be serarch and remove the ampersand if found
Return Value:
UINT, count of ampersands removed
Author:
19-Sep-1995 Tue 21:55:19 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
REMOVE_AMPERCENT(CHAR);
}
UINT
RemoveAmpersandW(
LPWSTR pStr
)
/*++
Routine Description:
This function remove ampersand from a string, the string must be writable
Arguments:
pwStr - string to be serarch and remove the ampersand if found
Return Value:
UINT, count of ampersands removed
Author:
19-Sep-1995 Tue 21:55:19 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
REMOVE_AMPERCENT(WCHAR);
}
UINT
DupAmpersandW(
LPWSTR pwStr,
INT cChar,
INT cMaxChar
)
/*++
Routine Description:
This function remove ampersand from a string, the string must be writable
Arguments:
pwStr - string to be serarch and remove the ampersand if found
Return Value:
UINT, count of ampersands removed
Author:
19-Sep-1995 Tue 21:55:19 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LPWSTR pw;
LPWSTR pwCopy;
INT i;
INT cAdd = 0;
if (((i = cChar) > 0) && ((cMaxChar -= cChar) > 0)) {
pw = pwStr;
while ((i--) && (cAdd < cMaxChar)) {
if (*pw++ == L'&') {
++cAdd;
}
}
if (cAdd) {
pw = pwStr + cChar;
pwCopy = pw + cAdd;
CPSUIASSERT(0, "DupAmpersandW(): pwStr[%u] is not NULL",
*pw == L'\0', IntToPtr(cChar));
while (pwCopy >= pwStr) {
if ((*pwCopy-- = *pw--) == L'&') {
*pwCopy-- = L'&';
}
}
}
}
return((UINT)cAdd);
}
UINT
GetString(
PGSBUF pGSBuf,
LPTSTR pStr
)
/*++
Routine Description:
This function load the string either from caller (ANSI or UNICODE) or
from common UI DLL, if the pStr is valid then it will just it, after
getting the correct string, it will convert it to UNICODE as needed
Arguments:
pGSBuf - Pointer to GSBUF structure and following structure must set
pTVWnd - Pointer to the TVWND which has all then information
needed.
pBuf - Pointer to the begining of the buffer (LPWSTR)
pEndBuf - Pointer to the end of the buffer
pStr - Pointer to the string to be converted
Return Value:
UINT - Count of character stored in the pBuf not include the NULL
terminator, if the pBuf only has one character left then it
always store a NULL and return 0
Author:
29-Aug-1995 Tue 12:30:49 created -by- Daniel Chou (danielc)
First version
31-Aug-1995 Thu 10:58:04 updated -by- Daniel Chou (danielc)
Re-write to do UNICODE conversion and ANSI call checking
05-Feb-1996 Mon 12:20:28 updated -by- Daniel Chou (danielc)
Fix the bug when UNICODE we do lstrcpy without checking the buffer
size.
Revision History:
--*/
{
LPWSTR pBuf;
WORD Flags;
GSBUF GSBuf = *pGSBuf;
UINT RemoveAmpersandOff = 0;
INT cChar;
INT Len = 0;
//
// Make pBuf pointed to the first available character
//
pBuf = pGSBuf->pBuf;
Flags = pGSBuf->Flags;
CPSUIASSERT(0, "GetString(pBuf=NULL)", pBuf, 0);
if (pGSBuf->pEndBuf) {
cChar = (INT)(pGSBuf->pEndBuf - pBuf);
} else {
cChar = MAX_RES_STR_CHARS;
}
//
// Check if we have room to convert the string, make sure we reduced the
// cChar by one for the NULL terminator
//
if ((pStr == NULL) || (cChar < 2)) {
if (pStr) {
CPSUIWARN(("GetString: pStr=%08lx, Buffer cChar=%ld too smaller",
pStr, cChar));
}
*pBuf = L'\0';
return(0);
}
if (pGSBuf->chPreAdd != L'\0') {
CPSUIDBG(DBG_GETSTR0, ("GetString(): Pre-Add Char = '%wc'",
pGSBuf->chPreAdd));
//
// If we pre-add character first then do it now
//
if ((*pBuf++ = pGSBuf->chPreAdd) == L'&') {
RemoveAmpersandOff = 1;
}
cChar--;
pGSBuf->chPreAdd = L'\0';
}
if (--cChar < 1) {
CPSUIDBG(DBG_GETSTR1, ("GetString()=Only has one character for SPACE"));
NULL;
} else if (!VALID_PTR(pStr)) {
HINSTANCE hInst;
WORD ResID;
//
// Apperantly this is the resource ID, the LoadString() will not
// write exceed the cChar included the NULL terminator according to
// the Win32 help file. At here we know we either have to convert
// the ASCII string to UNICODE or we load the UNICODE string to the
// buffer already
//
ResID = LOWORD(LODWORD(pStr));
CPSUIDBGBLK({
if ((ResID >= IDI_CPSUI_ICONID_FIRST) &&
(ResID <= IDI_CPSUI_ICONID_LAST)) {
CPSUIERR(("ResID=%ld is in icon ID range, change it", ResID));
ResID = ResID - IDI_CPSUI_ICONID_FIRST + IDS_CPSUI_STRID_FIRST;
}
})
if ((ResID >= IDS_CPSUI_STRID_FIRST) &&
(ResID <= IDS_CPSUI_STRID_LAST)) {
hInst = hInstDLL;
if (Flags & GBF_INT_NO_PREFIX) {
Flags &= ~GBF_PREFIX_OK;
}
} else {
hInst = (Flags & GBF_IDS_INT_CPSUI) ? hInstDLL : pGSBuf->hInst;
CPSUIASSERT(0, "GetString(hInst=NULL, %08lx)", pStr, 0);
}
//
// Now loaded from common UI DLL directly to the user buffer
//
if (Len = LoadString(hInst, ResID, pBuf, cChar)) {
pBuf += Len;
} else {
pBuf = pGSBuf->pBuf;
CPSUIERR(("LoadString(ID=%ld) FAILED", ResID));
}
} else if ((Flags & GBF_COPYWSTR) ||
(!(Flags & GBF_ANSI_CALL))) {
//
// We have UNICODE string but may need to put into the buffer
//
if (Len = lstrlen(pStr)) {
if (Len > cChar) {
Len = cChar;
}
CopyMemory(pBuf, pStr, sizeof(WCHAR) * Len);
pBuf += Len;
}
} else {
//
// We are loading the ANSI string
//
if (Len = lstrlenA((LPSTR)pStr)) {
if (Len = MultiByteToWideChar(CP_ACP,
0,
(LPCSTR)pStr,
Len,
pBuf,
cChar)) {
pBuf += Len;
} else {
//
// Conversion is not complete so make sure it NULL terminated
//
pBuf = pGSBuf->pBuf;
CPSUIWARN(("GetString: pstr='%hs', Buffer reach limit=%ld, Len=%ld",
pStr, cChar, Len));
}
CPSUIDBG(DBG_GETSTR0, ("Convert to UNICODE, Len=%d, cChar=%d",
Len, cChar));
}
}
//
// Save the new index back and return the len to the caller
//
*pBuf = L'\0';
Len = (INT)(pBuf - pGSBuf->pBuf);
if (!(Flags & GBF_PREFIX_OK)) {
Len -= RemoveAmpersandW(pGSBuf->pBuf + RemoveAmpersandOff);
}
if (Flags & GBF_DUP_PREFIX) {
Len += DupAmpersandW(pGSBuf->pBuf,
Len,
(INT)(UINT)(pGSBuf->pEndBuf - pGSBuf->pBuf));
}
CPSUIDBG(DBG_GETSTR1, ("GetString()=%ws (%d/%d)", pGSBuf->pBuf, Len, cChar));
CPSUIASSERT(0, "GetString() : Len != Real Len (%ld)",
Len == lstrlen(pGSBuf->pBuf), IntToPtr(lstrlen(pGSBuf->pBuf)));
pGSBuf->pBuf += Len;
return((UINT)Len);
}
UINT
GSBufAddNumber(
PGSBUF pGSBuf,
DWORD Number,
BOOL Sign
)
/*++
Routine Description:
Convert a number to a string with the limitation of GSBUF
Arguments:
pGSBuf - Pointer to GSBUF structure and following structure must set
pTVWnd - Pointer to the TVWND which has all then information
needed.
pBuf - Pointer to the begining of the buffer (LPWSTR)
pEndBuf - Pointer to the end of the buffer
Number - LONG number to be converted
Sign - if TRUE then Number is a sign long number else it is a unsigned
DWORD
Return Value:
UINT total bytes converted to the string
Author:
21-Feb-1996 Wed 12:17:00 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
WCHAR wBuf[16];
UINT cChar;
UINT Len = 0;
if (((cChar = (INT)(pGSBuf->pEndBuf - pGSBuf->pBuf - 1)) > 0) &&
(Len = wsprintf(wBuf, (Sign) ? L"%ld" : L"%lu", Number))) {
if (Len > cChar) {
Len = cChar;
}
CopyMemory(pGSBuf->pBuf, wBuf, sizeof(WCHAR) * Len);
pGSBuf->pBuf += Len;
*(pGSBuf->pBuf) = L'\0';
}
return(Len);
}
UINT
GSBufAddWChar(
PGSBUF pGSBuf,
UINT IntCharStrID,
UINT Count
)
/*++
Routine Description:
Add a single character to the GSBuf
Arguments:
pGSBuf - Pointer to GSBUF structure and following structure must set
pTVWnd - Pointer to the TVWND which has all then information
needed.
pBuf - Pointer to the begining of the buffer (LPWSTR)
pEndBuf - Pointer to the end of the buffer
wch - a single character to be added
Return Value:
BOOLEAN, true if succeed else false
Author:
21-Feb-1996 Wed 12:00:24 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
WCHAR wCh[2];
UINT cAvai;
if ((Count) &&
((cAvai = (UINT)(pGSBuf->pEndBuf - pGSBuf->pBuf)) > 1) &&
(LoadString(hInstDLL, IntCharStrID, wCh, COUNT_ARRAY(wCh)))) {
CPSUIDBG(DBG_ADD_WCHAR, ("GSBufAddWChar(%08lx, %u, %u)=%u of '%wc'",
pGSBuf, IntCharStrID, Count,
(Count > (cAvai - 1)) ? cAvai - 1 : Count, wCh[0]));
if (Count > (cAvai -= 1)) {
Count = cAvai;
}
cAvai = Count;
while (cAvai--) {
*(pGSBuf->pBuf)++ = wCh[0];
}
*(pGSBuf->pBuf) = L'\0';
return(Count);
} else {
CPSUIERR(("GSBufAddWChar(%08lx, %u, %u) FAILED",
pGSBuf, IntCharStrID, Count));
return(0);
}
}
UINT
GSBufAddSpace(
PGSBUF pGSBuf,
UINT Count
)
/*++
Routine Description:
Arguments:
Return Value:
Author:
20-Jul-1996 Sat 00:59:47 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
static WCHAR wSpace[2] = { 0, 0 };
UINT cAvai;
if (wSpace[0] == L'\0') {
LoadString(hInstDLL,
IDS_INT_CPSUI_SPACE_CHAR,
wSpace,
COUNT_ARRAY(wSpace));
}
if ((wSpace[0] != L'\0') &&
(Count) &&
((cAvai = (UINT)(pGSBuf->pEndBuf - pGSBuf->pBuf)) > 1)) {
CPSUIDBG(DBG_ADD_SPACE, ("GSBufAddSpace(%08lx, %u)=%u of '%wc'",
pGSBuf, Count,
(Count > (cAvai - 1)) ? cAvai - 1 : Count, wSpace[0]));
if (Count > (cAvai -= 1)) {
Count = cAvai;
}
cAvai = Count;
while (cAvai--) {
*(pGSBuf->pBuf)++ = wSpace[0];
}
*(pGSBuf->pBuf) = L'\0';
return(Count);
} else {
CPSUIERR(("GSBufAddSpace(%08lx, %u) FAILED", pGSBuf, Count));
return(0);
}
}
UINT
GetStringBuffer(
HINSTANCE hInst,
WORD GBFlags,
WCHAR chPreAdd,
LPTSTR pStr,
LPWSTR pBuf,
UINT cwBuf
)
/*++
Routine Description:
Arguments:
Return Value:
Author:
07-Sep-1995 Thu 10:45:09 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
GSBUF GSBuf;
GSBuf.hInst = hInst;
GSBuf.Flags = GBFlags;
GSBuf.pBuf = (LPWSTR)pBuf;
GSBuf.pEndBuf = (LPWSTR)pBuf + cwBuf;
GSBuf.chPreAdd = chPreAdd;
return(GetString(&GSBuf, pStr));
}
LONG
LoadCPSUIString(
LPTSTR pStr,
UINT cStr,
UINT StrResID,
BOOL AnsiCall
)
/*++
Routine Description:
Arguments:
Return Value:
Author:
08-Feb-1996 Thu 13:36:12 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
if ((pStr) && (cStr)) {
UINT Len = 0;
if ((StrResID >= IDS_CPSUI_STRID_FIRST) &&
(StrResID <= IDS_CPSUI_STRID_LAST)) {
if (AnsiCall) {
if (Len = LoadStringA(hInstDLL, StrResID, (LPSTR)pStr, cStr)) {
Len -= RemoveAmpersandA((LPSTR)pStr);
}
} else {
if (Len = LoadString(hInstDLL, StrResID, (LPWSTR)pStr, cStr)) {
Len -= RemoveAmpersandW((LPWSTR)pStr);
}
}
}
return((LONG)Len);
} else {
return(-1);
}
}
UINT
ComposeStrData(
HINSTANCE hInst,
WORD GBFlags,
LPWSTR pBuf,
UINT cwBuf,
UINT IntFormatStrID,
LPTSTR pStr,
DWORD dw1,
DWORD dw2
)
/*++
Routine Description:
Arguments:
Return Value:
Author:
19-Jul-1996 Fri 17:11:19 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
TCHAR szFormat[MAX_RES_STR_CHARS * 3];
LPTSTR pData;
LPTSTR pFinal;
UINT Count;
UINT i;
UINT cb;
ZeroMemory(szFormat, sizeof(szFormat));
if ((IntFormatStrID) &&
(i = LoadString(hInstDLL,
IntFormatStrID,
(LPTSTR)szFormat,
MAX_RES_STR_CHARS))) {
cb = ARRAYSIZE(szFormat) - i - 1;
pData = szFormat + i + 1;
if (!pStr) {
//
// Skip the pStr if it passed as NULL
//
Count = wnsprintf(pFinal = pData, cb, szFormat, dw1, dw2);
} else {
i = GetStringBuffer(hInst,
(WORD)(GBFlags | GBF_INT_NO_PREFIX),
(WCHAR)0,
pStr,
pData,
MAX_RES_STR_CHARS);
cb = cb - i - 1;
pFinal = pData + i + 1;
Count = wnsprintf(pFinal, cb, szFormat, pData, dw1, dw2);
}
if (Count > (cwBuf - 1)) {
Count = cwBuf - 1;
szFormat[Count] = '\0';
}
CopyMemory(pBuf, pFinal, (Count + 1) * sizeof(TCHAR));
CPSUIDBG(DBG_COMPOSESTR, ("ComposeString('%ws', '%ws', %lu, %lu)='%ws' [%u]",
szFormat, pData, dw1, dw2, pBuf, Count));
} else {
Count = GetStringBuffer(hInst, GBFlags, (WCHAR)0, pStr, pBuf, cwBuf);
CPSUIDBG(DBG_COMPOSESTR, ("ComposeString(%08lx, %lu, %lu)=FAILED, '%ws' [%u]",
pStr, dw1, dw2, pBuf, Count));
}
return(Count);
}