aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--win32/PlatWin.cxx110
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() {