windows-nt/Source/XPSP1/NT/shell/comctl32/v5/unicwrap.cpp

5212 lines
154 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation, 1994-1995
//
// File: unicwrap.cpp
//
// Contents: Wrappers for all Unicode functions used in MSHTML.
// Any Unicode parameters/structure fields/buffers are converted
// to ANSI, and then the corresponding ANSI version of the function
// is called.
//
//----------------------------------------------------------------------------
#include "ctlspriv.h"
#ifdef UNICODE
#ifndef WINNT
#include "unicwrap.h"
#undef TextOutW
#undef ExtTextOutW
int MbcsFromUnicode(LPSTR pstr, int cch, LPCWSTR pwstr, int cwch = -1);
int UnicodeFromMbcs(LPWSTR pwstr, int cwch, LPCSTR pstr, int cch = -1);
//+---------------------------------------------------------------------------
//
// Member: CConvertStr::Free
//
// Synopsis: Frees string if alloc'd and initializes to NULL.
//
//----------------------------------------------------------------------------
void CConvertStr::Free()
{
if (_pstr != _ach && HIWORD64(_pstr) != 0)
{
delete [] _pstr;
}
_pstr = NULL;
}
//+---------------------------------------------------------------------------
//
// Member: CConvertStrW::Free
//
// Synopsis: Frees string if alloc'd and initializes to NULL.
//
//----------------------------------------------------------------------------
void CConvertStrW::Free()
{
if (_pwstr != _awch && HIWORD64(_pwstr) != 0)
{
delete [] _pwstr;
}
_pwstr = NULL;
}
//+---------------------------------------------------------------------------
//
// Member: CStrInW::Init
//
// Synopsis: Converts a LPSTR function argument to a LPWSTR.
//
// Arguments: [pstr] -- The function argument. May be NULL or an atom
// (HIWORD(pwstr) == 0).
//
// [cch] -- The number of characters in the string to
// convert. If -1, the string is assumed to be
// NULL terminated and its length is calculated.
//
// Modifies: [this]
//
//----------------------------------------------------------------------------
void CStrInW::Init(LPCSTR pstr, int cch)
{
int cchBufReq;
_cwchLen = 0;
// Check if string is NULL or an atom.
if (HIWORD64(pstr) == 0)
{
_pwstr = (LPWSTR) pstr;
return;
}
ASSERT(cch == -1 || cch > 0);
//
// Convert string to preallocated buffer, and return if successful.
//
_cwchLen = MultiByteToWideChar(
CP_ACP, 0, pstr, cch, _awch, ARRAYSIZE(_awch));
if (_cwchLen > 0)
{
if(_awch[_cwchLen-1] == 0)
_cwchLen--; // account for terminator
_pwstr = _awch;
return;
}
//
// Alloc space on heap for buffer.
//
cchBufReq = MultiByteToWideChar( CP_ACP, 0, pstr, cch, NULL, 0 );
ASSERT(cchBufReq > 0);
_pwstr = new WCHAR[cchBufReq];
if (!_pwstr)
{
// On failure, the argument will point to the empty string.
_awch[0] = 0;
_pwstr = _awch;
return;
}
ASSERT(HIWORD64(_pwstr));
_cwchLen = -1 + MultiByteToWideChar(
CP_ACP, 0, pstr, cch, _pwstr, cchBufReq );
ASSERT(_cwchLen >= 0);
}
//+---------------------------------------------------------------------------
//
// Member: CStrIn::CStrIn
//
// Synopsis: Inits the class.
//
// NOTE: Don't inline this function or you'll increase code size
// by pushing -1 on the stack for each call.
//
//----------------------------------------------------------------------------
CStrIn::CStrIn(LPCWSTR pwstr) : CConvertStr(CP_ACP)
{
Init(pwstr, -1);
}
CStrIn::CStrIn(UINT uCP, LPCWSTR pwstr) : CConvertStr(uCP)
{
Init(pwstr, -1);
}
//+---------------------------------------------------------------------------
//
// Member: CStrIn::Init
//
// Synopsis: Converts a LPWSTR function argument to a LPSTR.
//
// Arguments: [pwstr] -- The function argument. May be NULL or an atom
// (HIWORD(pwstr) == 0).
//
// [cwch] -- The number of characters in the string to
// convert. If -1, the string is assumed to be
// NULL terminated and its length is calculated.
//
// Modifies: [this]
//
//----------------------------------------------------------------------------
void CStrIn::Init(LPCWSTR pwstr, int cwch)
{
int cchBufReq;
#if DBG == 1 /* { */
int errcode;
#endif /* } */
_cchLen = 0;
// Check if string is NULL or an atom.
if (HIWORD64(pwstr) == 0)
{
_pstr = (LPSTR) pwstr;
return;
}
if ( cwch == 0 )
{
*_ach = '\0';
_pstr = _ach;
return;
}
ASSERT(cwch == -1 || cwch > 0);
//
// Convert string to preallocated buffer, and return if successful.
//
_cchLen = WideCharToMultiByte(
_uCP, 0, pwstr, cwch, _ach, ARRAYSIZE(_ach), NULL, NULL);
if (_cchLen > 0)
{
if (_ach[_cchLen-1]==0) _cchLen--; // account for terminator
_pstr = _ach;
return;
}
cchBufReq = WideCharToMultiByte(
CP_ACP, 0, pwstr, cwch, NULL, 0, NULL, NULL);
ASSERT(cchBufReq > 0);
_pstr = new char[cchBufReq];
if (!_pstr)
{
// On failure, the argument will point to the empty string.
_ach[0] = 0;
_pstr = _ach;
return;
}
ASSERT(HIWORD64(_pstr));
_cchLen = -1 + WideCharToMultiByte(
_uCP, 0, pwstr, cwch, _pstr, cchBufReq, NULL, NULL);
#if DBG == 1 /* { */
if (_cchLen < 0)
{
errcode = GetLastError();
ASSERT(0 && "WideCharToMultiByte failed in unicode wrapper.");
}
#endif /* } */
}
//+---------------------------------------------------------------------------
//
// Member: CStrInMulti::CStrInMulti
//
// Synopsis: Converts mulitple LPWSTRs to a multiple LPSTRs.
//
// Arguments: [pwstr] -- The strings to convert.
//
// Modifies: [this]
//
//----------------------------------------------------------------------------
CStrInMulti::CStrInMulti(LPCWSTR pwstr)
{
LPCWSTR pwstrT;
// We don't handle atoms because we don't need to.
ASSERT(HIWORD64(pwstr));
//
// Count number of characters to convert.
//
pwstrT = pwstr;
if (pwstr)
{
do {
while (*pwstrT++)
;
} while (*pwstrT++);
}
Init(pwstr, (int)(pwstrT - pwstr));
}
//+---------------------------------------------------------------------------
//
// Member: CStrOut::CStrOut
//
// Synopsis: Allocates enough space for an out buffer.
//
// Arguments: [pwstr] -- The Unicode buffer to convert to when destroyed.
// May be NULL.
//
// [cwchBuf] -- The size of the buffer in characters.
//
// Modifies: [this].
//
//----------------------------------------------------------------------------
CStrOut::CStrOut(LPWSTR pwstr, int cwchBuf) : CConvertStr(CP_ACP)
{
ASSERT(cwchBuf >= 0);
if (!cwchBuf)
pwstr = NULL;
_pwstr = pwstr;
_cwchBuf = cwchBuf;
if (!pwstr)
{
ASSERT(cwchBuf == 0);
_pstr = NULL;
return;
}
ASSERT(HIWORD64(pwstr));
// Initialize buffer in case Windows API returns an error.
_ach[0] = 0;
// Use preallocated buffer if big enough.
if (cwchBuf * 2 <= ARRAYSIZE(_ach))
{
_pstr = _ach;
return;
}
// Allocate buffer.
_pstr = new char[cwchBuf * 2];
if (!_pstr)
{
//
// On failure, the argument will point to a zero-sized buffer initialized
// to the empty string. This should cause the Windows API to fail.
//
ASSERT(cwchBuf > 0);
_pwstr[0] = 0;
_cwchBuf = 0;
_pstr = _ach;
return;
}
ASSERT(HIWORD64(_pstr));
_pstr[0] = 0;
}
//+---------------------------------------------------------------------------
//
// Member: CStrOut::ConvertIncludingNul
//
// Synopsis: Converts the buffer from MBCS to Unicode
//
// Return: Character count INCLUDING the trailing '\0'
//
//----------------------------------------------------------------------------
int CStrOut::ConvertIncludingNul()
{
int cwch;
if (!_pstr)
return 0;
ASSERT(_cwchBuf);
// Preinit to null string in case of horrible catastrophe
_pwstr[0] = TEXT('\0');
cwch = MultiByteToWideChar(_uCP, 0, _pstr, -1, _pwstr, _cwchBuf);
if (!cwch) {
// Output buffer was short. Must double-buffer (yuck)
int cwchNeeded = MultiByteToWideChar(_uCP, 0, _pstr, -1, NULL, 0);
if (cwchNeeded) {
LPWSTR pwsz = (LPWSTR)LocalAlloc(LMEM_FIXED,
cwchNeeded * SIZEOF(WCHAR));
if (pwsz) {
cwch = MultiByteToWideChar(_uCP, 0, _pstr, -1,
pwsz, cwchNeeded);
if (cwch) {
StrCpyNW(_pwstr, pwsz, _cwchBuf);
cwch = _cwchBuf;
}
LocalFree(pwsz);
}
} else {
#if DBG == 1 /* { */
DWORD errcode = GetLastError();
ASSERT(0 && "MultiByteToWideChar failed in unicode wrapper.");
#endif /* } */
}
}
Free();
return cwch;
}
//+---------------------------------------------------------------------------
//
// Member: CStrOut::ConvertExcludingNul
//
// Synopsis: Converts the buffer from MBCS to Unicode
//
// Return: Character count EXCLUDING the trailing '\0'
//
//----------------------------------------------------------------------------
int CStrOut::ConvertExcludingNul()
{
int ret = ConvertIncludingNul();
if (ret)
{
ret -= 1;
}
return ret;
}
//+---------------------------------------------------------------------------
//
// Member: CStrOut::~CStrOut
//
// Synopsis: Converts the buffer from MBCS to Unicode.
//
// Note: Don't inline this function, or you'll increase code size as
// both ConvertIncludingNul() and CConvertStr::~CConvertStr will be
// called inline.
//
//----------------------------------------------------------------------------
CStrOut::~CStrOut()
{
ConvertIncludingNul();
}
//+---------------------------------------------------------------------------
//
// Function: MbcsFromUnicode
//
// Synopsis: Converts a string to MBCS from Unicode.
//
// Arguments: [pstr] -- The buffer for the MBCS string.
// [cch] -- The size of the MBCS buffer, including space for
// NULL terminator.
//
// [pwstr] -- The Unicode string to convert.
// [cwch] -- The number of characters in the Unicode string to
// convert, including NULL terminator. If this
// number is -1, the string is assumed to be
// NULL terminated. -1 is supplied as a
// default argument.
//
// Returns: If [pstr] is NULL or [cch] is 0, 0 is returned. Otherwise,
// the number of characters converted, including the terminating
// NULL, is returned (note that converting the empty string will
// return 1). If the conversion fails, 0 is returned.
//
// Modifies: [pstr].
//
//----------------------------------------------------------------------------
int MbcsFromUnicode(LPSTR pstr, int cch, LPCWSTR pwstr, int cwch)
{
int ret;
#if DBG == 1 /* { */
int errcode;
#endif /* } */
ASSERT(cch >= 0);
if (!pstr || cch == 0)
return 0;
ASSERT(pwstr);
ASSERT(cwch == -1 || cwch > 0);
ret = WideCharToMultiByte(CP_ACP, 0, pwstr, cwch, pstr, cch, NULL, NULL);
#if DBG == 1 /* { */
if (ret <= 0)
{
errcode = GetLastError();
ASSERT(0 && "WideCharToMultiByte failed in unicode wrapper.");
}
#endif /* } */
return ret;
}
//+---------------------------------------------------------------------------
//
// Function: UnicodeFromMbcs
//
// Synopsis: Converts a string to Unicode from MBCS.
//
// Arguments: [pwstr] -- The buffer for the Unicode string.
// [cwch] -- The size of the Unicode buffer, including space for
// NULL terminator.
//
// [pstr] -- The MBCS string to convert.
// [cch] -- The number of characters in the MBCS string to
// convert, including NULL terminator. If this
// number is -1, the string is assumed to be
// NULL terminated. -1 is supplied as a
// default argument.
//
// Returns: If [pwstr] is NULL or [cwch] is 0, 0 is returned. Otherwise,
// the number of characters converted, including the terminating
// NULL, is returned (note that converting the empty string will
// return 1). If the conversion fails, 0 is returned.
//
// Modifies: [pwstr].
//
//----------------------------------------------------------------------------
int UnicodeFromMbcs(LPWSTR pwstr, int cwch, LPCSTR pstr, int cch)
{
int ret;
#if DBG == 1 /* { */
int errcode;
#endif /* } */
ASSERT(cwch >= 0);
if (!pwstr || cwch == 0)
return 0;
ASSERT(pstr);
ASSERT(cch == -1 || cch > 0);
ret = MultiByteToWideChar(CP_ACP, 0, pstr, cch, pwstr, cwch);
#if DBG == 1 /* { */
if (ret <= 0)
{
errcode = GetLastError();
ASSERT(0 && "MultiByteToWideChar failed in unicode wrapper.");
}
#endif /* } */
return ret;
}
//+------------------------------------------------------------------------
//
// Contents: widechar character type function (CT_CTYPE1) and (CT_CTYPE3)
//
// Synopsis: We do not have wide char support for IsChar functions
// under Win95. The Unicode-Wrapper functions we have
// in core\wrappers all convert to CP_ACP and then call
// the A version, which means we will have invalid results
// for any characters which aren't in CP_ACP.
//
// The solution is to roll our own, which result in these
// unfortunately large tables. Here's how it works:
//
// bits: fedc ba98 7654 3210
// pppp pppp iiib bbbb
//
// The 'b' bits form a 32-bit bit mask into our data. The data
// entrys boolean, and are thus 4-bytes long. Of the 2^32
// possible combinations, we in fact have only 218 distinct
// values of data. These are stored in adwData.
//
// The 'p' bits represent a page. Each page has eight
// possible entries, represent by 'i'. In most pages, the
// bitfields and data are both uniform.
//
// adwData[abIndex[abType[page]][index]] represents the data
//
// 1 << bits represents the bitmask.
//
//-------------------------------------------------------------------------
#define __BIT_SHIFT 0
#define __INDEX_SHIFT 5
#define __PAGE_SHIFT 8
#define __BIT_MASK 31
#define __INDEX_MASK 7
// straight lookup functions are inlined.
#define ISCHARFUNC(type, wch) \
(adwData[abIndex[abType1##type[wch>>__PAGE_SHIFT]] \
[(wch>>__INDEX_SHIFT)&__INDEX_MASK]] \
>> (wch&__BIT_MASK)) & 1
//
// To avoid header file conflicts with IsCharAlphaW, IsCharAlphaNumericW, ... defined in
// winuser.h, the functions names end in "Wrap". SHLWAPI.DEF exports these functions with
// the correct name.
//
STDAPI_(BOOL) IsCharAlphaWrap(WCHAR wch);
STDAPI_(BOOL) IsCharAlphaNumericWrap(WCHAR wch);
STDAPI_(BOOL) IsCharUpperWrap(WCHAR wch);
STDAPI_(BOOL) IsCharLowerWrap(WCHAR wch);
const DWORD adwData[218] =
{
0x00000000, 0x07fffffe, 0xff7fffff, 0xffffffff, // 0x00-0x03
0xfc3fffff, 0x00ffffff, 0xffff0000, 0x000001ff, // 0x04-0x07
0xffffd740, 0xfffffffb, 0x547f7fff, 0x000ffffd, // 0x08-0x0b
0xffffdffe, 0xdffeffff, 0xffff0003, 0xffff199f, // 0x0c-0x0f
0x033fcfff, 0xfffe0000, 0x007fffff, 0xfffffffe, // 0x10-0x13
0x000000ff, 0x000707ff, 0x000007fe, 0x7cffffff, // 0x14-0x17
0x002f7fff, 0xffffffe0, 0x03ffffff, 0xff000000, // 0x18-0x1b
0x00000003, 0xfff99fe0, 0x03c5fdff, 0xb0000000, // 0x1c-0x1f
0x00030003, 0xfff987e0, 0x036dfdff, 0x5e000000, // 0x20-0x23
0xfffbafe0, 0x03edfdff, 0x00000001, 0x03cdfdff, // 0x24-0x27
0xd63dc7e0, 0x03bfc718, 0xfffddfe0, 0x03effdff, // 0x28-0x2b
0x40000000, 0x03fffdff, 0x000d7fff, 0x0000003f, // 0x2c-0x2f
0xfef02596, 0x00006cae, 0x30000000, 0xffff003f, // 0x30-0x33
0x83ffffff, 0xffffff07, 0x07ffffff, 0x3f3fffff, // 0x34-0x37
0xaaff3f3f, 0x3fffffff, 0x1fdfffff, 0x0fcf1fdc, // 0x38-0x3b
0x1fdc1fff, 0xf0000000, 0x000003ff, 0x00000020, // 0x3c-0x3f
0x781fffff, 0x77ffffff, 0xfffe1fff, 0x00007fff, // 0x40-0x43
0x0000000f, 0x00003fff, 0x80f8007f, 0x5f7fffff, // 0x44-0x47
0xffffffdb, 0x0003ffff, 0xfff80000, 0xfffffdff, // 0x48-0x4b
0xfffffffd, 0xfffcffff, 0x0fff0000, 0x1fffffff, // 0x4c-0x4f
0xffffffc0, 0x7ffffffe, 0x1cfcfcfc, 0x00003e00, // 0x50-0x53
0x00000fff, 0x80000000, 0xfc00fffe, 0xf8000001, // 0x54-0x57
0x78000001, 0x00800000, 0x00040000, 0x7fffffff, // 0x58-0x5b
0x44300003, 0x000000b0, 0x0000007c, 0xfe000000, // 0x5c-0x5f
0x00000200, 0x00180000, 0x88001000, 0x0007f801, // 0x60-0x63
0x00013c00, 0xffd00000, 0x0000000e, 0x001f3fff, // 0x64-0x67
0x0001003c, 0xd0000000, 0x0080399f, 0x07fc000c, // 0x68-0x6b
0x00000004, 0x00003987, 0x001f0000, 0x00013bbf, // 0x6c-0x6f
0x00c0398f, 0x00010000, 0x0000000c, 0xc0000000, // 0x70-0x73
0x00803dc7, 0x00603ddf, 0x00803dcf, 0x87f28000, // 0x74-0x77
0x0c00ffc0, 0x3bff8000, 0x00003f5f, 0x08000000, // 0x78-0x7b
0xe0000000, 0xe000e003, 0x6000e000, 0xffff7fff, // 0x7c-0x7f
0x0000007f, 0xfc00fc00, 0x00007c00, 0x01ffffff, // 0x80-0x83
0xffff0007, 0x000007ff, 0x0000001f, 0x003fffff, // 0x84-0x87
0xffffdfff, 0x0000ffff, 0xfc0fffff, 0xfffff3de, // 0x88-0x8b
0xfffffeff, 0x7f47afff, 0xffc000fe, 0xff1fffff, // 0x8c-0x8f
0x7ffeffff, 0x80ffffff, 0x7e000000, 0x78000000, // 0x90-0x93
0x8fffffff, 0x0001ffff, 0xffff0fff, 0xf87fffff, // 0x94-0x97
0xffff000f, 0xfff7fe1f, 0xffd70f7f, 0x0001003e, // 0x98-0x9b
0x00007f7f, 0x03ff0000, 0x020c0000, 0x0000ffc0, // 0x9c-0x9f
0x0007ff80, 0x03f10000, 0x0000007e, 0x7f7fffff, // 0xa0-0xa3
0x55555555, 0xaa555555, 0x555554aa, 0x2b555555, // 0xa4-0xa7
0xb1dbced6, 0x11aed295, 0x4aaaadb0, 0x54165555, // 0xa8-0xab
0x00555555, 0xfffed740, 0x00000ffb, 0x541c0000, // 0xac-0xaf
0x00005555, 0x55550001, 0x5555088a, 0x01154555, // 0xb0-0xb3
0x00155555, 0x01555555, 0x3f00ff00, 0xff00ff00, // 0xb4-0xb7
0xaa003f00, 0x0000ff00, 0x1f00ff00, 0x0f001f00, // 0xb8-0xbb
0x1f001f00, 0xffc00000, 0xaaaaaaaa, 0x55aaaaaa, // 0xbc-0xbf
0xaaaaab55, 0xd4aaaaaa, 0x4e243129, 0x2651292a, // 0xc0-0xc3
0xb5555b60, 0xa82daaaa, 0x00aaaaaa, 0xffaffbfb, // 0xc4-0xc7
0x640f7ffc, 0x000001f9, 0xfffff000, 0x00637fff, // 0xc8-0xcb
0x000faaa8, 0xaaaa0002, 0xaaaa1114, 0x022a8aaa, // 0xcc-0xcf
0x07eaaaaa, 0x02aaaaaa, 0x003f00ff, 0x00ff00ff, // 0xd0-0xd3
0x00ff003f, 0x3fff00ff, 0x00df00ff, 0x00cf00dc, // 0xd4-0xd7
0x00dc00ff, 0x00f8007f
};
const BYTE abIndex[98][8] =
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x00
{ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02 }, // 0x01
{ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04 }, // 0x02
{ 0x05, 0x00, 0x06, 0x03, 0x03, 0x07, 0x00, 0x00 }, // 0x03
{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x09, 0x0a, 0x0b }, // 0x04
{ 0x0c, 0x03, 0x0d, 0x03, 0x0e, 0x03, 0x0f, 0x10 }, // 0x05
{ 0x00, 0x11, 0x12, 0x13, 0x14, 0x00, 0x06, 0x15 }, // 0x06
{ 0x00, 0x01, 0x16, 0x11, 0x03, 0x17, 0x18, 0x00 }, // 0x07
{ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 }, // 0x08
{ 0x21, 0x22, 0x23, 0x00, 0x24, 0x25, 0x00, 0x26 }, // 0x09
{ 0x1d, 0x27, 0x1f, 0x1c, 0x28, 0x29, 0x00, 0x00 }, // 0x0a
{ 0x2a, 0x2b, 0x00, 0x1c, 0x2a, 0x2b, 0x2c, 0x1c }, // 0x0b
{ 0x2a, 0x2d, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00 }, // 0x0c
{ 0x13, 0x2e, 0x2f, 0x00, 0x30, 0x31, 0x32, 0x00 }, // 0x0d
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x33, 0x12 }, // 0x0e
{ 0x03, 0x03, 0x34, 0x03, 0x03, 0x35, 0x03, 0x1a }, // 0x0f
{ 0x03, 0x03, 0x03, 0x03, 0x36, 0x03, 0x03, 0x1a }, // 0x10
{ 0x37, 0x03, 0x38, 0x39, 0x03, 0x3a, 0x3b, 0x3c }, // 0x11
{ 0x00, 0x00, 0x00, 0x00, 0x3d, 0x03, 0x03, 0x3e }, // 0x12
{ 0x3f, 0x00, 0x13, 0x03, 0x40, 0x13, 0x03, 0x41 }, // 0x13
{ 0x19, 0x42, 0x03, 0x03, 0x43, 0x00, 0x00, 0x00 }, // 0x14
{ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }, // 0x15
{ 0x03, 0x03, 0x03, 0x03, 0x03, 0x2f, 0x00, 0x00 }, // 0x16
{ 0x03, 0x03, 0x03, 0x03, 0x03, 0x44, 0x00, 0x00 }, // 0x17
{ 0x03, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x18
{ 0x46, 0x47, 0x48, 0x03, 0x03, 0x49, 0x4a, 0x4b }, // 0x19
{ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x4c }, // 0x1a
{ 0x03, 0x39, 0x06, 0x03, 0x4d, 0x03, 0x14, 0x4e }, // 0x1b
{ 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x4f }, // 0x1c
{ 0x00, 0x01, 0x01, 0x50, 0x03, 0x51, 0x52, 0x00 }, // 0x1d
{ 0x53, 0x26, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00 }, // 0x1e
{ 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x1f
{ 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x20
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55 }, // 0x21
{ 0x00, 0x56, 0x57, 0x58, 0x00, 0x13, 0x59, 0x59 }, // 0x22
{ 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00 }, // 0x23
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5b, 0x3e }, // 0x24
{ 0x03, 0x03, 0x2f, 0x5c, 0x5d, 0x00, 0x00, 0x00 }, // 0x25
{ 0x00, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00 }, // 0x26
{ 0x00, 0x00, 0x5f, 0x00, 0x60, 0x06, 0x44, 0x61 }, // 0x27
{ 0x62, 0x00, 0x63, 0x64, 0x00, 0x00, 0x65, 0x45 }, // 0x28
{ 0x66, 0x3d, 0x67, 0x68, 0x66, 0x69, 0x6a, 0x6b }, // 0x29
{ 0x6c, 0x69, 0x6d, 0x6e, 0x66, 0x3d, 0x6f, 0x00 }, // 0x2a
{ 0x66, 0x3d, 0x70, 0x71, 0x72, 0x73, 0x74, 0x00 }, // 0x2b
{ 0x66, 0x73, 0x75, 0x00, 0x72, 0x73, 0x75, 0x00 }, // 0x2c
{ 0x72, 0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x2d
{ 0x00, 0x77, 0x78, 0x00, 0x00, 0x79, 0x7a, 0x00 }, // 0x2e
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b }, // 0x2f
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7d, 0x7e }, // 0x30
{ 0x03, 0x7f, 0x80, 0x81, 0x82, 0x54, 0x06, 0x1c }, // 0x31
{ 0x03, 0x83, 0x4a, 0x03, 0x84, 0x03, 0x03, 0x85 }, // 0x32
{ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x49 }, // 0x33
{ 0x4c, 0x03, 0x03, 0x36, 0x00, 0x00, 0x00, 0x00 }, // 0x34
{ 0x03, 0x86, 0x85, 0x03, 0x03, 0x03, 0x03, 0x85 }, // 0x35
{ 0x03, 0x03, 0x03, 0x03, 0x87, 0x88, 0x03, 0x89 }, // 0x36
{ 0x8a, 0x03, 0x03, 0x89, 0x00, 0x00, 0x00, 0x00 }, // 0x37
{ 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x00, 0x00 }, // 0x38
{ 0x13, 0x91, 0x00, 0x00, 0x92, 0x00, 0x00, 0x93 }, // 0x39
{ 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 }, // 0x3a
{ 0x4f, 0x03, 0x44, 0x94, 0x03, 0x95, 0x96, 0x5b }, // 0x3b
{ 0x03, 0x03, 0x03, 0x97, 0x03, 0x03, 0x39, 0x5b }, // 0x3c
{ 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3d
{ 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x3e
{ 0x00, 0x98, 0x99, 0x9a, 0x03, 0x03, 0x03, 0x4f }, // 0x3f
{ 0x56, 0x57, 0x58, 0x9b, 0x73, 0x26, 0x00, 0x9c }, // 0x40
{ 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00 }, // 0x41
{ 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x9d }, // 0x42
{ 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x9f }, // 0x43
{ 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xa0 }, // 0x44
{ 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0x00 }, // 0x45
{ 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x9d, 0x00 }, // 0x46
{ 0x00, 0x00, 0x00, 0xa1, 0x3e, 0x00, 0x00, 0x00 }, // 0x47
{ 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x48
{ 0x00, 0x9d, 0xa2, 0xa2, 0x00, 0x00, 0x00, 0x00 }, // 0x49
{ 0x9d, 0xa2, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4a
{ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x00 }, // 0x4b
{ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab }, // 0x4c
{ 0xac, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x4d
{ 0x00, 0x00, 0x00, 0x00, 0xad, 0xae, 0xaf, 0xb0 }, // 0x4e
{ 0x0c, 0x89, 0x00, 0xa4, 0xb1, 0xa4, 0xb2, 0xb3 }, // 0x4f
{ 0x00, 0x11, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x50
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x2f, 0x00 }, // 0x51
{ 0xa4, 0xa4, 0xa4, 0xa4, 0xb4, 0xa4, 0xa4, 0xb5 }, // 0x52
{ 0xb6, 0xb7, 0xb8, 0xb9, 0xb7, 0xba, 0xbb, 0xbc }, // 0x53
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x89, 0x00 }, // 0x54
{ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x55
{ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x02 }, // 0x56
{ 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5 }, // 0x57
{ 0xc6, 0x00, 0x06, 0xc7, 0xc8, 0xc9, 0x00, 0x00 }, // 0x58
{ 0x00, 0x00, 0x00, 0x00, 0x71, 0xca, 0xcb, 0xcc }, // 0x59
{ 0x00, 0x06, 0x0d, 0xbe, 0xcd, 0xbe, 0xce, 0xcf }, // 0x5a
{ 0x00, 0x00, 0x00, 0x13, 0x14, 0x00, 0x00, 0x00 }, // 0x5b
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x12 }, // 0x5c
{ 0xbe, 0xbe, 0xbe, 0xbe, 0xd0, 0xbe, 0xbe, 0xd1 }, // 0x5d
{ 0xd2, 0xd3, 0xd4, 0xd5, 0xd3, 0xd6, 0xd7, 0xd8 }, // 0x5e
{ 0x00, 0x00, 0x00, 0x00, 0x3d, 0x87, 0x06, 0x3e }, // 0x5f
{ 0xd9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // 0x60
{ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 } // 0x61
};
const BYTE abType1Alpha[256] = // 154
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00,
0x00, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x00,
0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11,
0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x13, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x16,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x15, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d
};
BOOL IsCharSpaceW(WCHAR wch)
{
int nType;
switch(wch>>8)
{
case 0x00: nType = 0x1e; break;
case 0x20: nType = 0x1f; break;
case 0x30: nType = 0x20; break;
case 0xfe: nType = 0x21; break;
default: nType = 0x00; break;
}
return (adwData[abIndex[nType][(wch>>__INDEX_SHIFT)&__INDEX_MASK]]
>>(wch&__BIT_MASK)) & 1;
}
const BYTE abType1Punct[256] = // 32
{
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x00,
0x00, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x00,
0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x39, 0x3a, 0x3b, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3d, 0x00, 0x3e, 0x3f, 0x40
};
const BYTE abType1Digit[256] = // 11
{
0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00,
0x00, 0x43, 0x43, 0x44, 0x43, 0x45, 0x46, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48
};
BOOL IsCharDigitW(WCHAR wch) { return ISCHARFUNC(Digit, wch); }
BOOL IsCharXDigitW(WCHAR wch)
{
int nType;
switch(wch>>8)
{
case 0x00: nType = 0x49; break;
case 0xff: nType = 0x4a; break;
default: nType = 0x00; break;
}
return (adwData[abIndex[nType][(wch>>__INDEX_SHIFT)&__INDEX_MASK]]
>> (wch&__BIT_MASK)) & 1;
}
const BYTE abType1Upper[256] = // 12
{
0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53,
0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55
};
const BYTE abType1Lower[256] = // 13
{
0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0x5e,
0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x61
};
BOOL IsCharPunctW(WCHAR wch) { return ISCHARFUNC(Punct, wch); }
BOOL IsCharCntrlW(WCHAR wch)
{
return (unsigned)(wch - 0x0000) <= (0x001f - 0x0000)
|| (unsigned)(wch - 0x007f) <= (0x009f - 0x007f);
}
// NB (cthrash) WCH_NBSP is considered blank, for compatibility.
BOOL IsCharBlankW(WCHAR wch)
{
return wch == 0x0009
|| wch == 0x0020
|| wch == 0x00a0
|| wch == 0x3000
|| wch == 0xfeff;
}
BOOL IsCharAlphaWrap(WCHAR wch) { return ISCHARFUNC(Alpha, wch); }
BOOL IsCharUpperWrap(WCHAR wch) { return ISCHARFUNC(Upper, wch); }
BOOL IsCharLowerWrap(WCHAR wch) { return ISCHARFUNC(Lower, wch); }
BOOL IsCharAlphaNumericWrap(WCHAR wch)
{
return ISCHARFUNC(Alpha, wch) || ISCHARFUNC(Digit, wch);
}
static const BYTE abType3PageSub[256] =
{
0x00, 0x80, 0x81, 0x82, 0x00, 0x83, 0x84, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86,
0x00, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x8e, 0x8f, 0x90, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x91,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x20, 0x92, 0x00, 0x00, 0x93, 0x94, 0x00
};
static const BYTE abType3Page0[256] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08,
0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x09, 0x09,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09,
0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x09, 0x09, 0x01, 0x09, 0x09, 0x01,
0x01, 0x01, 0x00, 0x01, 0x09, 0x01, 0x01, 0x09,
0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const BYTE abType3Page32[256] =
{
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
0x11, 0x11, 0x01, 0x01, 0x11, 0x11, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static const BYTE abType3Page48[256] =
{
0x11, 0x11, 0x11, 0x00, 0x00, 0x20, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x11, 0x11, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00,
0x00, 0x06, 0x06, 0x16, 0x16, 0x04, 0x04, 0x00,
0x00, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
0x12, 0x12, 0x12, 0x12, 0x02, 0x12, 0x02, 0x12,
0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12,
0x02, 0x12, 0x02, 0x12, 0x02, 0x12, 0x02, 0x12,
0x02, 0x12, 0x02, 0x12, 0x12, 0x02, 0x12, 0x02,
0x12, 0x02, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
0x02, 0x02, 0x12, 0x02, 0x02, 0x12, 0x02, 0x02,
0x12, 0x02, 0x02, 0x12, 0x02, 0x02, 0x12, 0x12,
0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x02, 0x12,
0x02, 0x02, 0x12, 0x12, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x13, 0x06, 0x02, 0x02, 0x00
};
static const BYTE abType3Page255[256] =
{
0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10,
0x11, 0x11, 0x11, 0x11, 0x11, 0x10, 0x11, 0x11,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x00,
0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
struct tagType3DualValue
{
DWORD adwBitfield[8];
DWORD adwValue[2];
}
const aType3DualValue[21] =
{
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page1
0x00000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000001 },
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page2
0x00000000, 0x3f000000, 0x00000000, 0x00000000, 0x00000001 },
{ 0x00000000, 0x00000000, 0x00000000, 0x04000000, 0x000000b0, // Page3
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
{ 0x00000000, 0x00000000, 0xf8000000, 0x00000000, 0x00000200, // Page5
0x40000000, 0x00000009, 0x00180000, 0x00000000, 0x00000001 },
{ 0x88001000, 0x00000000, 0x00000000, 0x00003c00, 0x00000000, // Page6
0x00000000, 0x00100000, 0x00000200, 0x00000000, 0x00000001 },
{ 0x00000000, 0x80008000, 0x0c008040, 0x00000000, 0x00000000, // Page14
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page31
0xe0000000, 0xe000e003, 0x6000e000, 0x00000000, 0x00000001 },
{ 0x00800000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, // Page33
0xffffffff, 0xffffffff, 0x000007ff, 0x00000000, 0x00000001 },
{ 0x40000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page34
0x00000000, 0x00000000, 0xfffc0000, 0x00000001, 0x00000000 },
{ 0x00000002, 0x00000000, 0x00000000, 0xf8000000, 0xffffffff, // Page35
0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 },
{ 0x00000000, 0xffffffe0, 0xfffff800, 0xffffffff, 0xffffffff, // Page36
0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 },
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffc00000, // Page37
0x00002000, 0x00000000, 0xffff8000, 0x00000001, 0x00000000 },
{ 0x03f00000, 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, // Page38
0xffffffff, 0xffffffff, 0xffffffff, 0x00000001, 0x00000000 },
{ 0xfffff3de, 0xfffffeff, 0x7f47afff, 0x000000fe, 0xff100000, // Page39
0x7ffeffff, 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
{ 0x00000000, 0xfffe0000, 0xffffffff, 0x0000001f, 0x00000000, // Page49
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000010 },
{ 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0x00000000, // Page50
0x00000000, 0x00000fff, 0x00000000, 0x00000000, 0x00000001 },
{ 0x00000000, 0x00000000, 0xff000000, 0x0001ffff, 0x00000000, // Page51
0x00000000, 0x00000000, 0x7fffffff, 0x00000000, 0x00000001 },
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // Page159
0xffffffc0, 0xffffffff, 0xffffffff, 0x00000020, 0x00000000 },
{ 0x00000000, 0xffffc000, 0xffffffff, 0xffffffff, 0xffffffff, // Page250
0xffffffff, 0xffffffff, 0xffffffff, 0x00000020, 0x00000000 },
{ 0x00000000, 0xc0000000, 0x00000000, 0x00000000, 0x00000000, // Page253
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 },
{ 0x00000000, 0xfff90000, 0xfef7fe1f, 0x00000f77, 0x00000000, // Page254
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 }
};
//
// CType 3 Flag Bits.
//
// In the interest of reducing our table complexity, we've here a reduced
// bitfield. Only those bits currently used by IE4 are returned by
// GetStringType3Ex().
//
// These are the flags are they are defined in winnls.h
//
// C3_NONSPACING 0x0001
// C3_DIACRITIC 0x0002
// C3_VOWELMARK 0x0004
// C3_SYMBOL 0x0008
// C3_KATAKANA 0x0010
// C3_HIRAGANA 0x0020
// C3_HALFWIDTH 0x0040
// C3_FULLWIDTH 0x0080
// C3_IDEOGRAPH 0x0100
// C3_KASHIDA 0x0200
// C3_LEXICAL 0x0400
// C3_ALPHA 0x8000
// The supported flags are encoded by shifting them to the right 3 bits.
// C3_SYMBOL 0x0001
// C3_KATAKANA 0x0002
// C3_HIRAGANA 0x0004
// C3_HALFWIDTH 0x0008
// C3_FULLWIDTH 0x0010
// C3_IDEOGRAPH 0x0020
// GetStringType3Ex returns the correct Win32 flags NOT the compressed flags.
BOOL GetStringType3ExW(
LPCWSTR lpSrcStr, // string arg
int cchSrc, // length (or -1)
LPWORD lpCharType ) // output buffer
{
LPCWSTR lpStop = lpSrcStr + ((cchSrc == -1) ? MAXLONG : cchSrc);
while (lpSrcStr < lpStop)
{
WCHAR wch = *lpSrcStr++;
WORD wCharType;
BYTE bPageSub;
if (!wch && cchSrc == -1)
break;
switch (wch & (unsigned int)0xff00)
{
case 0x0000:
wCharType = abType3Page0[wch]; // Page0: 4 values
break;
case 0x2000:
wCharType = abType3Page32[wch & 0xff]; // Page32: 4 values
break;
case 0x3000:
wCharType = abType3Page48[wch & 0xff]; // Page48: 10 values
break;
case 0xff00:
wCharType = abType3Page255[wch & 0xff]; // Page255: 7 values
break;
default:
bPageSub = abType3PageSub[wch>>8];
if (bPageSub & 0x80) // 21 pages have 2 values
{
const struct tagType3DualValue *p = aType3DualValue +
(bPageSub & 0x7f);
wCharType = (BYTE) p->adwValue[(p->adwBitfield[(wch>>5)&7]
>> (wch & 0x1f)) & 1];
}
else // 231 pages have 1 value
{
wCharType = bPageSub;
}
break;
}
*lpCharType++ = wCharType << 3;
}
return TRUE;
}
//
// Str Functions from SHLWAPI
//
int StrCmpW(
IN LPCWSTR pwsz1,
IN LPCWSTR pwsz2)
{
int iRet = -1; // arbitrary on failure
ASSERT(IS_VALID_STRING_PTRW(pwsz1, -1));
ASSERT(IS_VALID_STRING_PTRW(pwsz2, -1));
if (pwsz1 && pwsz2)
{
CStrIn psz1(pwsz1);
CStrIn psz2(pwsz2);
iRet = lstrcmpA(psz1, psz2);
}
return iRet;
}
int StrCmpIW(
IN LPCWSTR pwsz1,
IN LPCWSTR pwsz2)
{
int iRet = -1; // arbitrary on failure
ASSERT(IS_VALID_STRING_PTRW(pwsz1, -1));
ASSERT(IS_VALID_STRING_PTRW(pwsz2, -1));
if (pwsz1 && pwsz2)
{
CStrIn psz1(pwsz1);
CStrIn psz2(pwsz2);
iRet = lstrcmpiA(psz1, psz2);
}
return iRet;
}
#if 0 // BUGBUG: We have another StrCpyW in strings.c
LPWSTR StrCpyW(LPWSTR psz1, LPCWSTR psz2)
{
LPWSTR psz = psz1;
ASSERT(psz1);
ASSERT(psz2);
while (*psz1++ = *psz2++)
;
return psz;
}
#endif
LPWSTR StrCatW(LPWSTR psz1, LPCWSTR psz2)
{
LPWSTR psz = psz1;
ASSERT(psz1);
ASSERT(psz2);
while (0 != *psz1)
psz1++;
while (*psz1++ = *psz2++)
;
return psz;
}
//+------------------------------------------------------------------------
//
// Implementation of the wrapped functions
//
//-------------------------------------------------------------------------
BOOL AppendMenuWrap(
HMENU hMenu,
UINT uFlags,
UINT uIDnewItem,
LPCWSTR lpnewItem)
{
ASSERT(!(uFlags & MF_BITMAP) && !(uFlags & MF_OWNERDRAW));
CStrIn str(lpnewItem);
return AppendMenuA(hMenu, uFlags, uIDnewItem, str);
}
BOOL CallMsgFilterWrap(LPMSG lpMsg, int nCode)
{
return CallMsgFilterA(lpMsg, nCode);
}
LRESULT CallWindowProcWrap(
WNDPROC lpPrevWndFunc,
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
return CallWindowProcA(lpPrevWndFunc, hWnd, Msg, wParam, lParam);
}
//----------------------------------------------------------------------
//
// function: CharLowerWrap( LPWSTR pch )
//
// purpose: Converts character to lowercase. Takes either a pointer
// to a string, or a character masquerading as a pointer.
// In the later case, the HIWORD must be zero. This is
// as spec'd for Win32.
//
// returns: Lowercased character or string. In the string case,
// the lowercasing is done inplace.
//
//----------------------------------------------------------------------
LPWSTR CharLowerWrap( LPWSTR pch )
{
if (!HIWORD64(pch))
{
WCHAR ch = (WCHAR)(LONG_PTR)pch;
CharLowerBuffWrap( &ch, 1 );
pch = (LPWSTR)MAKEINTATOM(ch);
}
else
{
CharLowerBuffWrap( pch, lstrlenW(pch) );
}
return pch;
}
//----------------------------------------------------------------------
//
// function: CharLowerBuffWrap( LPWSTR pch, DWORD cch )
//
// purpose: Converts a string to lowercase. String must be cch
// characters in length.
//
// returns: Character count (cch). The lowercasing is done inplace.
//
//----------------------------------------------------------------------
DWORD CharLowerBuffWrap( LPWSTR pch, DWORD cchLength )
{
DWORD cch;
for ( cch = cchLength; cch-- ; pch++ )
{
WCHAR ch = *pch;
if (IsCharUpperWrap(ch))
{
if (ch < 0x0100)
{
*pch += 32; // Get Latin-1 out of the way first
}
else if (ch < 0x0531)
{
if (ch < 0x0391)
{
if (ch < 0x01cd)
{
if (ch <= 0x178)
{
if (ch < 0x0178)
{
*pch += (ch == 0x0130) ? 0 : 1;
}
else
{
*pch -= 121;
}
}
else
{
static const BYTE abLookup[] =
{ // 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f
/* 0x0179-0x17f */ 1, 0, 1, 0, 1, 0, 0,
/* 0x0180-0x187 */ 0, 210, 1, 0, 1, 0, 206, 1,
/* 0x0188-0x18f */ 0, 205, 205, 1, 0, 0, 79, 202,
/* 0x0190-0x197 */ 203, 1, 0, 205, 207, 0, 211, 209,
/* 0x0198-0x19f */ 1, 0, 0, 0, 211, 213, 0, 214,
/* 0x01a0-0x1a7 */ 1, 0, 1, 0, 1, 0, 0, 1,
/* 0x01a8-0x1af */ 0, 218, 0, 0, 1, 0, 218, 1,
/* 0x01b0-0x1b7 */ 0, 217, 217, 1, 0, 1, 0, 219,
/* 0x01b8-0x1bf */ 1, 0, 0, 0, 1, 0, 0, 0,
/* 0x01c0-0x1c7 */ 0, 0, 0, 0, 2, 0, 0, 2,
/* 0x01c8-0x1cb */ 0, 0, 2, 0
};
*pch += abLookup[ch-0x0179];
}
}
else if (ch < 0x0386)
{
switch (ch)
{
case 0x01f1: *pch += 2; break;
case 0x01f2: break;
default: *pch += 1;
}
}
else
{
static const BYTE abLookup[] =
{ 38, 0, 37, 37, 37, 0, 64, 0, 63, 63 };
*pch += abLookup[ch-0x0386];
}
}
else
{
if (ch < 0x0410)
{
if (ch < 0x0401)
{
if (ch < 0x03e2)
{
if (!InRange(ch, 0x03d2, 0x03d4) &&
!(InRange(ch, 0x3da, 0x03e0) & !(ch & 1)))
{
*pch += 32;
}
}
else
{
*pch += 1;
}
}
else
{
*pch += 80;
}
}
else
{
if (ch < 0x0460)
{
*pch += 32;
}
else
{
*pch += 1;
}
}
}
}
else
{
if (ch < 0x2160)
{
if (ch < 0x1fba)
{
if (ch < 0x1f08)
{
if (ch < 0x1e00)
{
*pch += 48;
}
else
{
*pch += 1;
}
}
else if (!(InRange(ch, 0x1f88, 0x1faf) && (ch & 15)>7))
{
*pch -= 8;
}
}
else
{
static const BYTE abLookup[] =
{ // 8 9 a b c d e f
0, 0, 74, 74, 0, 0, 0, 0,
86, 86, 86, 86, 0, 0, 0, 0,
8, 8, 100, 100, 0, 0, 0, 0,
8, 8, 112, 112, 7, 0, 0, 0,
128, 128, 126, 126, 0, 0, 0, 0
};
int i = (ch-0x1fb0);
*pch -= (int)abLookup[((i>>1) & ~7) | (i & 7)];
}
}
else
{
if (ch < 0xff21)
{
if (ch < 0x24b6)
{
*pch += 16;
}
else
{
*pch += 26;
}
}
else
{
*pch += 32;
}
}
}
}
else
{
// These are Unicode Number Forms. They have lowercase counter-
// parts, but are not considered uppercase. Why, I don't know.
if (InRange(ch, 0x2160, 0x216f))
{
*pch += 16;
}
}
}
return cchLength;
}
//
// BUGBUG - Do CharNextWrap and CharPrevWrap need to call the
// CharNextW, CharPrevW on WinNT? Couldn't these be MACROS?
LPWSTR CharNextWrap(LPCWSTR lpszCurrent)
{
if (*lpszCurrent)
{
return (LPWSTR) lpszCurrent + 1;
}
else
{
return (LPWSTR) lpszCurrent;
}
}
LPWSTR CharPrevWrap(LPCWSTR lpszStart, LPCWSTR lpszCurrent)
{
if (lpszCurrent == lpszStart)
{
return (LPWSTR) lpszStart;
}
else
{
return (LPWSTR) lpszCurrent - 1;
}
}
BOOL CharToOemWrap(LPCWSTR lpszSrc, LPSTR lpszDst)
{
CStrIn str(lpszSrc);
return CharToOemA(str, lpszDst);
}
//----------------------------------------------------------------------
//
// function: CharUpperWrap( LPWSTR pch )
//
// purpose: Converts character to uppercase. Takes either a pointer
// to a string, or a character masquerading as a pointer.
// In the later case, the HIWORD must be zero. This is
// as spec'd for Win32.
//
// returns: Uppercased character or string. In the string case,
// the uppercasing is done inplace.
//
//----------------------------------------------------------------------
LPWSTR CharUpperWrap( LPWSTR pch )
{
if (!HIWORD64(pch))
{
WCHAR ch = (WCHAR)(LONG_PTR)pch;
CharUpperBuffWrap( &ch, 1 );
pch = (LPWSTR)MAKEINTATOM(ch);
}
else
{
CharUpperBuffWrap( pch, lstrlenW(pch) );
}
return pch;
}
//----------------------------------------------------------------------
//
// function: CharUpperBuffWrap( LPWSTR pch, DWORD cch )
//
// purpose: Converts a string to uppercase. String must be cch
// characters in length. Note that this function is
// is messier that CharLowerBuffWrap, and the reason for
// this is many Unicode characters are considered uppercase,
// even when they don't have an uppercase counterpart.
//
// returns: Character count (cch). The uppercasing is done inplace.
//
//----------------------------------------------------------------------
DWORD CharUpperBuffWrap( LPWSTR pch, DWORD cchLength )
{
DWORD cch;
for ( cch = cchLength; cch-- ; pch++ )
{
WCHAR ch = *pch;
if (IsCharLowerWrap(ch))
{
if (ch < 0x00ff)
{
*pch -= ((ch != 0xdf) << 5);
}
else if (ch < 0x03b1)
{
if (ch < 0x01f5)
{
if (ch < 0x01ce)
{
if (ch < 0x017f)
{
if (ch < 0x0101)
{
*pch += 121;
}
else
{
*pch -= (ch != 0x0131 &&
ch != 0x0138 &&
ch != 0x0149);
}
}
else if (ch < 0x01c9)
{
static const BYTE abMask[] =
{ // 6543210f edcba987
0xfc, 0xbf, // 11111100 10111111
0xbf, 0x67, // 10111111 01100111
0xff, 0xef, // 11111111 11101111
0xff, 0xf7, // 11111111 11110111
0xbf, 0xfd // 10111111 11111101
};
int i = ch - 0x017f;
*pch -= ((abMask[i>>3] >> (i&7)) & 1) +
(ch == 0x01c6);
}
else
{
*pch -= ((ch != 0x01cb)<<1);
}
}
else
{
if (ch < 0x01df)
{
if (ch < 0x01dd)
{
*pch -= 1;
}
else
{
*pch -= 79;
}
}
else
{
*pch -= 1 + (ch == 0x01f3) -
InRange(ch,0x01f0,0x01f2);
}
}
}
else if (ch < 0x0253)
{
*pch -= (ch < 0x0250);
}
else if (ch < 0x03ac)
{
static const BYTE abLookup[] =
{// 0/8 1/9 2/a 3/b 4/c 5/d 6/e 7/f
/* 0x0253-0x0257 */ 210, 206, 0, 205, 205,
/* 0x0258-0x025f */ 0, 202, 0, 203, 0, 0, 0, 0,
/* 0x0260-0x0267 */ 205, 0, 0, 207, 0, 0, 0, 0,
/* 0x0268-0x026f */ 209, 211, 0, 0, 0, 0, 0, 211,
/* 0x0270-0x0277 */ 0, 0, 213, 0, 0, 214, 0, 0,
/* 0x0278-0x027f */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x0280-0x0287 */ 0, 0, 0, 218, 0, 0, 0, 0,
/* 0x0288-0x028f */ 218, 0, 217, 217, 0, 0, 0, 0,
/* 0x0290-0x0297 */ 0, 0, 219
};
if (ch <= 0x0292)
{
*pch -= abLookup[ch - 0x0253];
}
}
else
{
*pch -= (ch == 0x03b0) ? 0 : (37 + (ch == 0x03ac));
}
}
else
{
if (ch < 0x0561)
{
if (ch < 0x0451)
{
if (ch < 0x03e3)
{
if (ch < 0x03cc)
{
*pch -= (ch != 0x03c2)<<5;
}
else
{
int i = (ch < 0x03d0);
*pch -= (i<<6) - i + (ch == 0x03cc);
}
}
else if (ch < 0x0430)
{
*pch -= (ch < 0x03f0);
}
else
{
*pch -= 32;
}
}
else if (ch < 0x0461)
{
*pch -= 80;
}
else
{
*pch -= 1;
}
}
else
{
if (ch < 0x1fb0)
{
if (ch < 0x1f70)
{
if (ch < 0x1e01)
{
int i = ch != 0x0587 && ch != 0x10f6;
*pch -= ((i<<5)+(i<<4)); /* 48 */
}
else if (ch < 0x1f00)
{
*pch -= !InRange(ch, 0x1e96, 0x1e9a);
}
else
{
int i = !InRange(ch, 0x1f50, 0x1f56)||(ch & 1);
*pch += (i<<3);
}
}
else
{
static const BYTE abLookup[] =
{ 74, 86, 86, 100, 128, 112, 126 };
if ( ch <= 0x1f7d )
{
*pch += abLookup[(ch-0x1f70)>>1];
}
}
}
else
{
if (ch < 0x24d0)
{
if (ch < 0x1fe5)
{
*pch += (0x0023 & (1<<(ch&15))) ? 8 : 0;
}
else if (ch < 0x2170)
{
*pch += (0x0023 & (1<<(ch&15))) ? 7 : 0;
}
else
{
*pch -= ((ch > 0x24b5)<<4);
}
}
else if (ch < 0xff41)
{
int i = !InRange(ch, 0xfb00, 0xfb17);
*pch -= (i<<4)+(i<<3)+(i<<1); /* 26 */
}
else
{
*pch -= 32;
}
}
}
}
}
else
{
int i = InRange(ch, 0x2170, 0x217f);
*pch -= (i<<4);
}
}
return cchLength;
}
int CopyAcceleratorTableWrap(
HACCEL hAccelSrc,
LPACCEL lpAccelDst,
int cAccelEntries)
{
return CopyAcceleratorTableA(hAccelSrc, lpAccelDst, cAccelEntries);
}
HACCEL CreateAcceleratorTableWrap(LPACCEL lpAccel, int cEntries)
{
return CreateAcceleratorTableA(lpAccel, cEntries);
}
typedef HDC (*FnCreateHDCA)(LPCSTR, LPCSTR, LPCSTR, CONST DEVMODEA *);
HDC CreateHDCWrap(
LPCWSTR lpszDriver,
LPCWSTR lpszDevice,
LPCWSTR lpszOutput,
CONST DEVMODEW * lpInitData,
FnCreateHDCA pfn)
{
DEVMODEA * pdevmode = NULL;
CStrIn strDriver(lpszDriver);
CStrIn strDevice(lpszDevice);
CStrIn strOutput(lpszOutput);
HDC hdcReturn = 0;
if (lpInitData)
{
pdevmode = (DEVMODEA *) LocalAlloc( LPTR, lpInitData->dmSize + lpInitData->dmDriverExtra );
if (pdevmode)
{
MbcsFromUnicode((CHAR *)pdevmode->dmDeviceName, CCHDEVICENAME, lpInitData->dmDeviceName);
memcpy(&pdevmode->dmSpecVersion,
&lpInitData->dmSpecVersion,
FIELD_OFFSET(DEVMODEW,dmFormName) - FIELD_OFFSET(DEVMODEW,dmSpecVersion));
MbcsFromUnicode((CHAR *)pdevmode->dmFormName, CCHFORMNAME, lpInitData->dmFormName);
memcpy(&pdevmode->dmLogPixels,
&lpInitData->dmLogPixels,
lpInitData->dmDriverExtra + lpInitData->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
pdevmode->dmSize -= (sizeof(BCHAR) - sizeof(char)) * (CCHDEVICENAME + CCHFORMNAME);
}
}
hdcReturn = (*pfn)(strDriver, strDevice, strOutput, pdevmode);
if (pdevmode)
{
LocalFree(pdevmode);
}
return hdcReturn;
}
HDC CreateDCWrap(
LPCWSTR lpszDriver,
LPCWSTR lpszDevice,
LPCWSTR lpszOutput,
CONST DEVMODEW * lpInitData)
{
return CreateHDCWrap(lpszDriver, lpszDevice, lpszOutput, lpInitData, CreateDCA);
}
HDC CreateICWrap(
LPCWSTR lpszDriver,
LPCWSTR lpszDevice,
LPCWSTR lpszOutput,
CONST DEVMODEW * lpInitData)
{
return CreateHDCWrap(lpszDriver, lpszDevice, lpszOutput, lpInitData, CreateICA);
}
BOOL CreateDirectoryWrap(
LPCWSTR lpPathName,
LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
CStrIn str(lpPathName);
ASSERT(!lpSecurityAttributes);
return CreateDirectoryA(str, lpSecurityAttributes);
}
HANDLE CreateEventWrap(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCWSTR lpName)
{
return CreateEventA(lpEventAttributes, bManualReset, bInitialState, (LPCSTR) lpName);
}
HANDLE CreateFileWrap(
LPCWSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile)
{
CStrIn str(lpFileName);
return CreateFileA(
str,
dwDesiredAccess,
dwShareMode,
lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
hTemplateFile);
}
HANDLE CreateFileMappingWrap(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
DWORD flProtect,
DWORD dwMaxSizeHigh,
DWORD dwMaxSizeLow,
LPCWSTR lpName)
{
CStrIn str(lpName);
return CreateFileMappingA(
hFile,
lpFileMappingAttributes,
flProtect,
dwMaxSizeHigh,
dwMaxSizeLow,
str);
}
HFONT CreateFontWrap(
int nHeight,
int nWidth,
int nEscapement,
int nOrientation,
int fnWeight,
DWORD fdwItalic,
DWORD fdwUnderline,
DWORD fdwStrikeOut,
DWORD fdwCharSet,
DWORD fdwOutputPrecision,
DWORD fdwClipPrecision,
DWORD fdwQuality,
DWORD fdwPitchAndFamily,
LPCWSTR lpszFace)
{
CStrIn str(lpszFace);
return CreateFontA(
nHeight,
nWidth,
nEscapement,
nOrientation,
fnWeight,
fdwItalic,
fdwUnderline,
fdwStrikeOut,
fdwCharSet,
fdwOutputPrecision,
fdwClipPrecision,
fdwQuality,
fdwPitchAndFamily,
str);
}
HFONT CreateFontIndirectWrap(CONST LOGFONTW * plfw)
{
LOGFONTA lfa;
HFONT hFont;
memcpy(&lfa, plfw, FIELD_OFFSET(LOGFONTA, lfFaceName));
MbcsFromUnicode(lfa.lfFaceName, ARRAYSIZE(lfa.lfFaceName), plfw->lfFaceName);
hFont = CreateFontIndirectA(&lfa);
return hFont;
}
HWND CreateWindowExWrap(
DWORD dwExStyle,
LPCWSTR lpClassName,
LPCWSTR lpWindowName,
DWORD dwStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam)
{
CStrIn strClass(lpClassName);
CStrIn strWindow(lpWindowName);
return CreateWindowExA(
dwExStyle,
strClass,
strWindow,
dwStyle,
X,
Y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam);
}
LRESULT DefWindowProcWrap(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProcA(hWnd, msg, wParam, lParam);
}
BOOL DeleteFileWrap(LPCWSTR pwsz)
{
CStrIn str(pwsz);
return DeleteFileA(str);
}
LRESULT DispatchMessageWrap(CONST MSG * lpMsg)
{
return DispatchMessageA(lpMsg);
}
#ifndef FONT_LINK
int DrawTextWrap(
HDC hDC,
LPCWSTR lpString,
int nCount,
LPRECT lpRect,
UINT uFormat)
{
CStrIn str(lpString, nCount);
return DrawTextA(hDC, str, str.strlen(), lpRect, uFormat);
}
// shlwapi also have this.
int DrawTextExPrivWrap(
HDC hDC,
LPWSTR lpString,
int nCount,
LPRECT lpRect,
UINT uFormat,
LPDRAWTEXTPARAMS lpDTParams)
{
CStrIn str(lpString, nCount);
return DrawTextExA(hDC, str, str.strlen(), lpRect, uFormat, lpDTParams);
}
#endif
struct EFFSTAT
{
LPARAM lParam;
FONTENUMPROC lpEnumFontProc;
BOOL fFamilySpecified;
};
int CALLBACK EnumFontFamiliesCallbackWrap(
ENUMLOGFONTA * lpelf,
NEWTEXTMETRIC * lpntm,
DWORD FontType,
LPARAM lParam)
{
ENUMLOGFONTW elf;
// Convert strings from ANSI to Unicode
if (((EFFSTAT *)lParam)->fFamilySpecified && (FontType & TRUETYPE_FONTTYPE) )
{
UnicodeFromMbcs(
elf.elfFullName,
ARRAYSIZE(elf.elfFullName),
(LPCSTR) lpelf->elfFullName);
UnicodeFromMbcs(
elf.elfStyle,
ARRAYSIZE(elf.elfStyle),
(LPCSTR) lpelf->elfStyle);
}
else
{
elf.elfStyle[0] = L'\0';
elf.elfFullName[0] = L'\0';
}
UnicodeFromMbcs(
elf.elfLogFont.lfFaceName,
ARRAYSIZE(elf.elfLogFont.lfFaceName),
(LPCSTR) lpelf->elfLogFont.lfFaceName);
// Copy the non-string data
memcpy(
&elf.elfLogFont,
&lpelf->elfLogFont,
FIELD_OFFSET(LOGFONTA, lfFaceName));
// Chain to the original callback function
return (*((EFFSTAT *) lParam)->lpEnumFontProc)(
(const LOGFONTW *) &elf,
(const TEXTMETRICW *) lpntm,
FontType,
((EFFSTAT *) lParam)->lParam);
}
int EnumFontFamiliesWrap(
HDC hdc,
LPCWSTR lpszFamily,
FONTENUMPROC lpEnumFontProc,
LPARAM lParam)
{
CStrIn str(lpszFamily);
EFFSTAT effstat;
effstat.lParam = lParam;
effstat.lpEnumFontProc = lpEnumFontProc;
effstat.fFamilySpecified = lpszFamily != NULL;
return EnumFontFamiliesA(
hdc,
str,
(FONTENUMPROCA) EnumFontFamiliesCallbackWrap,
(LPARAM) &effstat);
}
int EnumFontFamiliesExWrap(
HDC hdc,
LPLOGFONTW lplfw,
FONTENUMPROC lpEnumFontProc,
LPARAM lParam,
DWORD dwFlags )
{
LOGFONTA lfa;
CStrIn str(lplfw->lfFaceName);
EFFSTAT effstat;
ASSERT( FIELD_OFFSET(LOGFONTW, lfFaceName) == FIELD_OFFSET(LOGFONTA, lfFaceName) );
memcpy( &lfa, lplfw, sizeof(LOGFONTA) - FIELD_OFFSET(LOGFONTA, lfFaceName) );
memcpy( lfa.lfFaceName, str, LF_FACESIZE );
effstat.lParam = lParam;
effstat.lpEnumFontProc = lpEnumFontProc;
effstat.fFamilySpecified = lplfw->lfFaceName != NULL;
return EnumFontFamiliesExA(
hdc,
&lfa,
(FONTENUMPROCA) EnumFontFamiliesCallbackWrap,
(LPARAM) &effstat,
dwFlags );
}
BOOL EnumResourceNamesWrap(
HINSTANCE hModule,
LPCWSTR lpType,
ENUMRESNAMEPROCW lpEnumFunc,
LONG lParam)
{
ASSERT(HIWORD64(lpType) == 0);
return EnumResourceNamesA(hModule, (LPCSTR) lpType, (ENUMRESNAMEPROCA)lpEnumFunc, lParam);
}
#ifndef FONT_LINK
//
// There's an app that patches Win95 GDI and their ExtTextOutW handler
// is broken. It always dereferences the lpStr parameter, even if
// cb is zero. Consequently, any time we are about to pass NULL as
// the lpStr, we have to change our mind and pass a null UNICODE string
// instead.
//
// The name of this app: Lotus SmartSuite ScreenCam 97.
//
BOOL ExtTextOutWrap(HDC hdc, int x, int y, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpStr, UINT cch, CONST INT *lpDx)
{
// Force a thunk to ANSI if running Win95 + ME
if (g_fMEEnabled && !g_bRunOnMemphis)
{
CStrIn str(lpStr, cch);
return ExtTextOutA(hdc, x, y, fuOptions, lprc, str, str.strlen(), lpDx);
}
else
{
if (lpStr == NULL) // workaround
lpStr = TEXT(""); // for ScreenCam 97
return ExtTextOutW(hdc, x, y, fuOptions, lprc, lpStr, cch, lpDx);
}
}
#endif
HANDLE FindFirstFileWrap(
LPCWSTR lpFileName,
LPWIN32_FIND_DATAW pwszFd)
{
CStrIn str(lpFileName);
WIN32_FIND_DATAA fd;
HANDLE ret;
memcpy(&fd, pwszFd, sizeof(FILETIME)*3+sizeof(DWORD)*5);
ret = FindFirstFileA(str, &fd);
memcpy(pwszFd, &fd, sizeof(FILETIME)*3+sizeof(DWORD)*5);
UnicodeFromMbcs(pwszFd->cFileName, ARRAYSIZE(pwszFd->cFileName), fd.cFileName);
UnicodeFromMbcs(pwszFd->cAlternateFileName, ARRAYSIZE(pwszFd->cAlternateFileName), fd.cAlternateFileName);
return ret;
}
//
// Although Win95 implements FindResource[Ex]W, its implementation is buggy
// if you pass a string parameter, so we must thunk to the ANSI side.
//
// The bug is that FindResource[Ex]W will accidentally
// call LocalFree(lpName) and LocalFree(lpType), so if lpName and lpType
// point to heap memory, Kernel32 secretly freed your memory and you fault
// five minutes later.
//
HRSRC FindResourceExWrap(HINSTANCE hModule, LPCWSTR lpType, LPCWSTR lpName, WORD wLang)
{
CStrIn strType(lpType); // rlefile.cpp passes TEXT("AVI")
CStrIn strName(lpName);
return FindResourceExA(hModule, strType, strName, wLang);
}
HWND FindWindowWrap(LPCWSTR lpClassName, LPCWSTR lpWindowName)
{
CStrIn strClass(lpClassName);
CStrIn strWindow(lpWindowName);
return FindWindowA(strClass, strWindow);
}
DWORD FormatMessageWrap(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPWSTR lpBuffer,
DWORD nSize,
va_list * Arguments)
{
//This assert is only valid on Windows 95.
ASSERT(!(dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER));
CStrOut str(lpBuffer, nSize);
FormatMessageA(
dwFlags,
lpSource,
dwMessageId,
dwLanguageId,
str,
str.BufSize(),
Arguments);
return str.ConvertExcludingNul();
}
BOOL GetClassInfoWrap(HINSTANCE hModule, LPCWSTR lpClassName, LPWNDCLASSW lpWndClassW)
{
BOOL ret;
CStrIn strClassName(lpClassName);
ASSERT(sizeof(WNDCLASSA) == sizeof(WNDCLASSW));
ret = GetClassInfoA(hModule, strClassName, (LPWNDCLASSA) lpWndClassW);
lpWndClassW->lpszMenuName = NULL;
lpWndClassW->lpszClassName = NULL;
return ret;
}
DWORD GetClassLongWrap(HWND hWnd, int nIndex)
{
return GetClassLongA(hWnd, nIndex);
}
int GetClassNameWrap(HWND hWnd, LPWSTR lpClassName, int nMaxCount)
{
CStrOut strClassName(lpClassName, nMaxCount);
GetClassNameA(hWnd, strClassName, strClassName.BufSize());
return strClassName.ConvertIncludingNul();
}
int GetClipboardFormatNameWrap(UINT format, LPWSTR lpFormatName, int cchFormatName)
{
CStrOut strFormatName(lpFormatName, cchFormatName);
GetClipboardFormatNameA(format, strFormatName, strFormatName.BufSize());
return strFormatName.ConvertIncludingNul();
}
DWORD GetCurrentDirectoryWrap(DWORD nBufferLength, LPWSTR lpBuffer)
{
CStrOut str(lpBuffer, nBufferLength);
GetCurrentDirectoryA(str.BufSize(), str);
return str.ConvertExcludingNul();
}
int GetDateFormatWrap(
LCID Locale,
DWORD dwFlags,
CONST SYSTEMTIME *lpDate,
LPCWSTR lpFormat,
LPWSTR lpDateStr,
int cchDate)
{
CStrIn strFormat(lpFormat);
CStrOut str(lpDateStr, cchDate);
ASSERT(cchDate != 0 || lpDateStr == NULL);
int iRc = GetDateFormatA(Locale, dwFlags, lpDate, strFormat, str, str.BufSize());
// If app was merely querying, then return size and stop
if (!str)
return iRc;
return str.ConvertIncludingNul();
}
UINT GetDlgItemTextWrap(
HWND hWndDlg,
int idControl,
LPWSTR lpsz,
int cchMax)
{
CStrOut str(lpsz, cchMax);
GetDlgItemTextA(hWndDlg, idControl, str, str.BufSize());
return str.ConvertExcludingNul();
}
DWORD GetFileAttributesWrap(LPCWSTR lpFileName)
{
CStrIn str(lpFileName);
return GetFileAttributesA(str);
}
int GetKeyNameTextWrap(LONG lParam, LPWSTR lpsz, int nSize)
{
CStrOut str(lpsz, nSize);
GetKeyNameTextA(lParam, str, str.BufSize());
return str.ConvertExcludingNul();
}
int GetLocaleInfoWrap(LCID Locale, LCTYPE LCType, LPWSTR lpsz, int cchData)
{
CStrOut str(lpsz, cchData);
GetLocaleInfoA(Locale, LCType, str, str.BufSize());
return str.ConvertIncludingNul();
}
BOOL GetMenuItemInfoWrap(
HMENU hMenu,
UINT uItem,
BOOL fByPosition,
LPMENUITEMINFOW lpmiiW)
{
BOOL fRet;
ASSERT( sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA) &&
FIELD_OFFSET(MENUITEMINFOW, dwTypeData) ==
FIELD_OFFSET(MENUITEMINFOA, dwTypeData) );
if ( (MIIM_TYPE & lpmiiW->fMask) &&
0 == (lpmiiW->fType & (MFT_BITMAP | MFT_SEPARATOR)))
{
MENUITEMINFOA miiA;
CStrOut str(lpmiiW->dwTypeData, lpmiiW->cch);
memcpy( &miiA, lpmiiW, sizeof(MENUITEMINFOA) );
miiA.dwTypeData = str;
miiA.cch = str.BufSize();
fRet = GetMenuItemInfoA( hMenu, uItem, fByPosition, &miiA );
memcpy(lpmiiW, &miiA, FIELD_OFFSET(MENUITEMINFOW, dwTypeData));
}
else
{
fRet = GetMenuItemInfoA( hMenu, uItem, fByPosition,
(LPMENUITEMINFOA)lpmiiW );
}
return fRet;
}
int GetMenuStringWrap(
HMENU hMenu,
UINT uIDItem,
LPWSTR lpString,
int nMaxCount,
UINT uFlag)
{
CStrOut str(lpString, nMaxCount);
GetMenuStringA(hMenu, uIDItem, str, str.BufSize(), uFlag);
return str.ConvertExcludingNul();
}
BOOL GetMessageWrap(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax)
{
return GetMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax);
}
DWORD GetModuleFileNameWrap(HINSTANCE hModule, LPWSTR pwszFilename, DWORD nSize)
{
CStrOut str(pwszFilename, nSize);
GetModuleFileNameA(hModule, str, str.BufSize());
return str.ConvertIncludingNul();
}
int GetNumberFormatWrap(
LCID Locale,
DWORD dwFlags,
LPCWSTR lpValue,
CONST NUMBERFMTW *lpFormat,
LPWSTR lpNumberStr,
int cchNumber)
{
CStrIn strValue(lpValue);
CStrOut str(lpNumberStr, cchNumber);
ASSERT(cchNumber != 0);
NUMBERFMTA nfA;
CopyMemory(&nfA, lpFormat, sizeof(nfA));
CStrIn strDec(lpFormat->lpDecimalSep);
nfA.lpDecimalSep = strDec;
CStrIn strThou(lpFormat->lpThousandSep);
nfA.lpThousandSep = strThou;
GetNumberFormatA(Locale, dwFlags, strValue, &nfA, str, str.BufSize());
return str.ConvertIncludingNul();
}
UINT GetSystemDirectoryWrap(LPWSTR lpBuffer, UINT uSize)
{
CStrOut str(lpBuffer, uSize);
GetSystemDirectoryA(str, str.BufSize());
return str.ConvertExcludingNul();
}
DWORD SearchPathWrap(
LPCWSTR lpPathName,
LPCWSTR lpFileName,
LPCWSTR lpExtension,
DWORD cchReturnBuffer,
LPWSTR lpReturnBuffer,
LPWSTR * plpfilePart)
{
CStrIn strPath(lpPathName);
CStrIn strFile(lpFileName);
CStrIn strExtension(lpExtension);
CStrOut strReturnBuffer(lpReturnBuffer, cchReturnBuffer);
DWORD dwLen = SearchPathA(
strPath,
strFile,
strExtension,
strReturnBuffer.BufSize(),
strReturnBuffer,
(LPSTR *)plpfilePart);
//
// Getting the correct value for plpfilePart requires
// a strrchr on the converted string. If this value
// is needed, just add the code to do it here.
//
*plpfilePart = NULL;
if (cchReturnBuffer == 0)
dwLen = 2*dwLen;
else
dwLen = strReturnBuffer.ConvertExcludingNul();
return dwLen;
}
HMODULE GetModuleHandleWrap(LPCWSTR lpModuleName)
{
CStrIn str(lpModuleName);
return GetModuleHandleA(str);
}
int GetObjectWrap(HGDIOBJ hgdiObj, int cbBuffer, LPVOID lpvObj)
{
int nRet;
if(cbBuffer != sizeof(LOGFONTW))
{
nRet = GetObjectA(hgdiObj, cbBuffer, lpvObj);
}
else
{
LOGFONTA lfa;
nRet = GetObjectA(hgdiObj, sizeof(lfa), &lfa);
if (nRet > 0)
{
memcpy(lpvObj, &lfa, FIELD_OFFSET(LOGFONTW, lfFaceName));
UnicodeFromMbcs(((LOGFONTW*)lpvObj)->lfFaceName, ARRAYSIZE(((LOGFONTW*)lpvObj)->lfFaceName),
lfa.lfFaceName, -1);
nRet = sizeof(LOGFONTW);
}
}
return nRet;
}
//--------------------------------------------------------------
// GetFullPathNameWrap
//--------------------------------------------------------------
DWORD GetFullPathNameWrap( LPCWSTR lpFileName,
DWORD nBufferLength,
LPWSTR lpBuffer,
LPWSTR *lpFilePart)
{
CStrIn strIn(lpFileName);
CStrOut strOut(lpBuffer,nBufferLength);
LPSTR pFile;
DWORD dwRet;
dwRet = GetFullPathNameA(strIn, nBufferLength, strOut, &pFile);
strOut.ConvertIncludingNul();
*lpFilePart = lpBuffer + (pFile - strOut);
return dwRet;
}
BOOL GetStringTypeExWrap(LCID lcid, DWORD dwInfoType, LPCTSTR lpSrcStr, int cchSrc, LPWORD lpCharType)
{
CStrIn str(lpSrcStr, cchSrc);
return GetStringTypeExA(lcid, dwInfoType, str, str.strlen(), lpCharType);
}
UINT GetPrivateProfileIntWrap(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
INT nDefault,
LPCWSTR lpFileName)
{
CStrIn strApp(lpAppName);
CStrIn strKey(lpKeyName);
CStrIn strFile(lpFileName);
return GetPrivateProfileIntA(strApp, strKey, nDefault, strFile);
}
UINT GetProfileIntWrap(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
INT nDefault)
{
CStrIn strApp(lpAppName);
CStrIn strKey(lpKeyName);
return GetProfileIntA(strApp, strKey, nDefault);
}
DWORD GetProfileStringWrap(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpBuffer,
DWORD dwBuffersize)
{
CStrIn strApp(lpAppName);
CStrIn strKey(lpKeyName);
CStrIn strDefault(lpDefault);
CStrOut strBuffer(lpBuffer, dwBuffersize);
GetProfileStringA(strApp, strKey, strDefault, strBuffer, dwBuffersize);
return strBuffer.ConvertIncludingNul();
}
HANDLE GetPropWrap(HWND hWnd, LPCWSTR lpString)
{
CStrIn str(lpString);
return GetPropA(hWnd, str);
}
UINT GetTempFileNameWrap(
LPCWSTR lpPathName,
LPCWSTR lpPrefixString,
UINT uUnique,
LPWSTR lpTempFileName)
{
CStrIn strPath(lpPathName);
CStrIn strPrefix(lpPrefixString);
CStrOut strFileName(lpTempFileName, MAX_PATH);
return GetTempFileNameA(strPath, strPrefix, uUnique, strFileName);
}
DWORD GetTempPathWrap(DWORD nBufferLength, LPWSTR lpBuffer)
{
CStrOut str(lpBuffer, nBufferLength);
GetTempPathA(str.BufSize(), str);
return str.ConvertExcludingNul();
}
#ifndef FONT_LINK
BOOL GetTextExtentPointWrap(
HDC hdc,
LPCWSTR pwsz,
int cb,
LPSIZE pSize)
{
CStrIn str(pwsz,cb);
return GetTextExtentPointA(hdc, str, str.strlen(), pSize);
}
BOOL GetTextExtentPoint32Wrap(
HDC hdc,
LPCWSTR pwsz,
int cb,
LPSIZE pSize)
{
CStrIn str(pwsz,cb);
return GetTextExtentPoint32A(hdc, str, str.strlen(), pSize);
}
#endif
int GetTextFaceWrap(
HDC hdc,
int cch,
LPWSTR lpFaceName)
{
CStrOut str(lpFaceName, cch);
GetTextFaceA(hdc, str.BufSize(), str);
return str.ConvertIncludingNul();
}
BOOL GetTextMetricsWrap(HDC hdc, LPTEXTMETRICW lptm)
{
BOOL ret;
TEXTMETRICA tm;
ret = GetTextMetricsA(hdc, &tm);
if (ret)
{
lptm->tmHeight = tm.tmHeight;
lptm->tmAscent = tm.tmAscent;
lptm->tmDescent = tm.tmDescent;
lptm->tmInternalLeading = tm.tmInternalLeading;
lptm->tmExternalLeading = tm.tmExternalLeading;
lptm->tmAveCharWidth = tm.tmAveCharWidth;
lptm->tmMaxCharWidth = tm.tmMaxCharWidth;
lptm->tmWeight = tm.tmWeight;
lptm->tmOverhang = tm.tmOverhang;
lptm->tmDigitizedAspectX = tm.tmDigitizedAspectX;
lptm->tmDigitizedAspectY = tm.tmDigitizedAspectY;
lptm->tmItalic = tm.tmItalic;
lptm->tmUnderlined = tm.tmUnderlined;
lptm->tmStruckOut = tm.tmStruckOut;
lptm->tmPitchAndFamily = tm.tmPitchAndFamily;
lptm->tmCharSet = tm.tmCharSet;
UnicodeFromMbcs(&lptm->tmFirstChar, 1, (LPSTR) &tm.tmFirstChar, 1);
UnicodeFromMbcs(&lptm->tmLastChar, 1, (LPSTR) &tm.tmLastChar, 1);
UnicodeFromMbcs(&lptm->tmDefaultChar, 1, (LPSTR) &tm.tmDefaultChar, 1);
UnicodeFromMbcs(&lptm->tmBreakChar, 1, (LPSTR) &tm.tmBreakChar, 1);
}
return ret;
}
int GetTimeFormatWrap(
LCID Locale,
DWORD dwFlags,
CONST SYSTEMTIME *lpTime,
LPCWSTR lpFormat,
LPWSTR lpTimeStr,
int cchTime)
{
CStrIn strFormat(lpFormat);
CStrOut str(lpTimeStr, cchTime);
ASSERT(cchTime != 0);
GetTimeFormatA(Locale, dwFlags, lpTime, strFormat, str, str.BufSize());
return str.ConvertIncludingNul();
}
LONG GetWindowLongWrap(HWND hWnd, int nIndex)
{
return GetWindowLongA(hWnd, nIndex);
}
int GetWindowTextWrap(HWND hWnd, LPWSTR lpString, int nMaxCount)
{
CStrOut str(lpString, nMaxCount);
GetWindowTextA(hWnd, str, str.BufSize());
return str.ConvertExcludingNul();
}
int GetWindowTextLengthWrap(HWND hWnd)
{
WCHAR wstr[MAX_PATH];
return GetWindowTextWrap(hWnd, wstr, ARRAYSIZE(wstr));
}
UINT GetWindowsDirectoryWrap(LPWSTR lpWinPath, UINT cch)
{
CStrOut str(lpWinPath, cch);
GetWindowsDirectoryA(str, str.BufSize());
return str.ConvertExcludingNul();
}
ATOM GlobalAddAtomWrap(LPCWSTR lpString)
{
CStrIn str(lpString);
return GlobalAddAtomA(str);
}
BOOL GrayStringWrap(
HDC hDC,
HBRUSH hBrush,
GRAYSTRINGPROC lpOutputFunc,
LPARAM lpData,
int nCount,
int x,
int y,
int nWidth,
int nHeight)
{
CStrIn str((LPWSTR)lpData);
return GrayStringA(hDC, hBrush, lpOutputFunc, (LPARAM)(LPCSTR)str, str.strlen(), x, y, nWidth, nHeight);
}
LONG ImmGetCompositionStringWrap(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
{
int cb = 0;
if ((dwIndex & GCS_COMPSTR) || (dwIndex & GCS_RESULTSTR))
{
if (dwBufLen)
{
CStrOut str((LPWSTR)lpBuf, dwBufLen/sizeof(WCHAR) + 1);
cb = ImmGetCompositionStringA(hIMC, dwIndex, str, str.BufSize());
*(WCHAR*)((LPSTR)str + cb) = L'\0';
return str.ConvertExcludingNul() * sizeof(WCHAR);
}
else
{
LPWSTR lpStr;
cb = ImmGetCompositionStringA(hIMC, dwIndex, lpBuf, dwBufLen);
lpStr = (LPWSTR)LocalAlloc(LPTR, (cb + 1) * sizeof(WCHAR));
if (lpStr)
{
CStrOut str(lpStr, cb + 1);
cb = ImmGetCompositionStringA(hIMC, dwIndex, str, str.BufSize());
*(WCHAR*)((LPSTR)str + cb) = L'\0';
cb = str.ConvertExcludingNul() * sizeof(WCHAR);
LocalFree(lpStr);
return cb;
}
}
}
else if (dwIndex & GCS_COMPATTR)
{
if (dwBufLen)
{
LPSTR lpStr, lpAttr;
UINT i = 0;
lpStr = (LPSTR)LocalAlloc(LPTR, dwBufLen);
if (lpStr)
{
lpAttr = (LPSTR)LocalAlloc(LPTR, dwBufLen);
if (lpAttr)
{
LPSTR lpNext = lpStr;
cb = ImmGetCompositionStringA(hIMC, GCS_COMPSTR, lpStr, dwBufLen);
ImmGetCompositionStringA(hIMC, GCS_COMPATTR, lpAttr, dwBufLen);
for (i = 0; (lpNext - lpStr < cb) && (i < dwBufLen); i++)
{
((LPSTR)lpBuf)[i] = lpAttr[lpNext - lpStr];
lpNext = CharNextA(lpNext);
}
LocalFree(lpAttr);
}
LocalFree(lpStr);
}
return i;
}
}
return ImmGetCompositionStringA(hIMC, dwIndex, lpBuf, dwBufLen);
}
LONG ImmSetCompositionStringWrap(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen, LPVOID lpRead, DWORD dwReadLen)
{
if (dwIndex & SCS_SETSTR)
{
CStrIn str((LPWSTR)lpComp);
ASSERT(!lpRead);
return ImmSetCompositionStringA(hIMC, dwIndex, str, str.strlen(), lpRead, dwReadLen);
}
return ImmSetCompositionStringA(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
}
BOOL InsertMenuWrap(
HMENU hMenu,
UINT uPosition,
UINT uFlags,
UINT uIDNewItem,
LPCWSTR lpNewItem)
{
CStrIn str(lpNewItem);
return InsertMenuA(hMenu, uPosition, uFlags, uIDNewItem, str);
}
BOOL IsDialogMessageWrap(HWND hWndDlg, LPMSG lpMsg)
{
return IsDialogMessageA(hWndDlg, lpMsg);
}
HACCEL LoadAcceleratorsWrap(HINSTANCE hInstance, LPCWSTR lpTableName)
{
CStrIn str(lpTableName);
return LoadAcceleratorsA(hInstance, (LPCSTR) str);
}
HBITMAP LoadBitmapWrap(HINSTANCE hInstance, LPCWSTR lpBitmapName)
{
CStrIn str(lpBitmapName);
return LoadBitmapA(hInstance, str);
}
HCURSOR LoadCursorWrap(HINSTANCE hInstance, LPCWSTR lpCursorName)
{
CStrIn str(lpCursorName);
return LoadCursorA(hInstance, (LPCSTR) str);
}
HICON LoadIconWrap(HINSTANCE hInstance, LPCWSTR lpIconName)
{
CStrIn str(lpIconName);
return LoadIconA(hInstance, str);
}
HANDLE LoadImageWrap(
HINSTANCE hInstance,
LPCWSTR lpName,
UINT uType,
int cxDesired,
int cyDesired,
UINT fuLoad)
{
CStrIn str(lpName);
return LoadImageA(
hInstance,
str,
uType,
cxDesired,
cyDesired,
fuLoad);
}
HINSTANCE LoadLibraryWrap(LPCWSTR lpLibFileName)
{
CStrIn str(lpLibFileName);
return LoadLibraryA(str);
}
HINSTANCE LoadLibraryExWrap(
LPCWSTR lpLibFileName,
HANDLE hFile,
DWORD dwFlags)
{
CStrIn str(lpLibFileName);
return LoadLibraryExA(str, hFile, dwFlags);
}
HMENU LoadMenuWrap(HINSTANCE hInstance, LPCWSTR lpMenuName)
{
ASSERT(HIWORD64(lpMenuName) == 0);
return LoadMenuA(hInstance, (LPCSTR) lpMenuName);
}
int LoadStringWrap(HINSTANCE hInstance, UINT uID, LPWSTR lpBuffer, int nBufferMax)
{
//
// Do it manually. The old code used to call LoadStringA and then
// convert it up to unicode, which is bad since resources are
// physically already Unicode! Just copy it out directly.
//
if (nBufferMax <= 0) return 0; // sanity check
PWCHAR pwch;
/*
* String tables are broken up into "bundles" of 16 strings each.
*/
HRSRC hrsrc;
int cwch = 0;
hrsrc = FindResourceA(hInstance, (LPSTR)(LONG_PTR)(1 + uID / 16), (LPSTR)RT_STRING);
if (hrsrc) {
pwch = (PWCHAR)LoadResource(hInstance, hrsrc);
if (pwch) {
/*
* Now skip over the strings in the resource until we
* hit the one we want. Each entry is a counted string,
* just like Pascal.
*/
for (uID %= 16; uID; uID--) {
pwch += *pwch + 1;
}
cwch = min(*pwch, nBufferMax - 1);
memcpy(lpBuffer, pwch+1, cwch * sizeof(WCHAR)); /* Copy the goo */
}
}
lpBuffer[cwch] = L'\0'; /* Terminate the string */
return cwch;
}
UINT MapVirtualKeyWrap(UINT uCode, UINT uMapType)
{
return MapVirtualKeyA(uCode, uMapType);
}
//----------------------------------------------------------------------
//
// function: TransformCharNoOp1( WCHAR **ppch )
//
// purpose: Stand-in for TransformCharWidth. Used by the function
// CompareStringString.
//
// returns: Character at *ppch. The value *ppch is incremented.
//
//----------------------------------------------------------------------
static WCHAR TransformCharNoOp1( LPCWSTR *ppch, int )
{
WCHAR ch = **ppch;
(*ppch)++;
return ch;
}
//----------------------------------------------------------------------
//
// function: TransformCharWidth( WCHAR **ppch, cchRemaining )
//
// purpose: Converts halfwidth characters to fullwidth characters.
// Also combines voiced (dakuon) and semi-voiced (handakuon)
// characters. *pch is advanced by one, unless there is a
// (semi)voiced character, in which case it is advanced by
// two characters.
//
// Note that unlike the full widechar version, we do not
// combine other characters, notably the combining Hiragana
// characters (U+3099 and U+309A.) This is to keep the
// tables from getting unnecessarily large.
//
// cchRemaining is passed so as to not include the voiced
// marks if it's passed the end of the specified buffer.
//
// returns: Full width character. *pch is incremented.
//
//----------------------------------------------------------------------
static WCHAR TransformCharWidth( LPCWSTR *ppch, int cchRemaining )
{
WCHAR ch = **ppch;
(*ppch)++;
if (ch == 0x0020)
{
ch = 0x3000;
}
else if (ch == 0x005c)
{
// REVERSE SOLIDUS (aka BACKSLASH) maps to itself
}
else if (InRange(ch, 0x0021, 0x07e))
{
ch += 65248;
}
else if (InRange(ch, 0x00a2, 0x00af))
{
static const WCHAR achFull[] =
{
0xffe0, 0xffe1, 0x00a4, 0xffe5, 0xffe4, 0x00a7, 0x00a8, // 0xa2-0xa8
0x00a9, 0x00aa, 0x00ab, 0xffe2, 0x00ad, 0x00ae, 0xffe3 // 0xa9-0xaf
};
ch = achFull[ch - 0x00a2];
}
else if (ch == 0x20a9) // WON SIGN
{
ch = 0xffe6;
}
else if (InRange(ch, 0xff61, 0xffdc))
{
WCHAR chNext = (cchRemaining > 1) ? **ppch : 0;
if (chNext == 0xff9e && InRange(ch, 0xff73, 0xff8e))
{
if (cchRemaining != 1)
{
static const WCHAR achFull[] =
{
/* 0xff73-0xff79 */ 0xb0f4, 0x30a8, 0x30aa, 0xb0ac, 0xb0ae, 0xb0b0, 0xb0b2,
/* 0xff7a-0xff80 */ 0xb0b4, 0xb0b6, 0xb0b8, 0xb0ba, 0xb0bc, 0xb0be, 0xb0c0,
/* 0xff81-0xff87 */ 0xb0c2, 0xb0c5, 0xb0c7, 0xb0c9, 0x30ca, 0x30cb, 0x30cc,
/* 0xff88-0xff8e */ 0x30cd, 0x30ce, 0xb0d0, 0xb0d3, 0xb0d6, 0xb0d9, 0xb0dc
};
// HALFWIDTH KATAKANA VOICED SOUND MARK
WCHAR chTemp = achFull[ch - 0xff73];
// Some in the range absorb the sound mark.
// These are indicated by the set high-bit.
ch = chTemp & 0x7fff;
if (chTemp & 0x8000)
{
(*ppch)++;
}
}
}
else if (chNext == 0xff9f && InRange(ch, 0xff8a, 0xff8e))
{
// HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
ch = 0x30d1 + (ch - 0xff8a) * 3;
(*ppch)++;
}
else
{
static const WCHAR achMapFullFFxx[] =
{
0x3002, 0x300c, 0x300d, 0x3001, 0x30fb, 0x30f2, 0x30a1, // 0xff61-0xff67
0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, // 0xff68-0xff6e
0x30c3, 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, // 0xff6f-0xff75
0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, // 0xff76-0xff7c
0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c4, 0x30c6, // 0xff7d-0xff83
0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, // 0xff84-0xff8a
0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, // 0xff8b-0xff91
0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, 0x30ea, // 0xff92-0xff98
0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c, // 0xff99-0xff9f
0x3164, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, // 0xffa0-0xffa6
0x3137, 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, // 0xffa7-0xffad
0x313e, 0x313f, 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, // 0xffae-0xffb4
0x3145, 0x3146, 0x3147, 0x3148, 0x3149, 0x314a, 0x314b, // 0xffb5-0xffbb
0x314c, 0x314d, 0x314e, 0xffbf, 0xffc0, 0xffc1, 0x314f, // 0xffbc-0xffc2
0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0xffc8, 0xffc9, // 0xffc3-0xffc9
0x3155, 0x3156, 0x3157, 0x3158, 0x3159, 0x315a, 0xffd0, // 0xffca-0xffd0
0xffd1, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, 0x3160, // 0xffd1-0xffd7
0xffd8, 0xffd9, 0x3161, 0x3162, 0x3163 // 0xffd8-0xffac
};
ch = achMapFullFFxx[ch - 0xff61];
}
}
return ch;
}
//----------------------------------------------------------------------
//
// function: TransformaCharNoOp2( WCHAR ch )
//
// purpose: Stand-in for CharLowerBuffWrap. Used by the function
// CompareStringString.
//
// returns: Original character
//
//----------------------------------------------------------------------
static WCHAR TransformCharNoOp2( WCHAR ch )
{
return ch;
}
//----------------------------------------------------------------------
//
// function: TransformaCharKana( WCHAR ch )
//
// purpose: Converts Hiragana characters to Katakana characters
//
// returns: Original character if not Hiragana,
// Katanaka character if Hiragana
//
//----------------------------------------------------------------------
static WCHAR TransformCharKana( WCHAR ch )
{
if (((ch & 0xff00) == 0x3000) &&
(InRange(ch, 0x3041, 0x3094) || InRange(ch, 0x309d, 0x309e)))
{
ch += 0x060;
}
return ch;
}
//----------------------------------------------------------------------
//
// function: TransformCharNoOp3( LPWSTR pch, DWORD cch )
//
// purpose: Stand-in for CharLowerBuffWrap. Used by the function
// CompareStringString.
//
// returns: Character count (cch).
//
//----------------------------------------------------------------------
static DWORD TransformCharNoOp3( LPWSTR, DWORD cch )
{
return cch;
}
//----------------------------------------------------------------------
//
// function: TransformaCharFinal( WCHAR ch )
//
// purpose: Converts "final" forms to regular forms
//
// returns: Original character if not Hiragana,
// Katanaka character if Hiragana
//
//----------------------------------------------------------------------
// BUGBUG (cthrash) We do not fold Presentation Forms (Alphabetic or Arabic)
static WCHAR TransformCharFinal( WCHAR ch )
{
WCHAR chRet = ch;
if (ch >= 0x3c2) // short-circuit ASCII +
{
switch (ch)
{
case 0x03c2: // GREEK SMALL LETTER FINAL SIGMA
case 0x05da: // HEBREW LETTER FINAL KAF
case 0x05dd: // HEBREW LETTER FINAL MEM
case 0x05df: // HEBREW LETTER FINAL NUN
case 0x05e3: // HEBREW LETTER FINAL PE
case 0x05e5: // HEBREW LETTER FINAL TSADI
case 0xfb26: // HEBREW LETTER WIDE FINAL MEM
case 0xfb3a: // HEBREW LETTER FINAL KAF WITH DAGESH
case 0xfb43: // HEBREW LETTER FINAL PE WITH DAGESH
chRet++;
break;
}
}
return ch;
}
//----------------------------------------------------------------------
//
// function: CompareStringString( ... )
//
// purpose: Helper for CompareStringWrap.
//
// We handle the string comparsion for CompareStringWrap.
// We can convert each character to (1) fullwidth,
// (2) Katakana, and (3) lowercase, as necessary.
//
// returns: 1 - string A is less in lexical value as string B
// 2 - string B is equal in lexical value as string B
// 3 - string B is greater in lexical value as string B
//
//----------------------------------------------------------------------
static int CompareStringString(
DWORD dwFlags,
LPCWSTR lpA,
int cchA,
LPCWSTR lpB,
int cchB )
{
int nRet = 0;
WCHAR wchIgnoreNulA = cchA == -1 ? 0 : -1;
WCHAR wchIgnoreNulB = cchB == -1 ? 0 : -1;
WCHAR (*pfnTransformWidth)(LPCWSTR *, int);
WCHAR (*pfnTransformKana)(WCHAR);
DWORD (*pfnTransformLower)(LPWSTR, DWORD);
WCHAR (*pfnTransformFinal)(WCHAR);
pfnTransformWidth = (dwFlags & NORM_IGNOREWIDTH)
? TransformCharWidth : TransformCharNoOp1;
pfnTransformKana = (dwFlags & NORM_IGNOREKANATYPE)
? TransformCharKana : TransformCharNoOp2;
pfnTransformLower = (dwFlags & NORM_IGNORECASE)
? CharLowerBuffWrap : TransformCharNoOp3;
pfnTransformFinal = (dwFlags & NORM_IGNORECASE)
? TransformCharFinal : TransformCharNoOp2;
while ( !nRet
&& cchA
&& cchB
&& (*lpA | wchIgnoreNulA)
&& (*lpB | wchIgnoreNulB) )
{
WCHAR chA, chB;
LPCWSTR lpAOld = lpA;
LPCWSTR lpBOld = lpB;
chA = (*pfnTransformWidth)(&lpA, cchA);
chA = (*pfnTransformKana)(chA);
(*pfnTransformLower)(&chA, 1);
chA = (*pfnTransformFinal)(chA);
chB = (*pfnTransformWidth)(&lpB, cchB);
chB = (*pfnTransformKana)(chB);
(*pfnTransformLower)(&chB, 1);
chB = (*pfnTransformFinal)(chB);
nRet = (int)chA - (int)chB;
cchA -= (int) (lpA-lpAOld);
cchB -= (int) (lpB-lpBOld);
}
if (!nRet)
{
nRet = cchA - cchB;
}
if (nRet)
{
nRet = nRet > 0 ? 1 : -1;
}
return nRet + 2;
}
//----------------------------------------------------------------------
//
// function: CompareStringWord( ... )
//
// purpose: Helper for CompareStringWrap.
//
// We handle the word comparsion for CompareStringWrap.
//
// returns: 1 - string A is less in lexical value as string B
// 2 - string B is equal in lexical value as string B
// 3 - string B is greater in lexical value as string B
//
//----------------------------------------------------------------------
static int CompareStringWord(
LCID lcid,
DWORD dwFlags,
LPCWSTR lpA,
int cchA,
LPCWSTR lpB,
int cchB )
{
// BUGBUG (cthrash) We won't properly support word compare for the
// time being. Do the same old CP_ACP trick, which should cover
// enough cases.
// fail if either string is NULL, as it causes assert on debug windows
if (!lpA || !lpB)
return 0;
CStrIn strA(lpA, cchA);
CStrIn strB(lpB, cchB);
cchA = strA.strlen();
cchB = strB.strlen();
return CompareStringA(lcid, dwFlags, strA, cchA, strB, cchB);
}
//----------------------------------------------------------------------
//
// function: CompareStringWrap( ... )
//
// purpose: Unicode wrapper of CompareString for Win95.
//
// Note not all bits in dwFlags are honored; specifically,
// since we don't do a true widechar word compare, we
// won't properly handle NORM_IGNORENONSPACE or
// NORM_IGNORESYMBOLS for arbitrary widechar strings.
//
// returns: 1 - string A is less in lexical value as string B
// 2 - string B is equal in lexical value as string B
// 3 - string B is greater in lexical value as string B
//
//----------------------------------------------------------------------
LWSTDAPI_(int) CompareStringAltW(
LCID lcid,
DWORD dwFlags,
LPCWSTR lpA,
int cchA,
LPCWSTR lpB,
int cchB )
{
int nRet;
if (dwFlags & SORT_STRINGSORT)
{
nRet = CompareStringString(dwFlags, lpA, cchA, lpB, cchB);
}
else
{
nRet = CompareStringWord(lcid, dwFlags, lpA, cchA, lpB, cchB);
}
return nRet;
}
int CompareStringWrap(
LCID Locale,
DWORD dwCmpFlags,
LPCWSTR lpString1,
int cchCount1,
LPCWSTR lpString2,
int cchCount2)
{
// fail if either string is NULL, as it causes assert on debug windows
if (!lpString1 || !lpString2)
return 0;
CStrIn strString1(lpString1, cchCount1);
CStrIn strString2(lpString2, cchCount2);
cchCount1 = strString1.strlen();
cchCount2 = strString2.strlen();
return CompareStringA(Locale, dwCmpFlags,
strString1,cchCount1,
strString2,cchCount2);
}
BOOL MessageBoxIndirectWrap(MSGBOXPARAMS *pmbp)
{
CStrIn strText(pmbp->lpszText);
CStrIn strCaption(pmbp->lpszCaption);
MSGBOXPARAMSA mbp;
memcpy(&mbp, pmbp, sizeof(mbp));
mbp.lpszText = strText;
mbp.lpszCaption = strCaption;
ASSERT(HIWORD64(mbp.lpszIcon) == 0);
return MessageBoxIndirectA(&mbp);
}
DWORD GetCharacterPlacementWrap(
HDC hdc, // handle to device context
LPCTSTR lpString, // pointer to string
int nCount, // number of characters in string
int nMaxExtent, // maximum extent for displayed string
LPGCP_RESULTS lpResults, // pointer to buffer for placement result
DWORD dwFlags // placement flags
)
{
CStrIn strText(lpString);
DWORD dwRet;
// Leave for someone else.
ASSERT (lpResults->lpOutString == NULL);
ASSERT (lpResults->lpClass == NULL);
dwRet = GetCharacterPlacementA (hdc, strText, nCount, nMaxExtent,
(LPGCP_RESULTSA)lpResults,
dwFlags);
return dwRet;
}
#ifndef FONT_LINK
BOOL GetCharWidthWrap (
HDC hdc,
UINT iFirstChar,
UINT iLastChar,
LPINT lpBuffer)
{
// Note that we expect to do only one character at a time for anything but
// ISO Latin 1.
if (iFirstChar > 255)
{
UINT mbChar=0;
WCHAR ch;
// Convert string
ch = (WCHAR)iFirstChar;
WideCharToMultiByte(CP_ACP, 0, &ch, 1,
(char *)&mbChar, 2, NULL, NULL);
}
return (GetCharWidthA (hdc, iFirstChar, iLastChar, lpBuffer));
}
#endif
BOOL ModifyMenuWrap(
HMENU hMenu,
UINT uPosition,
UINT uFlags,
UINT uIDNewItem,
LPCWSTR lpNewItem)
{
ASSERT(!(uFlags & MF_BITMAP) && !(uFlags & MF_OWNERDRAW));
CStrIn str(lpNewItem);
return ModifyMenuA(hMenu, uPosition, uFlags, uIDNewItem, str);
}
BOOL CopyFileWrap(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, BOOL bFailIfExists)
{
CStrIn strOld(lpExistingFileName);
CStrIn strNew(lpNewFileName);
return CopyFileA(strOld, strNew, bFailIfExists);
}
BOOL MoveFileWrap(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName)
{
CStrIn strOld(lpExistingFileName);
CStrIn strNew(lpNewFileName);
return MoveFileA(strOld, strNew);
}
BOOL OemToCharWrap(LPCSTR lpszSrc, LPWSTR lpszDst)
{
CStrOut strDst(lpszDst, lstrlenA(lpszSrc));
return OemToCharA(lpszSrc, strDst);
}
VOID OutputDebugStringWrap(LPCWSTR lpOutputString)
{
CStrIn str(lpOutputString);
OutputDebugStringA(str);
}
BOOL PeekMessageWrap(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg)
{
return PeekMessageA(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
}
BOOL PostMessageWrap(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
return PostMessageA(hWnd, Msg, wParam, lParam);
}
BOOL PostThreadMessageWrap(
DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
return PostThreadMessageA(idThread, Msg, wParam, lParam);
}
LONG RegCreateKeyWrap(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
{
CStrIn str(lpSubKey);
return RegCreateKeyA(hKey, str, phkResult);
}
LONG RegCreateKeyExWrap(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions, REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
{
CStrIn strSubKey(lpSubKey);
CStrIn strClass(lpClass);
return RegCreateKeyExA(hKey, strSubKey, Reserved, strClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
}
LONG RegDeleteKeyWrap(HKEY hKey, LPCWSTR pwszSubKey)
{
CStrIn str(pwszSubKey);
return RegDeleteKeyA(hKey, str);
}
LONG RegEnumKeyWrap(
HKEY hKey,
DWORD dwIndex,
LPWSTR lpName,
DWORD cbName)
{
CStrOut str(lpName, cbName);
return RegEnumKeyA(hKey, dwIndex, str, str.BufSize());
}
LONG RegEnumKeyExWrap(
HKEY hKey,
DWORD dwIndex,
LPWSTR lpName,
LPDWORD lpcbName,
LPDWORD lpReserved,
LPWSTR lpClass,
LPDWORD lpcbClass,
PFILETIME lpftLastWriteTime)
{
long ret;
DWORD dwClass = 0;
if (!lpcbClass)
{
lpcbClass = &dwClass;
}
CStrOut strName(lpName, *lpcbName);
CStrOut strClass(lpClass, *lpcbClass);
ret = RegEnumKeyExA(
hKey,
dwIndex,
strName,
lpcbName,
lpReserved,
strClass,
lpcbClass,
lpftLastWriteTime);
*lpcbName = strName.ConvertExcludingNul();
*lpcbClass = strClass.ConvertExcludingNul();
return ret;
}
LONG RegOpenKeyWrap(HKEY hKey, LPCWSTR pwszSubKey, PHKEY phkResult)
{
CStrIn str(pwszSubKey);
return RegOpenKeyA(hKey, str, phkResult);
}
LONG RegOpenKeyExWrap(
HKEY hKey,
LPCWSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult)
{
CStrIn str(lpSubKey);
return RegOpenKeyExA(hKey, str, ulOptions, samDesired, phkResult);
}
LONG RegQueryInfoKeyWrap(
HKEY hKey,
LPWSTR lpClass,
LPDWORD lpcbClass,
LPDWORD lpReserved,
LPDWORD lpcSubKeys,
LPDWORD lpcbMaxSubKeyLen,
LPDWORD lpcbMaxClassLen,
LPDWORD lpcValues,
LPDWORD lpcbMaxValueNameLen,
LPDWORD lpcbMaxValueLen,
LPDWORD lpcbSecurityDescriptor,
PFILETIME lpftLastWriteTime)
{
CStrIn str(lpClass);
return RegQueryInfoKeyA(
hKey,
str,
lpcbClass,
lpReserved,
lpcSubKeys,
lpcbMaxSubKeyLen,
lpcbMaxClassLen,
lpcValues,
lpcbMaxValueNameLen,
lpcbMaxValueLen,
lpcbSecurityDescriptor,
lpftLastWriteTime);
}
LONG RegQueryValueWrap(
HKEY hKey,
LPCWSTR pwszSubKey,
LPWSTR pwszValue,
PLONG lpcbValue)
{
long ret;
long cb;
CStrIn strKey(pwszSubKey);
CStrOut strValue(pwszValue, (*lpcbValue) / sizeof(WCHAR));
cb = strValue.BufSize();
ret = RegQueryValueA(hKey, strKey, strValue, &cb);
if (ret != ERROR_SUCCESS)
goto Cleanup;
if (strValue)
{
cb = strValue.ConvertIncludingNul();
}
*lpcbValue = cb * sizeof(WCHAR);
Cleanup:
return ret;
}
LONG RegQueryValueExWrap(
HKEY hKey,
LPCWSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData)
{
LONG ret;
CStrIn strValueName(lpValueName);
DWORD dwTempType;
DWORD cb;
//
// Determine the type of buffer needed
//
ret = RegQueryValueExA(hKey, strValueName, lpReserved, &dwTempType, NULL, &cb);
if (ret != ERROR_SUCCESS)
goto Cleanup;
ASSERT(dwTempType != REG_MULTI_SZ);
switch (dwTempType)
{
case REG_EXPAND_SZ:
case REG_SZ:
{
CStrOut strData((LPWSTR) lpData, (*lpcbData) / sizeof(WCHAR));
cb = strData.BufSize();
ret = RegQueryValueExA(hKey, strValueName, lpReserved, lpType, (LPBYTE)(LPSTR)strData, &cb);
if (ret != ERROR_SUCCESS)
break;
if (strData)
{
cb = strData.ConvertIncludingNul();
}
*lpcbData = cb * sizeof(WCHAR);
break;
}
default:
{
ret = RegQueryValueExA(
hKey,
strValueName,
lpReserved,
lpType,
lpData,
lpcbData);
break;
}
}
Cleanup:
return ret;
}
LONG RegSetValueWrap(
HKEY hKey,
LPCWSTR lpSubKey,
DWORD dwType,
LPCWSTR lpData,
DWORD cbData)
{
CStrIn strKey(lpSubKey);
CStrIn strValue(lpData);
return RegSetValueA(hKey, strKey, dwType, strValue, cbData);
}
LONG RegSetValueExWrap(
HKEY hKey,
LPCWSTR lpValueName,
DWORD Reserved,
DWORD dwType,
CONST BYTE* lpData,
DWORD cbData)
{
ASSERT(dwType != REG_MULTI_SZ);
CStrIn strKey(lpValueName);
CStrIn strSZ((dwType == REG_SZ || dwType == REG_EXPAND_SZ) ? (LPCWSTR) lpData : NULL);
if (strSZ)
{
lpData = (LPBYTE) (LPSTR) strSZ;
cbData = strSZ.strlen() + 1;
}
return RegSetValueExA(
hKey,
strKey,
Reserved,
dwType,
lpData,
cbData);
}
ATOM RegisterClassWrap(CONST WNDCLASSW * lpWndClass)
{
WNDCLASSA wc;
CStrIn strMenuName(lpWndClass->lpszMenuName);
CStrIn strClassName(lpWndClass->lpszClassName);
ASSERT(sizeof(wc) == sizeof(*lpWndClass));
memcpy(&wc, lpWndClass, sizeof(wc));
wc.lpszMenuName = strMenuName;
wc.lpszClassName = strClassName;
return RegisterClassA(&wc);
}
UINT RegisterClipboardFormatWrap(LPCWSTR lpString)
{
CStrIn str(lpString);
return RegisterClipboardFormatA(str);
}
UINT RegisterWindowMessageWrap(LPCWSTR lpString)
{
CStrIn str(lpString);
return RegisterWindowMessageA(str);
}
HANDLE RemovePropWrap(
HWND hWnd,
LPCWSTR lpString)
{
CStrIn str(lpString);
return RemovePropA(hWnd, str);
}
// NOTE (SumitC) Instead of calling SendDlgItemMessageA below, I'm forwarding to
// SendMessageWrap so as not to have to re-do the special-case processing.
LRESULT SendDlgItemMessageWrap(
HWND hDlg,
int nIDDlgItem,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
HWND hWnd;
hWnd = GetDlgItem(hDlg, nIDDlgItem);
return SendMessageWrap(hWnd, Msg, wParam, lParam);
}
// AdjustECPosition
//
// Convert mulitbyte position to unicode number of character position in EDIT control
//
// iType: ADJUST_TO_WCHAR_POS or ADJUST_TO_CHAR_POS
//
#define ADJUST_TO_WCHAR_POS 0
#define ADJUST_TO_CHAR_POS 1
int AdjustECPosition(char *psz, int iPos, int iType)
{
char *pstr = psz;
int iNewPos = iPos;
if (ADJUST_TO_WCHAR_POS == iType)
{
iNewPos = 0;
while (*pstr && (pstr - psz != iPos))
{
pstr = CharNextA(pstr);
iNewPos++;
}
}
else if (ADJUST_TO_CHAR_POS == iType)
{
while (*pstr && iPos--)
pstr = CharNextA(pstr);
iNewPos = (int) (pstr-psz);
}
return iNewPos;
}
//
// Edit controls can get really huge, so the MAX_PATH buffer in
// SendMessageWrap just doesn't cut it when push comes to shove.
//
// Try to use the small buffer, and switch to an allocated buffer
// only if the small buffer doesn't work.
//
// Use the handy CConvertStr class as our basis.
//
class CStrA : public CConvertStr
{
public:
CStrA(int cch);
inline int bufsize() { return _cchLen; }
protected:
int _cchLen;
};
CStrA::CStrA(int cch) : CConvertStr(CP_ACP)
{
_cchLen = cch;
if (cch <= ARRAYSIZE(_ach))
{
// It fits in our small buffer
_pstr = _ach;
}
else
{
// Need to allocate a big buffer
_pstr = new char[cch];
if (!_pstr)
{
// On failure, use the small buffer after all.
_pstr = _ach;
_cchLen = ARRAYSIZE(_ach);
}
}
}
LRESULT SendEditMessageWrap(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
WORD wStart, wEnd;
DWORD dwPos;
//
// EM_SETSEL is special - We can often handle it without having to
// get the client text, which is good since some clients
// return bad data.
//
// If the start and end positions are both either 0 or -1, then we
// don't need to do adjustment since 0 is always 0 and -1 is always -1.
//
if (Msg == EM_SETSEL) {
if ((wParam == 0 || (DWORD)wParam == 0xFFFFFFFF) &&
(lParam == 0 || (DWORD)lParam == 0xFFFFFFFF))
return SendMessageA(hWnd, Msg, wParam, lParam);
}
// Get the current window text, since we will be studying it
CStrA sz(GetWindowTextLengthA(hWnd) + 1);
GetWindowTextA(hWnd, sz, sz.bufsize());
switch (Msg)
{
case EM_GETSEL:
{
DWORD_PTR dwPos;
dwPos = SendMessageA(hWnd, Msg, wParam, lParam);
wStart = (WORD)AdjustECPosition(sz, GET_X_LPARAM(dwPos), ADJUST_TO_WCHAR_POS);
wEnd = (WORD)AdjustECPosition(sz, GET_Y_LPARAM(dwPos), ADJUST_TO_WCHAR_POS);
return MAKELONG(wStart, wEnd);
}
case EM_SETSEL:
wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS);
wEnd = (WORD)AdjustECPosition(sz, lParam, ADJUST_TO_CHAR_POS);
return SendMessageA(hWnd, Msg, wStart, wEnd);
case EM_LINEINDEX:
dwPos = SendMessageA(hWnd, Msg, wParam, lParam);
return AdjustECPosition(sz, dwPos, ADJUST_TO_WCHAR_POS);
case EM_LINELENGTH:
wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS);
dwPos = SendMessageA(hWnd, Msg, wStart, lParam);
return AdjustECPosition(sz + wStart, dwPos, ADJUST_TO_WCHAR_POS);
case EM_LINEFROMCHAR:
case EM_POSFROMCHAR:
wStart = (WORD)AdjustECPosition(sz, wParam, ADJUST_TO_CHAR_POS);
return SendMessageA(hWnd, Msg, wStart, lParam);
default:
AssertMsg(FALSE, TEXT("error: unknown message leaked into SendEditMessageWrap"));
return SendMessageA(hWnd, Msg, wParam, lParam);
}
}
#ifndef UNIX
#define SHLWAPI_SENDMESSAGEWRAPW_ORD 136
#else
#define SHLWAPI_SENDMESSAGEWRAPW_ORD "SendMessageWrapW"
#endif
typedef LRESULT (* PFNSENDMESSAGEWRAPW)(HWND, UINT, WPARAM, LPARAM);
LRESULT SendMessageWrap(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
// For XCP PlugUI:
// 1)If shlwapi is in memory, ask it to do the work, otherwise let it
// fall through to original comctl32 wrap implementation.
// 2)This implementation only apply to LB for fixing #67837
switch (Msg)
{
case LB_ADDSTRING:
case LB_FINDSTRING:
case LB_FINDSTRINGEXACT:
case LB_INSERTSTRING:
case LB_GETTEXT:
case LB_GETTEXTLEN:
case LB_SELECTSTRING:
{
extern HMODULE GetShlwapiHModule();
PFNSENDMESSAGEWRAPW pfnSndMsgWrapW = NULL;
HMODULE hShlwapi;
hShlwapi = GetShlwapiHModule();
if (hShlwapi)
pfnSndMsgWrapW = (PFNSENDMESSAGEWRAPW)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPI_SENDMESSAGEWRAPW_ORD);
if (pfnSndMsgWrapW)
return pfnSndMsgWrapW(hWnd, Msg, wParam, lParam);
else
break; // fall through the regular comctl32's wrap
}
}
// original comctl32's wrap implementation
CHAR sz[MAX_PATH]; // BUGBUG: It's big enough current comctl32 usage until now ...
switch (Msg)
{
case WM_GETTEXT:
{
CStrOut str((LPWSTR)lParam, (int) wParam);
SendMessageA(hWnd, Msg, (WPARAM) str.BufSize(), (LPARAM) (LPSTR) str);
return str.ConvertExcludingNul();
}
// The sz[] buffer is not large enough for these guys, so use a
// separate helper function.
case EM_GETSEL:
case EM_SETSEL:
case EM_LINEINDEX:
case EM_LINELENGTH:
case EM_LINEFROMCHAR:
case EM_POSFROMCHAR:
return SendEditMessageWrap(hWnd, Msg, wParam, lParam);
// BUGBUG raymondc - This is wrong. EM_GETLIMITTEXT returns the number
// of characters, not bytes. But the only place we use it is in our
// IME composition code, and maybe they really meant to divide by two...
case EM_GETLIMITTEXT:
return SendMessageA(hWnd, Msg, wParam, lParam) / sizeof(WCHAR);
case EM_GETLINE:
{
LRESULT nLen;
CStrOut str((LPWSTR) lParam, (* (SHORT *) lParam) + 1);
* (SHORT *) (LPSTR) str = * (SHORT *) lParam;
nLen = SendMessageA(hWnd, Msg, (WPARAM) wParam, (LPARAM) (LPSTR) str);
if(nLen > 0)
((LPSTR) str)[nLen] = '\0';
return nLen;
}
// BUGBUG: Always assume lParam points structure, not string buffer
case CB_INSERTSTRING:
{
return SendMessageA(hWnd, Msg, wParam, (LPARAM) lParam);
}
case WM_SETTEXT:
case LB_ADDSTRING:
case CB_ADDSTRING:
case EM_REPLACESEL:
ASSERT(wParam == 0 && "wParam should be 0 for these messages");
// fall through
case CB_SELECTSTRING:
case CB_FINDSTRINGEXACT:
case CB_FINDSTRING:
case LB_INSERTSTRING:
case LB_FINDSTRINGEXACT:
{
CStrIn str((LPWSTR) lParam);
return SendMessageA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str);
}
case LB_GETTEXTLEN:
case CB_GETLBTEXTLEN:
ASSERT((LB_GETTEXTLEN - LB_GETTEXT) == (CB_GETLBTEXTLEN - CB_GETLBTEXT));
lParam = (LPARAM)sz; // use temp buffer
Msg -= (LB_GETTEXTLEN - LB_GETTEXT);
// fall through ...
case LB_GETTEXT:
case CB_GETLBTEXT:
{
CStrOut str((LPWSTR)lParam, 255);
SendMessageA(hWnd, Msg, wParam, (LPARAM) (LPSTR) str);
return str.ConvertExcludingNul();
}
case EM_SETPASSWORDCHAR:
{
WPARAM wp;
ASSERT(HIWORD64(wParam) == 0);
MbcsFromUnicode((LPSTR) &wp, sizeof(wp), (LPWSTR) &wParam);
ASSERT(HIWORD64(wp) == 0);
return SendMessageA(hWnd, Msg, wp, lParam);
}
default:
return SendMessageA(hWnd, Msg, wParam, lParam);
}
}
BOOL SendNotifyMessageWrap(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
// BUGBUG: Should we use SendMessageWarp like SendDlgItemMessageWrap above?
return SendNotifyMessageA(hWnd, Msg, wParam, lParam);
}
BOOL SetCurrentDirectoryWrap(LPCWSTR lpszCurDir)
{
CStrIn str(lpszCurDir);
return SetCurrentDirectoryA(str);
}
BOOL SetDlgItemTextWrap(HWND hDlg, int nIDDlgItem, LPCWSTR lpString)
{
CStrIn str(lpString);
return SetDlgItemTextA(hDlg, nIDDlgItem, str);
}
BOOL SetMenuItemInfoWrap(
HMENU hMenu,
UINT uItem,
BOOL fByPosition,
LPCMENUITEMINFOW lpmiiW)
{
BOOL fRet;
ASSERT( sizeof(MENUITEMINFOW) == sizeof(MENUITEMINFOA) &&
FIELD_OFFSET(MENUITEMINFOW, dwTypeData) ==
FIELD_OFFSET(MENUITEMINFOA, dwTypeData) );
if ( (MIIM_TYPE & lpmiiW->fMask) &&
0 == (lpmiiW->fType & (MFT_BITMAP | MFT_SEPARATOR)))
{
MENUITEMINFOA miiA;
CStrIn str(lpmiiW->dwTypeData, lpmiiW->cch);
memcpy( &miiA, lpmiiW, sizeof(MENUITEMINFOA) );
miiA.dwTypeData = str;
miiA.cch = str.strlen();
fRet = SetMenuItemInfoA( hMenu, uItem, fByPosition, &miiA );
}
else
{
fRet = SetMenuItemInfoA( hMenu, uItem, fByPosition,
(LPCMENUITEMINFOA)lpmiiW );
}
return fRet;
}
BOOL SetPropWrap(
HWND hWnd,
LPCWSTR lpString,
HANDLE hData)
{
CStrIn str(lpString);
return SetPropA(hWnd, str, hData);
}
LONG SetWindowLongWrap(HWND hWnd, int nIndex, LONG dwNewLong)
{
return SetWindowLongA(hWnd, nIndex, dwNewLong);
}
HHOOK SetWindowsHookExWrap(
int idHook,
HOOKPROC lpfn,
HINSTANCE hmod,
DWORD dwThreadId)
{
return SetWindowsHookExA(idHook, lpfn, hmod, dwThreadId);
}
BOOL SetWindowTextWrap(HWND hWnd, LPCWSTR lpString)
{
CStrIn str(lpString);
return SetWindowTextA(hWnd, str);
}
BOOL SystemParametersInfoWrap(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni)
{
BOOL ret;
char ach[LF_FACESIZE];
if (uiAction == SPI_SETDESKWALLPAPER)
{
CStrIn str((LPCWSTR) pvParam);
ret = SystemParametersInfoA(
uiAction,
uiParam,
str,
fWinIni);
}
else if (uiAction == SPI_GETNONCLIENTMETRICS)
{
NONCLIENTMETRICSA ncmA;
NONCLIENTMETRICS *pncm = (NONCLIENTMETRICS *)pvParam;
ASSERT(uiParam == sizeof(NONCLIENTMETRICS) && pncm->cbSize == sizeof(NONCLIENTMETRICS));
ncmA.cbSize = sizeof(ncmA);
ret = SystemParametersInfoA(
uiAction,
sizeof(ncmA),
&ncmA,
fWinIni);
pncm->iBorderWidth = ncmA.iBorderWidth;
pncm->iScrollWidth = ncmA.iScrollWidth;
pncm->iScrollHeight = ncmA.iScrollHeight;
pncm->iCaptionWidth = ncmA.iCaptionWidth;
pncm->iCaptionHeight = ncmA.iCaptionHeight;
pncm->iSmCaptionWidth = ncmA.iSmCaptionWidth;
pncm->iSmCaptionHeight = ncmA.iSmCaptionHeight;
pncm->iMenuWidth = ncmA.iMenuWidth;
pncm->iMenuHeight = ncmA.iMenuHeight;
memcpy(&pncm->lfCaptionFont, &ncmA.lfCaptionFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
UnicodeFromMbcs(pncm->lfCaptionFont.lfFaceName, ARRAYSIZE(pncm->lfCaptionFont.lfFaceName), ncmA.lfCaptionFont.lfFaceName);
memcpy(&pncm->lfSmCaptionFont, &ncmA.lfSmCaptionFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
UnicodeFromMbcs(pncm->lfSmCaptionFont.lfFaceName, ARRAYSIZE(pncm->lfSmCaptionFont.lfFaceName), ncmA.lfSmCaptionFont.lfFaceName);
memcpy(&pncm->lfMenuFont, &ncmA.lfMenuFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
UnicodeFromMbcs(pncm->lfMenuFont.lfFaceName, ARRAYSIZE(pncm->lfMenuFont.lfFaceName), ncmA.lfMenuFont.lfFaceName);
memcpy(&pncm->lfStatusFont, &ncmA.lfStatusFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
UnicodeFromMbcs(pncm->lfStatusFont.lfFaceName, ARRAYSIZE(pncm->lfStatusFont.lfFaceName), ncmA.lfStatusFont.lfFaceName);
memcpy(&pncm->lfMessageFont, &ncmA.lfMessageFont, FIELD_OFFSET(LOGFONTW, lfFaceName));
UnicodeFromMbcs(pncm->lfMessageFont.lfFaceName, ARRAYSIZE(pncm->lfMessageFont.lfFaceName), ncmA.lfMessageFont.lfFaceName);
}
else
ret = SystemParametersInfoA(
uiAction,
uiParam,
pvParam,
fWinIni);
if ((uiAction == SPI_GETICONTITLELOGFONT) && ret)
{
strcpy(ach, ((LPLOGFONTA)pvParam)->lfFaceName);
UnicodeFromMbcs(
((LPLOGFONTW)pvParam)->lfFaceName,
ARRAYSIZE(((LPLOGFONTW)pvParam)->lfFaceName),
ach);
}
return ret;
}
#ifndef FONT_LINK
BOOL TextOutWrap(HDC hdc, int x, int y, LPCWSTR lpStr, int cb)
{
if (g_fMEEnabled && !g_bRunOnMemphis)
{
CStrIn str(lpStr);
return TextOutA(hdc, x, y, str, str.strlen());
}
else
return TextOutW(hdc, x, y, lpStr, cb);
}
#endif
int TranslateAcceleratorWrap(HWND hWnd, HACCEL hAccTable, LPMSG lpMsg)
{
return TranslateAcceleratorA(hWnd, hAccTable, lpMsg);
}
BOOL UnregisterClassWrap(LPCWSTR lpClassName, HINSTANCE hInstance)
{
CStrIn str(lpClassName);
return UnregisterClassA(str, hInstance);
}
SHORT VkKeyScanWrap(WCHAR ch)
{
CStrIn str(&ch, 1);
return VkKeyScanA(*(char *)str);
}
BOOL WinHelpWrap(HWND hwnd, LPCWSTR szFile, UINT uCmd, DWORD dwData)
{
CStrIn str(szFile);
return WinHelpA(hwnd, str, uCmd, dwData);
}
#define DBCS_CHARSIZE (2)
// N versions of wsprintf and wvsprintf which take an output buffer size to prevent overflow
// bugs. Taken from the NT wsprintf source code.
// _MBToWCS and _WCSToMB are actually macros which call ntrtl functions in the NT version.
int _MBToWCS(LPCSTR pszIn, int cchIn, LPWSTR *ppwszOut)
{
int cch = 0;
int cbAlloc;
if ((0 != cchIn) && (NULL != ppwszOut))
{
cchIn++;
cbAlloc = cchIn * sizeof(WCHAR);
*ppwszOut = (LPWSTR)LocalAlloc(LMEM_FIXED, cbAlloc);
if (NULL != *ppwszOut)
{
cch = MultiByteToWideChar(CP_ACP, 0, pszIn, cchIn, *ppwszOut, cchIn);
if (!cch)
{
LocalFree(*ppwszOut);
*ppwszOut = NULL;
}
else
{
cch--; // Just return the number of characters
}
}
}
return cch;
}
/****************************** Module Header ******************************\
* Module Name: wsprintf.c
*
* Copyright (c) 1985-91, Microsoft Corporation
* sprintf.c
*
* Implements Windows friendly versions of sprintf and vsprintf
*
* History:
* 2-15-89 craigc Initial
* 11-12-90 MikeHar Ported from windows 3
\***************************************************************************/
/* Max number of characters. Doesn't include termination character */
#define out(c) if (cchLimit) {*lpOut++=(c); cchLimit--;} else goto errorout
/***************************************************************************\
* SP_GetFmtValueW
*
* reads a width or precision value from the format string
*
* History:
* 11-12-90 MikeHar Ported from windows 3
* 07-27-92 GregoryW Created Unicode version (copied from SP_GetFmtValue)
\***************************************************************************/
LPCWSTR SP_GetFmtValueW(
LPCWSTR lpch,
int *lpw)
{
int ii = 0;
/* It might not work for some locales or digit sets */
while (*lpch >= L'0' && *lpch <= L'9') {
ii *= 10;
ii += (int)(*lpch - L'0');
lpch++;
}
*lpw = ii;
/*
* return the address of the first non-digit character
*/
return lpch;
}
/***************************************************************************\
* SP_PutNumberW
*
* Takes an unsigned long integer and places it into a buffer, respecting
* a buffer limit, a radix, and a case select (upper or lower, for hex).
*
*
* History:
* 11-12-90 MikeHar Ported from windows 3 asm --> C
* 12-11-90 GregoryW need to increment lpstr after assignment of mod
* 02-11-92 GregoryW temporary version until we have C runtime support
\***************************************************************************/
int SP_PutNumberW(
LPWSTR lpstr,
DWORD n,
int limit,
DWORD radix,
int uppercase)
{
DWORD mod;
int count = 0;
/* It might not work for some locales or digit sets */
if(uppercase)
uppercase = 'A'-'0'-10;
else
uppercase = 'a'-'0'-10;
if (count < limit) {
do {
mod = n % radix;
n /= radix;
mod += '0';
if (mod > '9')
mod += uppercase;
*lpstr++ = (WCHAR)mod;
count++;
} while((count < limit) && n);
}
return count;
}
/***************************************************************************\
* SP_ReverseW
*
* reverses a string in place
*
* History:
* 11-12-90 MikeHar Ported from windows 3 asm --> C
* 12-11-90 GregoryW fixed boundary conditions; removed count
* 02-11-92 GregoryW temporary version until we have C runtime support
\***************************************************************************/
void SP_ReverseW(
LPWSTR lpFirst,
LPWSTR lpLast)
{
WCHAR ch;
while(lpLast > lpFirst){
ch = *lpFirst;
*lpFirst++ = *lpLast;
*lpLast-- = ch;
}
}
/***************************************************************************\
* wvsprintfW (API)
*
* wsprintfW() calls this function.
*
* History:
* 11-Feb-1992 GregoryW copied xwvsprintf
* Temporary hack until we have C runtime support
* 1-22-97 tnoonan Converted to wvnsprintfW
\***************************************************************************/
int wvnsprintfW(
LPWSTR lpOut,
int cchLimitIn,
LPCWSTR lpFmt,
va_list arglist)
{
BOOL fAllocateMem = FALSE;
WCHAR prefix, fillch;
int left, width, prec, size, sign, radix, upper, hprefix;
int cchLimit = --cchLimitIn, cch;
LPWSTR lpT, lpTWC;
LPCSTR psz;
va_list varglist = arglist;
union {
long l;
unsigned long ul;
char sz[2];
WCHAR wsz[2];
} val;
if (cchLimit < 0)
return 0;
while (*lpFmt != 0) {
if (*lpFmt == L'%') {
/*
* read the flags. These can be in any order
*/
left = 0;
prefix = 0;
while (*++lpFmt) {
if (*lpFmt == L'-')
left++;
else if (*lpFmt == L'#')
prefix++;
else
break;
}
/*
* find fill character
*/
if (*lpFmt == L'0') {
fillch = L'0';
lpFmt++;
} else
fillch = L' ';
/*
* read the width specification
*/
lpFmt = SP_GetFmtValueW(lpFmt, &cch);
width = cch;
/*
* read the precision
*/
if (*lpFmt == L'.') {
lpFmt = SP_GetFmtValueW(++lpFmt, &cch);
prec = cch;
} else
prec = -1;
/*
* get the operand size
* default size: size == 0
* long number: size == 1
* wide chars: size == 2
* It may be a good idea to check the value of size when it
* is tested for non-zero below (IanJa)
*/
hprefix = 0;
if ((*lpFmt == L'w') || (*lpFmt == L't')) {
size = 2;
lpFmt++;
} else if (*lpFmt == L'l') {
size = 1;
lpFmt++;
} else {
size = 0;
if (*lpFmt == L'h') {
lpFmt++;
hprefix = 1;
}
}
upper = 0;
sign = 0;
radix = 10;
switch (*lpFmt) {
case 0:
goto errorout;
case L'i':
case L'd':
size=1;
sign++;
/*** FALL THROUGH to case 'u' ***/
case L'u':
/* turn off prefix if decimal */
prefix = 0;
donumeric:
/* special cases to act like MSC v5.10 */
if (left || prec >= 0)
fillch = L' ';
/*
* if size == 1, "%lu" was specified (good)
* if size == 2, "%wu" was specified (bad)
*/
if (size) {
val.l = va_arg(varglist, LONG);
} else if (sign) {
val.l = va_arg(varglist, SHORT);
} else {
val.ul = va_arg(varglist, unsigned);
}
if (sign && val.l < 0L)
val.l = -val.l;
else
sign = 0;
lpT = lpOut;
/*
* blast the number backwards into the user buffer
*/
cch = SP_PutNumberW(lpOut, val.l, cchLimit, radix, upper);
if (!(cchLimit -= cch))
goto errorout;
lpOut += cch;
width -= cch;
prec -= cch;
if (prec > 0)
width -= prec;
/*
* fill to the field precision
*/
while (prec-- > 0)
out(L'0');
if (width > 0 && !left) {
/*
* if we're filling with spaces, put sign first
*/
if (fillch != L'0') {
if (sign) {
sign = 0;
out(L'-');
width--;
}
if (prefix) {
out(prefix);
out(L'0');
prefix = 0;
}
}
if (sign)
width--;
/*
* fill to the field width
*/
while (width-- > 0)
out(fillch);
/*
* still have a sign?
*/
if (sign)
out(L'-');
if (prefix) {
out(prefix);
out(L'0');
}
/*
* now reverse the string in place
*/
SP_ReverseW(lpT, lpOut - 1);
} else {
/*
* add the sign character
*/
if (sign) {
out(L'-');
width--;
}
if (prefix) {
out(prefix);
out(L'0');
}
/*
* reverse the string in place
*/
SP_ReverseW(lpT, lpOut - 1);
/*
* pad to the right of the string in case left aligned
*/
while (width-- > 0)
out(fillch);
}
break;
case L'X':
upper++;
/*** FALL THROUGH to case 'x' ***/
case L'x':
radix = 16;
if (prefix)
if (upper)
prefix = L'X';
else
prefix = L'x';
goto donumeric;
case L'c':
case L'C':
if (!size && !hprefix) {
size = 1; // force WCHAR
}
/*** FALL THROUGH to case 'C' ***/
/*
* if size == 0, "%C" or "%hc" was specified (CHAR)
* if size == 1, "%c" or "%lc" was specified (WCHAR)
* if size == 2, "%wc" or "%tc" was specified (WCHAR)
*/
cch = 1; /* One character must be copied to the output buffer */
if (size) {
val.wsz[0] = va_arg(varglist, WCHAR);
val.wsz[1] = 0;
lpT = val.wsz;
goto putwstring;
} else {
val.sz[0] = va_arg(varglist, CHAR);
val.sz[1] = 0;
psz = val.sz;
goto putstring;
}
case L's':
case L'S':
if (!size && !hprefix) {
size = 1; // force LPWSTR
}
/*** FALL THROUGH to case 'S' ***/
/*
* if size == 0, "%S" or "%hs" was specified (LPSTR)
* if size == 1, "%s" or "%ls" was specified (LPWSTR)
* if size == 2, "%ws" or "%ts" was specified (LPWSTR)
*/
if (size) {
lpT = va_arg(varglist, LPWSTR);
cch = lstrlenW(lpT); // Win95 supports lstrlenW!
} else {
psz = va_arg(varglist, LPSTR);
cch = lstrlenA(psz);
putstring:
cch = _MBToWCS(psz, cch, &lpTWC);
fAllocateMem = (BOOL) cch;
lpT = lpTWC;
}
putwstring:
if (prec >= 0 && cch > prec)
cch = prec;
width -= cch;
if (left) {
while (cch--)
out(*lpT++);
while (width-- > 0)
out(fillch);
} else {
while (width-- > 0)
out(fillch);
while (cch--)
out(*lpT++);
}
if (fAllocateMem) {
LocalFree(lpTWC);
fAllocateMem = FALSE;
}
break;
default:
normalch:
out((WCHAR)*lpFmt);
break;
} /* END OF SWITCH(*lpFmt) */
} /* END OF IF(%) */ else
goto normalch; /* character not a '%', just do it */
/*
* advance to next format string character
*/
lpFmt++;
} /* END OF OUTER WHILE LOOP */
errorout:
*lpOut = 0;
if (fAllocateMem)
{
LocalFree(lpTWC);
}
return cchLimitIn - cchLimit;
}
LWSTDAPIV_(int) wnsprintfW(
LPWSTR lpOut,
int cchLimitIn,
LPCWSTR lpFmt,
...)
{
va_list arglist;
int ret;
va_start(arglist, lpFmt);
ret = wvnsprintfW(lpOut, cchLimitIn, lpFmt, arglist);
va_end(arglist);
return ret;
}
LWSTDAPIV_(int) wsprintfW(
LPWSTR lpOut,
LPCWSTR lpFmt,
...)
{
// unsafe printf. arbitrary max of 0x10000 length
va_list arglist;
int ret;
va_start(arglist, lpFmt);
ret = wvnsprintfW(lpOut, 0x10000, lpFmt, arglist);
va_end(arglist);
return ret;
}
//+---------------------------------------------------------------------------
// StartDoc
//----------------------------------------------------------------------------
int StartDocWrap( HDC hDC, const DOCINFO * lpdi )
{
CStrIn strDocName( lpdi->lpszDocName );
CStrIn strOutput( lpdi->lpszOutput );
CStrIn strDatatype( lpdi->lpszDatatype );
DOCINFOA dia;
dia.cbSize = sizeof(DOCINFO);
dia.lpszDocName = strDocName;
dia.lpszOutput = strOutput;
dia.lpszDatatype = strDatatype;
dia.fwType = lpdi->fwType;
return StartDocA( hDC, &dia );
}
#endif // !WINNT
////////////////////////////////////////////////////////////////////
//
// Plug UI support with SHLWAPI
//
typedef HRESULT (*PFNDLLGETVERSION)(DLLVERSIONINFO * pinfo);
HMODULE GetShlwapiHModule()
{
HMODULE hShlwapi = GetModuleHandle(TEXT("SHLWAPI"));
if (hShlwapi)
{
PFNDLLGETVERSION pfnDllGetVersion = (PFNDLLGETVERSION)GetProcAddress(hShlwapi, "DllGetVersion");
if (pfnDllGetVersion)
{
DLLVERSIONINFO dllinfo;
dllinfo.cbSize = sizeof(DLLVERSIONINFO);
if (pfnDllGetVersion(&dllinfo) == NOERROR)
{
if (dllinfo.dwMajorVersion < 5)
{
// This guy doesn't support ML functions
hShlwapi = NULL;
}
}
}
}
return hShlwapi;
}
// First, we need access to some helper functions:
//
#ifndef UNIX
#define SHLWAPIMLISMLHINSTANCE_ORD 429
#else
#define SHLWAPIMLISMLHINSTANCE_ORD "MLIsMLHInstance"
#endif
typedef BOOL (* PFNMLISMLHINSTANCE)(HINSTANCE);
BOOL MLIsMLHInstanceWrap(HINSTANCE hInst)
{
HMODULE hShlwapi = GetShlwapiHModule();
if (hShlwapi)
{
PFNMLISMLHINSTANCE pfn;
pfn = (PFNMLISMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLISMLHINSTANCE_ORD);
if (pfn)
return pfn(hInst);
}
// BUGBUG: What if an app told comctl32 to be PlugUI and we picked
// a resource that cannot be displayed on Win9x without
// shlwapi's font linking? Seems like we need to foricbly
// load shlwapi in that case...
//
// No shlwapi? then this can't be an ML hinstance.
return FALSE;
}
#ifndef UNIX
#define SHLWAPIMLSETMLHINSTANCE_ORD 430
#else
#define SHLWAPIMLSETMLHINSTANCE_ORD "MLSetMLHInstance"
#endif
typedef HRESULT (* PFNMLSETMLHINSTANCE)(HINSTANCE, LANGID);
HRESULT MLSetMLHInstanceWrap(HINSTANCE hInst, LANGID lidUI)
{
HMODULE hShlwapi;
PFNMLSETMLHINSTANCE pfnMLSet = NULL;
hShlwapi = GetShlwapiHModule();
if (hShlwapi)
{
pfnMLSet = (PFNMLSETMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLSETMLHINSTANCE_ORD);
if (pfnMLSet)
return pfnMLSet(hInst, lidUI);
}
return E_FAIL;
}
#ifndef UNIX
#define SHLWAPIMLCLEARMLHINSTANCE_ORD 431
#else
#define SHLWAPIMLCLEARMLHINSTANCE_ORD "MLClearMLHInstance"
#endif
typedef HRESULT (* PFNMLCLEARMLHINSTANCE)(HINSTANCE);
HRESULT MLClearMLHinstanceWrap(HINSTANCE hInst)
{
HMODULE hShlwapi;
PFNMLCLEARMLHINSTANCE pfnMLClear = NULL;
hShlwapi = GetShlwapiHModule();
if (hShlwapi)
{
pfnMLClear = (PFNMLCLEARMLHINSTANCE)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIMLCLEARMLHINSTANCE_ORD);
if (pfnMLClear)
return pfnMLClear(hInst);
}
return E_FAIL;
}
//
// And now, when shlwapi is around we delegate to it's ML-enabled implementations:
//
//
// Make sure we get the real USER32 versions.
//
#undef CreateDialogIndirectParamW
#ifndef UNIX
#define SHLWAPICREATEDIALOGINDIRECTPARAM_ORD 393
#else
#define SHLWAPICREATEDIALOGINDIRECTPARAM_ORD "CreateDialogIndirectParamWrapW"
#endif
typedef HWND (* PFNCREATEDIALOGINDIRECTPARAM)(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM);
HWND CreateDialogIndirectParamWrap(
HINSTANCE hInstance,
LPCDLGTEMPLATE lpTemplate,
HWND hWndParent,
DLGPROC lpDialogFunc,
LPARAM dwInitParam)
{
HMODULE hShlwapi;
PFNCREATEDIALOGINDIRECTPARAM pfnCDIP = NULL;
HWND hwndRet;
// If shlwapi is in memory, ask it to create the dialog,
// as then we get ML dialogs on downlevel platforms (if
// the hInstance is from MLLoadLibrary -- otherwise it
// thunks to the real A/W api for us).
//
hShlwapi = GetShlwapiHModule();
if (hShlwapi)
{
pfnCDIP = (PFNCREATEDIALOGINDIRECTPARAM)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPICREATEDIALOGINDIRECTPARAM_ORD);
}
if (!pfnCDIP)
{
if (g_bRunOnNT)
pfnCDIP = CreateDialogIndirectParamW;
else
pfnCDIP = CreateDialogIndirectParamA;
}
// If this is from comctl32, assume it was loaded via the MUI-Language
if (HINST_THISDLL == hInstance)
MLSetMLHInstanceWrap(hInstance, GetMUILanguage());
hwndRet = pfnCDIP(hInstance, lpTemplate, hWndParent, lpDialogFunc, dwInitParam);
if (HINST_THISDLL == hInstance)
MLClearMLHinstanceWrap(hInstance);
return(hwndRet);
}
//
// Make sure we get the real USER32 versions.
//
#undef DialogBoxIndirectParamW
#ifndef UNIX
#define SHLWAPIDIALOGBOXINDIRECTPARAM_ORD 58
#else
#define SHLWAPIDIALOGBOXINDIRECTPARAM_ORD "DialogBoxIndirectParamWrapW"
#endif
typedef INT_PTR (* PFNDIALOGBOXINDIRECTPARAM)(HINSTANCE, LPCDLGTEMPLATE, HWND, DLGPROC, LPARAM);
INT_PTR DialogBoxIndirectParamWrap(
HINSTANCE hInstance,
LPCDLGTEMPLATEW hDialogTemplate,
HWND hWndParent,
DLGPROC lpDialogFunc,
LPARAM dwInitParam)
{
HMODULE hShlwapi;
INT_PTR iRet;
PFNDIALOGBOXINDIRECTPARAM pfnDBIP = NULL;
// If shlwapi is in memory, ask it to create the dialog,
// as then we get ML dialogs on downlevel platforms (if
// the hInstance is from MLLoadLibrary -- otherwise it
// thunks to the real A/W api for us).
//
hShlwapi = GetShlwapiHModule();
if (hShlwapi)
pfnDBIP = (PFNDIALOGBOXINDIRECTPARAM)GetProcAddress(hShlwapi, (LPCSTR)SHLWAPIDIALOGBOXINDIRECTPARAM_ORD);
if (!pfnDBIP)
{
if (g_bRunOnNT)
pfnDBIP = DialogBoxIndirectParamW;
else
pfnDBIP = DialogBoxIndirectParamA;
}
// If this is from comctl32, assume it was loaded via the MUI-Language
if (HINST_THISDLL == hInstance)
MLSetMLHInstanceWrap(hInstance, GetMUILanguage());
iRet = pfnDBIP(hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam);
if (HINST_THISDLL == hInstance)
MLClearMLHinstanceWrap(hInstance);
return iRet;
}
#endif // UNICODE