aboutsummaryrefslogtreecommitdiffhomepage
path: root/win32
diff options
context:
space:
mode:
Diffstat (limited to 'win32')
-rw-r--r--win32/PlatWin.cxx142
-rw-r--r--win32/ScintillaWin.cxx214
2 files changed, 253 insertions, 103 deletions
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index 63dd56648..7ce9930e4 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -323,20 +323,49 @@ void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
surfaceSource.hdc, from.x, from.y, SRCCOPY);
}
-#define ASCII_ONLY 1
+int UCS2FromUTF8(const char *s, int len, wchar_t *tbuf, int tlen) {
+#ifdef USE_API
+ return ::MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, tlen);
+#else
+ int ui=0;
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ int i=0;
+ while (i<len) {
+ unsigned char ch = us[i++];
+ if (ch < 0x80) {
+ tbuf[ui] = ch;
+ } else if (ch < 0x80 + 0x40 + 0x20) {
+ tbuf[ui] = (ch & 0x1F) << 6;
+ ch = us[i++];
+ tbuf[ui] += ch & 0x7F;
+ } else {
+ tbuf[ui] = (ch & 0xF) << 12;
+ ch = us[i++];
+ tbuf[ui] += (ch & 0x7F) << 6;
+ ch = us[i++];
+ tbuf[ui] += ch & 0x7F;
+ }
+ ui++;
+ }
+ return ui;
+#endif
+}
+
+#define MAX_US_LEN 5000
void Surface::DrawText(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back) {
SetFont(font_);
::SetTextColor(hdc, fore.AsLong());
::SetBkColor(hdc, back.AsLong());
RECT rcw = RectFromPRectangle(rc);
-#ifdef ASCII_ONLY
- ::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, s, len, NULL);
-#else
- wchar_t tbuf[20000];
- int tlen = MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, sizeof(tbuf));
- ::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE, &rcw, tbuf, tlen, NULL);
-#endif
+ if (unicodeMode) {
+ wchar_t tbuf[MAX_US_LEN];
+ int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t));
+ 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, len, NULL);
+ }
}
void Surface::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, Colour fore, Colour back) {
@@ -344,60 +373,75 @@ void Surface::DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char
::SetTextColor(hdc, fore.AsLong());
::SetBkColor(hdc, back.AsLong());
RECT rcw = RectFromPRectangle(rc);
-#ifdef ASCII_ONLY
- ::ExtTextOut(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, s, len, NULL);
-#else
- wchar_t tbuf[20000];
- int tlen = MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, sizeof(tbuf));
- ::ExtTextOutW(hdc, rc.left, ybase, ETO_OPAQUE | ETO_CLIPPED, &rcw, tbuf, tlen, NULL);
-#endif
+ if (unicodeMode) {
+ wchar_t tbuf[MAX_US_LEN];
+ int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t));
+ 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, len, NULL);
+ }
}
int Surface::WidthText(Font &font_, const char *s, int len) {
SetFont(font_);
- SIZE sz;
-#ifdef ASCII_ONLY
- ::GetTextExtentPoint32(hdc, s, len, &sz);
-#else
- wchar_t tbuf[20000];
- int tlen = MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, sizeof(tbuf));
- ::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz);
-#endif
+ SIZE sz={0,0};
+ if (unicodeMode) {
+ int fit = 0;
+ wchar_t tbuf[MAX_US_LEN];
+ int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t));
+ tbuf[tlen] = L'\0';
+ fit = tlen;
+ //::GetTextExtentPoint32W(hdc, tbuf, tlen, &sz);
+ if (!::GetTextExtentExPointW(hdc, tbuf, tlen, 30000, &fit, NULL, &sz)) {
+ DWORD dw = GetLastError();
+ Platform::DebugPrintf("Error for 1 GTEEPW %d\n", dw);
+ } else {
+ //Platform::DebugPrintf("OK 1 GTEEPW %d\n", len);
+ }
+ } else {
+ ::GetTextExtentPoint32(hdc, s, len, &sz);
+ }
return sz.cx;
}
void Surface::MeasureWidths(Font &font_, const char *s, int len, int *positions) {
SetFont(font_);
- SIZE sz;
+ SIZE sz={0,0};
int fit = 0;
-#ifdef ASCII_ONLY
- ::GetTextExtentExPoint(hdc, s, len, 30000, &fit, positions, &sz);
-#else
- wchar_t tbuf[20000];
- int poses[20000];
- int tlen = MultiByteToWideChar(CP_UTF8, 0, s, len, tbuf, sizeof(tbuf));
- ::GetTextExtentExPointW(hdc, tbuf, tlen, 30000, &fit, poses, &sz);
- int ui=0;
- const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
- int i=0;
- while (i<len) {
- positions[i] = poses[ui];
- if (us[i] < 128) {
- ui++;
- } else if (us[i] < (128 + 64 + 32)) {
- positions[i+1] = poses[ui];
- ui++;
- i++;
+ if (unicodeMode) {
+ wchar_t tbuf[MAX_US_LEN];
+ int tlen = UCS2FromUTF8(s, len, tbuf, sizeof(tbuf)/sizeof(wchar_t));
+ tbuf[tlen] = L'\0';
+ int poses[MAX_US_LEN];
+ fit = tlen;
+ SetLastError(0);
+ if (!::GetTextExtentExPointW(hdc, tbuf, tlen, 30000, &fit, poses, &sz)) {
+ DWORD dw = GetLastError();
+ Platform::DebugPrintf("Error for GTEEPW %d\n", dw);
} else {
- positions[i+1] = poses[ui];
- positions[i+2] = poses[ui];
+ //Platform::DebugPrintf("OK GTEEPW %d\n", len);
+ }
+ int ui=0;
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ int i=0;
+ while (i<len) {
+ unsigned char uch = us[i];
+ positions[i++] = poses[ui];
+ if (uch >= 0x80) {
+ if (uch < (0x80 + 0x40 + 0x20)) {
+ positions[i++] = poses[ui];
+ } else {
+ positions[i++] = poses[ui];
+ positions[i++] = poses[ui];
+ }
+ }
ui++;
- i++;
- i++;
}
- i++;
+ positions[i] = sz.cx;
+ } else {
+ ::GetTextExtentExPoint(hdc, s, len, 30000, &fit, positions, &sz);
}
-#endif
}
int Surface::WidthChar(Font &font_, char ch) {
@@ -704,7 +748,7 @@ int Platform::Maximum(int a, int b) {
return b;
}
-//#define TRACE
+#define TRACE
void Platform::DebugPrintf(const char *format, ...) {
#ifdef TRACE
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index 9334ae215..104f15423 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -137,7 +137,7 @@ class ScintillaWin :
void ImeEndComposition();
void GetIntelliMouseParameters();
- HGLOBAL GetSelText();
+ void CopySelTextToClipboard();
void ScrollMessage(WPARAM wParam);
void HorizontalScrollMessage(WPARAM wParam);
void RealizeWindowPalette(bool inBackGround);
@@ -268,6 +268,7 @@ LRESULT ScintillaWin::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
BeginPaint(wMain.GetID(), &ps);
Surface surfaceWindow;
surfaceWindow.Init(ps.hdc);
+ surfaceWindow.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage);
rcPaint = PRectangle(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
PRectangle rcText = GetTextRectangle();
paintingAllText = rcPaint.Contains(rcText);
@@ -456,11 +457,13 @@ LRESULT ScintillaWin::WndProc(UINT iMessage, WPARAM wParam, LPARAM lParam) {
break;
case EM_CANPASTE: {
- OpenClipboard(wMain.GetID());
- HGLOBAL hmemSelection = GetClipboardData(CF_TEXT);
+ ::OpenClipboard(wMain.GetID());
+ HGLOBAL hmemSelection = ::GetClipboardData(CF_TEXT);
+ if (!hmemSelection && (SC_CP_UTF8 == pdoc->dbcsCodePage))
+ hmemSelection = ::GetClipboardData(CF_UNICODETEXT);
if (hmemSelection)
- GlobalUnlock(hmemSelection);
- CloseClipboard();
+ ::GlobalUnlock(hmemSelection);
+ ::CloseClipboard();
return hmemSelection != 0;
}
@@ -585,10 +588,9 @@ void ScintillaWin::NotifyDoubleClick(Point pt, bool shift) {
void ScintillaWin::Copy() {
//Platform::DebugPrintf("Copy\n");
if (currentPos != anchor) {
- HGLOBAL hmemSelection = GetSelText();
::OpenClipboard(wMain.GetID());
::EmptyClipboard();
- ::SetClipboardData(CF_TEXT, hmemSelection);
+ CopySelTextToClipboard();
if (selType == selRectangle) {
::SetClipboardData(cfColumnSelect, 0);
}
@@ -596,31 +598,88 @@ void ScintillaWin::Copy() {
}
}
+unsigned int UTF8Length(wchar_t *uptr, unsigned int tlen) {
+ unsigned int len = 0;
+ for (unsigned int i = 0; i < tlen && uptr[i]; i++) {
+ unsigned int uch = uptr[i];
+ if (uch < 0x80)
+ len++;
+ else if (uch < 0x800)
+ len+=2;
+ else
+ len +=3;
+ }
+ return len;
+}
+
+void UTF8FromUCS2(wchar_t *uptr, unsigned int tlen, char *putf, int len) {
+ int k = 0;
+ for (unsigned int i = 0; i < tlen && uptr[i]; i++) {
+ unsigned int uch = uptr[i];
+ if (uch < 0x80) {
+ putf[k++] = uch;
+ } else if (uch < 0x800) {
+ putf[k++] = 0xC0 | (uch >> 6);
+ putf[k++] = 0x80 | (uch & 0x3f);
+ } else {
+ putf[k++] = 0xE0 | (uch >> 12);
+ putf[k++] = 0x80 | ((uch >> 6) & 0x3f);
+ putf[k++] = 0x80 | (uch & 0x3f);
+ }
+ }
+ putf[len] = '\0';
+}
+
void ScintillaWin::Paste() {
pdoc->BeginUndoAction();
int selStart = SelectionStart();
ClearSelection();
::OpenClipboard(wMain.GetID());
bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect);
- HGLOBAL hmemSelection = ::GetClipboardData(CF_TEXT);
- if (hmemSelection) {
- char *ptr = static_cast<char *>(
- ::GlobalLock(hmemSelection));
- if (ptr) {
- unsigned int bytes = ::GlobalSize(hmemSelection);
- unsigned int len = bytes;
- for (unsigned int i = 0; i < bytes; i++) {
- if ((len == bytes) && (0 == ptr[i]))
- len = i;
+ HGLOBAL hmemUSelection = 0;
+ if (SC_CP_UTF8 == pdoc->dbcsCodePage) {
+ hmemUSelection = ::GetClipboardData(CF_UNICODETEXT);
+ if (hmemUSelection) {
+ wchar_t *uptr = static_cast<wchar_t *>(::GlobalLock(hmemUSelection));
+ if (uptr) {
+ unsigned int bytes = ::GlobalSize(hmemUSelection);
+ unsigned int len = UTF8Length(uptr, bytes/2);
+ char *putf = new char[len+1];
+ if (putf) {
+ UTF8FromUCS2(uptr, bytes/2, putf, len);
+ if (isRectangular) {
+ PasteRectangular(selStart, putf, len);
+ } else {
+ pdoc->InsertString(currentPos, putf, len);
+ SetEmptySelection(currentPos + len);
+ }
+ delete []putf;
+ }
}
- if (isRectangular) {
- PasteRectangular(selStart, ptr, len);
- } else {
- pdoc->InsertString(currentPos, ptr, len);
- SetEmptySelection(currentPos + len);
+ ::GlobalUnlock(hmemUSelection);
+ }
+ }
+ if (!hmemUSelection) {
+ HGLOBAL hmemSelection = ::GetClipboardData(CF_TEXT);
+ if (hmemSelection) {
+ char *ptr = static_cast<char *>(
+ ::GlobalLock(hmemSelection));
+ if (ptr) {
+ unsigned int bytes = ::GlobalSize(hmemSelection);
+ unsigned int len = bytes;
+ for (unsigned int i = 0; i < bytes; i++) {
+ if ((len == bytes) && (0 == ptr[i]))
+ len = i;
+ }
+ if (isRectangular) {
+ PasteRectangular(selStart, ptr, len);
+ } else {
+ pdoc->InsertString(currentPos, ptr, len);
+ SetEmptySelection(currentPos + len);
+ }
}
+ ::GlobalUnlock(hmemSelection);
}
- ::GlobalUnlock(hmemSelection);
}
::CloseClipboard();
pdoc->EndUndoAction();
@@ -795,7 +854,7 @@ STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
}
if (
- ((pFE->cfFormat != CF_TEXT) && (pFE->cfFormat != CF_HDROP)) ||
+ ((pFE->cfFormat != CF_TEXT) && (pFE->cfFormat != CF_UNICODETEXT) && (pFE->cfFormat != CF_HDROP)) ||
pFE->ptd != 0 ||
(pFE->dwAspect & DVASPECT_CONTENT) == 0 ||
pFE->lindex != -1 ||
@@ -963,25 +1022,56 @@ void ScintillaWin::GetIntelliMouseParameters() {
::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &ucWheelScrollLines, 0);
}
-HGLOBAL ScintillaWin::GetSelText() {
+void ScintillaWin::CopySelTextToClipboard() {
int bytes = SelectionRangeLength();
+ char *selChars = CopySelectionRange();
+ if (!selChars)
+ return;
HGLOBAL hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
bytes + 1);
if (hand) {
char *ptr = static_cast<char *>(::GlobalLock(hand));
- char *selChars = CopySelectionRange();
- if (selChars) {
- memcpy(ptr, selChars, bytes);
- delete []selChars;
- //for (int i = 0; i < bytes; i++) {
- // ptr[i] = pdoc->CharAt(startPos + i);
- //}
- }
+ memcpy(ptr, selChars, bytes);
ptr[bytes] = '\0';
::GlobalUnlock(hand);
}
- return hand;
+ ::SetClipboardData(CF_TEXT, hand);
+
+ if (SC_CP_UTF8 == pdoc->dbcsCodePage) {
+ int uchars = 0;
+ for (int i=0;i<bytes;i++) {
+ unsigned char ch = static_cast<unsigned char>(selChars[i]);
+ if ((ch < 0x80) || (ch > (0x80 + 0x40)))
+ uchars++;
+ }
+ HGLOBAL uhand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
+ 2 * (uchars + 1));
+ if (uhand) {
+ wchar_t *uptr = static_cast<wchar_t *>(::GlobalLock(uhand));
+ int k=0;
+ for (int j=0; j<uchars; j++) {
+ unsigned char ch = static_cast<unsigned char>(selChars[k++]);
+ if (ch < 0x80) {
+ uptr[j] = ch;
+ } else if (ch < 0x80 + 0x40 + 0x20) {
+ uptr[j] = (ch & 0x1F) << 6;
+ ch = static_cast<unsigned char>(selChars[k++]);
+ uptr[j] += ch & 0x7F;
+ } else {
+ uptr[j] = (ch & 0xF) << 12;
+ ch = static_cast<unsigned char>(selChars[k++]);
+ uptr[j] += (ch & 0x7F) << 6;
+ ch = static_cast<unsigned char>(selChars[k++]);
+ uptr[j] += ch & 0x7F;
+ }
+ }
+ uptr[uchars] = 0;
+ ::GlobalUnlock(uhand);
+ }
+ ::SetClipboardData(CF_UNICODETEXT, uhand);
+ }
+ delete []selChars;
}
void ScintillaWin::ScrollMessage(WPARAM wParam) {
@@ -1068,6 +1158,7 @@ void ScintillaWin::FullPaint() {
HDC hdc = ::GetDC(wMain.GetID());
Surface surfaceWindow;
surfaceWindow.Init(hdc);
+ surfaceWindow.SetUnicodeMode(SC_CP_UTF8 == pdoc->dbcsCodePage);
Paint(&surfaceWindow, rcPaint);
surfaceWindow.Release();
::ReleaseDC(wMain.GetID(), hdc);
@@ -1151,30 +1242,42 @@ STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
SetDragPosition(invalidPosition);
- FORMATETC fmte = {CF_TEXT,
- NULL,
- DVASPECT_CONTENT,
- -1,
- TYMED_HGLOBAL
- };
STGMEDIUM medium;
+ HRESULT hr = S_OK;
+
+ wchar_t *udata = 0;
+ char *data = 0;
+ int dataLen = 0;
+
+ if (SC_CP_UTF8 == pdoc->dbcsCodePage) {
+ FORMATETC fmtu = {CF_UNICODETEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ hr = pIDataSource->GetData(&fmtu, &medium);
+ if (SUCCEEDED(hr) && medium.hGlobal) {
+ udata = static_cast<wchar_t *>(::GlobalLock(medium.hGlobal));
+ int tlen = ::GlobalSize(medium.hGlobal);
+ // Convert UCS-2 to UTF-8
+ dataLen = UTF8Length(udata, tlen/2);
+ data = new char[dataLen+1];
+ if (data) {
+ UTF8FromUCS2(udata, tlen/2, data, dataLen);
+ }
+ }
+ }
- HRESULT hres = pIDataSource->GetData(&fmte, &medium);
- if (FAILED(hres)) {
- //Platform::DebugPrintf("Bad data format: 0x%x\n", hres);
- return hres;
+ if (!data) {
+ FORMATETC fmte = {CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ hr = pIDataSource->GetData(&fmte, &medium);
+ if (SUCCEEDED(hr) && medium.hGlobal) {
+ data = static_cast<char *>(::GlobalLock(medium.hGlobal));
+ }
}
- if (medium.hGlobal == 0) {
- return E_OUTOFMEMORY;
+
+ if (!data) {
+ //Platform::DebugPrintf("Bad data format: 0x%x\n", hres);
+ return hr;
}
- char *data = static_cast<char *>(::GlobalLock(medium.hGlobal));
-
- FORMATETC fmtr = {cfColumnSelect,
- NULL,
- DVASPECT_CONTENT,
- -1,
- TYMED_HGLOBAL
- };
+
+ FORMATETC fmtr = {cfColumnSelect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hrRectangular = pIDataSource->QueryGetData(&fmtr);
POINT rpt = {pt.x, pt.y};
@@ -1190,6 +1293,9 @@ STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
if (medium.pUnkForRelease != NULL)
medium.pUnkForRelease->Release();
+ if (udata)
+ delete []data;
+
return S_OK;
}