diff options
-rw-r--r-- | win32/PlatWin.cxx | 110 |
1 files changed, 70 insertions, 40 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index a2862efb0..66bbd25f3 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -309,6 +309,10 @@ class SurfaceImpl : public Surface { int maxWidthMeasure; int maxLenText; + int codePage; + // If 9x OS and current code page is same as ANSI code page. + bool win9xACPSame; + void BrushColor(ColourAllocated back); void SetFont(Font &font_); @@ -338,6 +342,7 @@ public: void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back); void Copy(PRectangle rc, Point from, Surface &surfaceSource); + void DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions); void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back); void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back); void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore); @@ -356,7 +361,7 @@ public: void FlushCachedState(); void SetUnicodeMode(bool unicodeMode_); - void SetDBCSMode(int codePage); + void SetDBCSMode(int codePage_); }; SurfaceImpl::SurfaceImpl() : @@ -372,6 +377,9 @@ SurfaceImpl::SurfaceImpl() : // There appears to be a 16 bit string length limit in GDI on NT and a limit of // 8192 characters on Windows 95. maxLenText = IsNT() ? 65535 : 8192; + + codePage = 0; + win9xACPSame = false; } SurfaceImpl::~SurfaceImpl() { @@ -545,40 +553,41 @@ void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) { static_cast<SurfaceImpl &>(surfaceSource).hdc, from.x, from.y, SRCCOPY); } -#define MAX_US_LEN 10000 +const int MAX_US_LEN = 10000; -void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, - ColourAllocated fore, ColourAllocated back) { +void SurfaceImpl::DrawTextCommon(PRectangle rc, Font &font_, int ybase, const char *s, int len, UINT fuOptions) { SetFont(font_); - ::SetTextColor(hdc, fore.AsLong()); - ::SetBkColor(hdc, back.AsLong()); RECT rcw = RectFromPRectangle(rc); if (unicodeMode) { wchar_t tbuf[MAX_US_LEN]; - int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)-1); - tbuf[tlen] = L'\0'; - ::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, tbuf, tlen, NULL); - } else { - ::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, s, + int tlen = UCS2FromUTF8(s, len, tbuf, MAX_US_LEN); + ::ExtTextOutW(hdc, rc.left, ybase, fuOptions, &rcw, tbuf, tlen, NULL); + } else if (IsNT() || (codePage==0) || win9xACPSame) { + ::ExtTextOutA(hdc, rc.left, ybase, fuOptions, &rcw, s, Platform::Minimum(len, maxLenText), NULL); + } else { + // Support Asian string display in 9x English + wchar_t tbuf[MAX_US_LEN]; + int tlen = ::MultiByteToWideChar(codePage, 0, s, len, NULL, 0); + if (tlen > MAX_US_LEN) + tlen = MAX_US_LEN; + ::MultiByteToWideChar(codePage, 0, s, len, tbuf, tlen); + ::ExtTextOutW(hdc, rc.left, ybase, fuOptions, &rcw, tbuf, tlen, NULL); } } +void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, + ColourAllocated fore, ColourAllocated back) { + ::SetTextColor(hdc, fore.AsLong()); + ::SetBkColor(hdc, back.AsLong()); + DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE); +} + void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back) { - SetFont(font_); ::SetTextColor(hdc, fore.AsLong()); ::SetBkColor(hdc, back.AsLong()); - RECT rcw = RectFromPRectangle(rc); - if (unicodeMode) { - wchar_t tbuf[MAX_US_LEN]; - int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)-1); - tbuf[tlen] = L'\0'; - ::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, tbuf, tlen, NULL); - } else { - ::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, s, - Platform::Minimum(len, maxLenText), NULL); - } + DrawTextCommon(rc, font_, ybase, s, len, ETO_OPAQUE | ETO_CLIPPED); } void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, @@ -586,19 +595,9 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font_, int ybase, con // Avoid drawing spaces in transparent mode for (int i=0;i<len;i++) { if (s[i] != ' ') { - SetFont(font_); ::SetTextColor(hdc, fore.AsLong()); ::SetBkMode(hdc, TRANSPARENT); - RECT rcw = RectFromPRectangle(rc); - if (unicodeMode) { - wchar_t tbuf[MAX_US_LEN]; - int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)-1); - tbuf[tlen] = L'\0'; - ::ExtTextOutW(hdc, rc.left, ybase, 0, &rcw, tbuf, tlen, NULL); - } else { - ::ExtTextOut(hdc, rc.left, ybase, 0, &rcw, s, - Platform::Minimum(len,maxLenText), NULL); - } + DrawTextCommon(rc, font_, ybase, s, len, 0); ::SetBkMode(hdc, OPAQUE); return; } @@ -610,11 +609,16 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { SIZE sz={0,0}; if (unicodeMode) { wchar_t tbuf[MAX_US_LEN]; - int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)-1); - tbuf[tlen] = L'\0'; + int tlen = UCS2FromUTF8(s, len, tbuf, MAX_US_LEN); ::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz); - } else { + } else if (IsNT() || (codePage==0) || win9xACPSame) { ::GetTextExtentPoint32(hdc, s, Platform::Minimum(len, maxLenText), &sz); + } else { + // Support Asian string display in 9x English + wchar_t tbuf[MAX_US_LEN]; + int tlen = ::MultiByteToWideChar(codePage, 0, s, len, NULL, 0); + ::MultiByteToWideChar(codePage, 0, s, len, tbuf, tlen); + ::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz); } return sz.cx; } @@ -625,8 +629,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi int fit = 0; if (unicodeMode) { wchar_t tbuf[MAX_US_LEN]; - int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t)-1); - tbuf[tlen] = L'\0'; + int tlen = UCS2FromUTF8(s, len, tbuf, MAX_US_LEN); int poses[MAX_US_LEN]; fit = tlen; if (!::GetTextExtentExPointW(hdc, tbuf, tlen, maxWidthMeasure, &fit, poses, &sz)) { @@ -661,7 +664,7 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi while (i<len) { positions[i++] = lastPos; } - } else { + } else if (IsNT() || (codePage==0) || win9xACPSame) { if (!::GetTextExtentExPoint(hdc, s, Platform::Minimum(len, maxLenText), maxWidthMeasure, &fit, positions, &sz)) { // Eeek - a NULL DC or other foolishness could cause this. @@ -673,6 +676,31 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi for (int i=fit;i<len;i++) positions[i] = positions[fit-1]; } + } else { + // Support Asian string display in 9x English + wchar_t tbuf[MAX_US_LEN]; + int tlen = ::MultiByteToWideChar(codePage, 0, s, len, NULL, 0); + ::MultiByteToWideChar(codePage, 0, s, len, tbuf, tlen); + + int poses[MAX_US_LEN]; + for (int widthSS=0; widthSS<tlen; widthSS++) { + ::GetTextExtentPoint32W(hdc, tbuf, widthSS+1, &sz); + poses[widthSS] = sz.cx; + } + + int ui = 0; + for (int i=0;i<len;) { + if (::IsDBCSLeadByteEx(codePage, s[i])) { + positions[i] = poses[ui]; + positions[i+1] = poses[ui]; + i += 2; + } else { + positions[i] = poses[ui]; + i++; + } + + ui++; + } } } @@ -753,8 +781,10 @@ void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) { unicodeMode=unicodeMode_; } -void SurfaceImpl::SetDBCSMode(int) { +void SurfaceImpl::SetDBCSMode(int codePage_) { // No action on window as automatically handled by system. + codePage = codePage_; + win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP()); } Surface *Surface::Allocate() { |