5212 lines
154 KiB
C++
5212 lines
154 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// 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
|