#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #include #include "exgdiw.h" #define ExMemAlloc(a) GlobalAllocPtr(GHND, (a)) #define ExMemFree(a) GlobalFreePtr((a)) static POSVERSIONINFO ExGetOSVersion(VOID) { static BOOL fFirst = TRUE; static OSVERSIONINFO os; if ( fFirst ) { os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx( &os ) ) { fFirst = FALSE; } } return &os; } static BOOL ExIsWin95(VOID) { BOOL fBool; fBool = (ExGetOSVersion()->dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && (ExGetOSVersion()->dwMajorVersion >= 4) && (ExGetOSVersion()->dwMinorVersion < 10); return fBool; } #if 0 static BOOL ExIsWin98(VOID) { BOOL fBool; fBool = (ExGetOSVersion()->dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && (ExGetOSVersion()->dwMajorVersion >= 4) && (ExGetOSVersion()->dwMinorVersion >= 10); return fBool; } static BOOL ExIsWinNT4(VOID) { BOOL fBool; fBool = (ExGetOSVersion()->dwPlatformId == VER_PLATFORM_WIN32_NT) && (ExGetOSVersion()->dwMajorVersion >= 4) && (ExGetOSVersion()->dwMinorVersion >= 0); return fBool; } static BOOL ExIsWinNT5(VOID) { BOOL fBool; fBool = (ExGetOSVersion()->dwPlatformId == VER_PLATFORM_WIN32_NT) && (ExGetOSVersion()->dwMajorVersion >= 4) && (ExGetOSVersion()->dwMinorVersion >= 10); return fBool; } static BOOL ExIsWinNT(VOID) { BOOL fBool; fBool = (ExGetOSVersion()->dwPlatformId == VER_PLATFORM_WIN32_NT); return fBool; } #endif //inline static UINT W2MForWin95(HDC hDC, LPWSTR lpwstr, UINT wchCount, // LPSTR lpstr, UINT chByteSize) static UINT W2MForGDI(INT codePage, LPWSTR lpwstr, UINT wchCount, LPSTR lpstr, UINT chByteSize) { LPSTR lptmp; UINT byte; UINT mbyte; char defChar = 0x7F; BOOL fUseDefChar = TRUE; switch(codePage) { case 932: case 936: case 950: case 949: byte = ::WideCharToMultiByte(codePage, WC_COMPOSITECHECK, lpwstr, wchCount, lpstr, chByteSize, &defChar, NULL); return byte; default: lptmp = lpstr; for(byte = 0; byte< wchCount; byte++) { defChar = 0x7F; mbyte = ::WideCharToMultiByte(codePage, WC_COMPOSITECHECK, lpwstr,1, lptmp, chByteSize - byte, &defChar, &fUseDefChar); if(mbyte != 1){ *lptmp = 0x7F; //defChar; } lptmp++; lpwstr++; } lpstr[byte]=0x00; return byte; } } static BOOL _ExExtTextOutWWithTrans(INT codePage, HDC hdc, int X, int Y, UINT fuOptions, CONST RECT *lprc, LPWSTR lpString, UINT cbCount, CONST INT *lpDx) { #ifndef UNDER_CE // always Unicode UINT bufsize = (cbCount + 1) * sizeof(WCHAR); BOOL fRet; LPSTR lpstr = (LPSTR)ExMemAlloc(bufsize); if(!lpstr) { return 0; } #if 0 UINT byte = ::WideCharToMultiByte(codePage, WC_COMPOSITECHECK, lpString, cbCount, lpstr, bufsize, &defChar, 0); #endif UINT byte = W2MForGDI(codePage, lpString, cbCount, lpstr, bufsize); fRet = ::ExtTextOutA(hdc,X,Y,fuOptions,lprc,lpstr, byte,lpDx); ExMemFree(lpstr); return fRet; #else // UNDER_CE return ::ExtTextOutW(hdc,X,Y,fuOptions,lprc,lpString, cbCount,lpDx); #endif // UNDER_CE } ////////////////////////////////////////////////////////////////// // Function : ExExtTextOutWForWin95 // Type : BOOL // Purpose : // Args : // : HDC hdc // handle to device context. // : int X // x-coordinate of reference point // : int Y // y-coordinate of reference point // : UINT fuOptions // text-output options. // : CONST RECT * lprc // optional clipping and/or opaquing rectangle. // : // : LPWSTR lpString // points to string. // : UINT cbCount // number of characters in string. // : CONST INT * lpDx // pointer to array of intercharacter spacing values // Return : // DATE : ////////////////////////////////////////////////////////////////// static BOOL ExExtTextOutWForWin95(HDC hdc, int X, int Y, UINT fuOptions, CONST RECT *lprc, LPWSTR lpString, UINT cbCount, CONST INT *lpDx) { //UINT bufsize = (cbCount + 1) * sizeof(WCHAR); TEXTMETRIC tm; ::GetTextMetrics(hdc, &tm); //---------------------------------------------------------------- //980730:By ToshiaK //Unicode GDI in Win95 has Bugs. //1. if try to use ExtTextOutW() with FE Unicode code point, with // som ANSI or SYMBOL charset font, GPF occurs. //2. ExtTextOutW() cannot draw EUDC code. (Must use ExtTextOutA() to draw) //---------------------------------------------------------------- LANGID langId = ::GetSystemDefaultLangID(); switch(tm.tmCharSet) { case SHIFTJIS_CHARSET: if(PRIMARYLANGID(langId) == LANG_JAPANESE) { return _ExExtTextOutWWithTrans(932, hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); } return ::ExtTextOutW(hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); break; case GB2312_CHARSET: if(langId == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)) { return _ExExtTextOutWWithTrans(936, hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); } return ::ExtTextOutW(hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); break; case CHINESEBIG5_CHARSET: if(langId == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)) { return _ExExtTextOutWWithTrans(950, hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); } return ::ExtTextOutW(hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); break; case HANGEUL_CHARSET: if(PRIMARYLANGID(langId) == LANG_KOREAN) { return _ExExtTextOutWWithTrans(949, hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); } return ::ExtTextOutW(hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); break; case SYMBOL_CHARSET: return _ExExtTextOutWWithTrans(1252, hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); break; default: { CHARSETINFO info; if(::TranslateCharsetInfo((DWORD *)tm.tmCharSet, &info, TCI_SRCCHARSET)) { return _ExExtTextOutWWithTrans(info.ciACP, hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); } else { return _ExExtTextOutWWithTrans(CP_ACP, hdc,X,Y,fuOptions,lprc,lpString,cbCount,lpDx); } } } } static BOOL _ExGetTextExtentPoint32WWithTrans(INT codePage, HDC hdc, LPWSTR wz, int cch, LPSIZE lpSize) { #ifndef UNDER_CE // always Unicode UINT bufsize = (cch + 1) * sizeof(WCHAR); LPSTR lpstr = (LPSTR)ExMemAlloc(bufsize); BOOL fRet; //CHAR defChar = 0x7F; if(!lpstr) { return 0; } UINT byte = W2MForGDI(codePage, wz, cch, lpstr, bufsize); #if 0 UINT byte = ::WideCharToMultiByte(codePage, WC_COMPOSITECHECK, wz, cch, lpstr, bufsize, &defChar, 0); #endif fRet = ::GetTextExtentPoint32A(hdc, lpstr, byte, lpSize); ExMemFree(lpstr); return fRet; #else // UNDER_CE return ::GetTextExtentPoint32W(hdc, wz, cch, lpSize); #endif // UNDER_CE } ////////////////////////////////////////////////////////////////// // Function : ExGetTextExtentPoint32WForWin95 // Type : inline BOOL // Purpose : // Args : // : HDC hdc //handle of device context. // : LPWSTR wz //address of text string. // : int cch //number of characters in string. // : LPSIZE lpSize //address of structure for string size. // Return : // DATE : Thu Jul 30 20:31:05 1998 // Histroy : ////////////////////////////////////////////////////////////////// static BOOL ExGetTextExtentPoint32WForWin95(HDC hdc, LPWSTR wz, int cch, LPSIZE lpSize) { TEXTMETRIC tm; ::GetTextMetrics(hdc, &tm); LANGID langId = ::GetSystemDefaultLangID(); switch(tm.tmCharSet) { case SHIFTJIS_CHARSET: if(PRIMARYLANGID(langId) == LANG_JAPANESE) { return _ExGetTextExtentPoint32WWithTrans(932, hdc, wz, cch,lpSize); } return ::GetTextExtentPoint32W(hdc, wz, cch, lpSize); break; case GB2312_CHARSET: if(langId == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)) { return _ExGetTextExtentPoint32WWithTrans(936, hdc, wz, cch,lpSize); } return ::GetTextExtentPoint32W(hdc, wz, cch, lpSize); break; case CHINESEBIG5_CHARSET: if(langId == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)) { return _ExGetTextExtentPoint32WWithTrans(950, hdc, wz, cch,lpSize); } return ::GetTextExtentPoint32W(hdc, wz, cch, lpSize); break; case HANGEUL_CHARSET: if(PRIMARYLANGID(langId) == LANG_KOREAN) { return _ExGetTextExtentPoint32WWithTrans(949, hdc, wz, cch,lpSize); } return ::GetTextExtentPoint32W(hdc, wz, cch, lpSize); break; case SYMBOL_CHARSET: return _ExGetTextExtentPoint32WWithTrans(1252, hdc, wz, cch,lpSize); break; default: { CHARSETINFO info; if(::TranslateCharsetInfo((DWORD *)tm.tmCharSet, &info, TCI_SRCCHARSET)) { return _ExGetTextExtentPoint32WWithTrans(info.ciACP, hdc, wz, cch,lpSize); } else { return _ExGetTextExtentPoint32WWithTrans(CP_ACP, hdc, wz, cch,lpSize); } } break; } } //---------------------------------------------------------------- //public Function //---------------------------------------------------------------- BOOL ExExtTextOutW(HDC hdc, // handle to device context. int X, // x-coordinate of reference point int Y, // y-coordinate of reference point UINT fuOptions, // text-output options. CONST RECT *lprc, // optional clipping and/or opaquing rectangle. LPWSTR lpString, // points to string. UINT cbCount, // number of characters in string. CONST INT *lpDx) // pointer to array of intercharacter spacing values ); { if(ExIsWin95()) { return ExExtTextOutWForWin95(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx); } return ExtTextOutW(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx); } BOOL ExGetTextExtentPoint32W(HDC hdc, // handle of device context. LPWSTR wz, // address of text string. int cch, // number of characters in string. LPSIZE lpSize) // address of structure for string size. { BOOL fRet; //if char count is 0 if(!wz) { lpSize->cx = lpSize->cy = 0; return 0; } if(cch == 0) { #ifndef UNDER_CE fRet = GetTextExtentPointA(hdc, " ", 1, lpSize); #else // UNDER_CE fRet = GetTextExtentPoint(hdc, TEXT(" "), 1, lpSize); #endif // UNDER_CE lpSize->cx = 0; return (fRet); } if(ExIsWin95()) { return ExGetTextExtentPoint32WForWin95(hdc, wz, cch, lpSize); } return GetTextExtentPoint32W(hdc, wz, cch, lpSize); }