diff options
Diffstat (limited to 'win32/ScintillaWin.cxx')
-rw-r--r-- | win32/ScintillaWin.cxx | 214 |
1 files changed, 160 insertions, 54 deletions
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; } |