|
|
//+---------------------------------------------------------------------------
//
// 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
|