diff options
author | nyamatongwe <devnull@localhost> | 2005-10-31 12:05:48 +0000 |
---|---|---|
committer | nyamatongwe <devnull@localhost> | 2005-10-31 12:05:48 +0000 |
commit | 97b0dbee2deee389c858a7a074fc4f80cae0eaa5 (patch) | |
tree | 76720fd9b3e8e0d6dbed08c2e0a7a2386652c53c | |
parent | 3e3820398a5ba722010a182403cf92bf4094907c (diff) | |
download | scintilla-mirror-97b0dbee2deee389c858a7a074fc4f80cae0eaa5.tar.gz |
Fix for bug 1342035 where two NULs were placed on clipboard
by copy.
Also fixed up some other potential clipboard issues and created
GlobalMemory class to regularise clipboard memory handling.
-rw-r--r-- | win32/ScintillaWin.cxx | 159 |
1 files changed, 89 insertions, 70 deletions
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index b36cc276b..5b54e75fe 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -1159,6 +1159,45 @@ static UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) { return cp; } +class GlobalMemory { + HGLOBAL hand; +public: + void *ptr; + GlobalMemory() : hand(0), ptr(0) { + } + GlobalMemory(HGLOBAL hand_) : hand(hand_), ptr(0) { + if (hand) { + ptr = ::GlobalLock(hand); + } + } + ~GlobalMemory() { + PLATFORM_ASSERT(!ptr); + } + void Allocate(size_t bytes) { + hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, bytes); + if (hand) { + ptr = ::GlobalLock(hand); + } + } + HGLOBAL Unlock() { + PLATFORM_ASSERT(ptr); + HGLOBAL handCopy = hand; + ::GlobalUnlock(hand); + ptr = 0; + hand = 0; + return handCopy; + } + void SetClip(UINT uFormat) { + ::SetClipboardData(uFormat, Unlock()); + } + operator bool() { + return ptr != 0; + } + SIZE_T Size() { + return ::GlobalSize(hand); + } +}; + void ScintillaWin::Paste() { if (!::OpenClipboard(MainHWND())) return; @@ -1168,15 +1207,15 @@ void ScintillaWin::Paste() { bool isRectangular = ::IsClipboardFormatAvailable(cfColumnSelect) != 0; // Always use CF_UNICODETEXT if available - HGLOBAL hmemUSelection = ::GetClipboardData(CF_UNICODETEXT); - if (hmemUSelection) { - wchar_t *uptr = static_cast<wchar_t *>(::GlobalLock(hmemUSelection)); + GlobalMemory memUSelection(::GetClipboardData(CF_UNICODETEXT)); + if (memUSelection) { + wchar_t *uptr = static_cast<wchar_t *>(memUSelection.ptr); if (uptr) { unsigned int len; char *putf; // Default Scintilla behaviour in Unicode mode if (IsUnicodeMode()) { - unsigned int bytes = ::GlobalSize(hmemUSelection); + unsigned int bytes = memUSelection.Size(); len = UTF8Length(uptr, bytes / 2); putf = new char[len + 1]; if (putf) { @@ -1207,15 +1246,14 @@ void ScintillaWin::Paste() { delete []putf; } } - ::GlobalUnlock(hmemUSelection); + memUSelection.Unlock(); } else { // CF_UNICODETEXT not available, paste ANSI text - HGLOBAL hmemSelection = ::GetClipboardData(CF_TEXT); - if (hmemSelection) { - char *ptr = static_cast<char *>( - ::GlobalLock(hmemSelection)); + GlobalMemory memSelection(::GetClipboardData(CF_TEXT)); + if (memSelection) { + char *ptr = static_cast<char *>(memSelection.ptr); if (ptr) { - unsigned int bytes = ::GlobalSize(hmemSelection); + unsigned int bytes = memSelection.Size(); unsigned int len = bytes; for (unsigned int i = 0; i < bytes; i++) { if ((len == bytes) && (0 == ptr[i])) @@ -1224,11 +1262,10 @@ void ScintillaWin::Paste() { // In Unicode mode, convert clipboard text to UTF-8 if (IsUnicodeMode()) { - wchar_t *uptr = static_cast<wchar_t *>(::GlobalAlloc(GPTR, - len * 2 + 2)); + wchar_t *uptr = new wchar_t[len+1]; unsigned int ulen = ::MultiByteToWideChar(CP_ACP, 0, - ptr, len, uptr, GlobalSize(static_cast<wchar_t *>(uptr))); + ptr, len, uptr, len+1); unsigned int mlen = UTF8Length(uptr, ulen); char *putf = new char[mlen + 1]; @@ -1237,7 +1274,7 @@ void ScintillaWin::Paste() { UTF8FromUCS2(uptr, ulen, putf, mlen); } - ::GlobalFree(static_cast<wchar_t *>(uptr)); + delete []uptr; if (isRectangular) { PasteRectangular(selStart, putf, mlen); @@ -1255,7 +1292,7 @@ void ScintillaWin::Paste() { } } } - ::GlobalUnlock(hmemSelection); + memSelection.Unlock(); } } ::CloseClipboard(); @@ -1694,62 +1731,49 @@ void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) { return ; ::EmptyClipboard(); - HGLOBAL uhand; - wchar_t *uptr = 0; + GlobalMemory uniText; // Default Scintilla behaviour in Unicode mode if (IsUnicodeMode()) { int uchars = UCS2Length(selectedText.s, selectedText.len); - uhand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, - 2 * (uchars)); - if (uhand) { - uptr = static_cast<wchar_t *>(::GlobalLock(uhand)); - UCS2FromUTF8(selectedText.s, selectedText.len, uptr, uchars); + uniText.Allocate(2 * uchars); + if (uniText) { + UCS2FromUTF8(selectedText.s, selectedText.len, static_cast<wchar_t *>(uniText.ptr), uchars); } } else { // Not Unicode mode // Convert to Unicode using the current Scintilla code page UINT cpSrc = CodePageFromCharSet( selectedText.characterSet, selectedText.codePage); - uhand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, - 2 * (selectedText.len + 1)); - if (uhand) { - uptr = static_cast<wchar_t *>(::GlobalLock(uhand)); - ::MultiByteToWideChar(cpSrc, 0, - selectedText.s, selectedText.len, uptr, GlobalSize(uhand)); + uniText.Allocate(2 * selectedText.len); + if (uniText) { + ::MultiByteToWideChar(cpSrc, 0, selectedText.s, selectedText.len, + static_cast<wchar_t *>(uniText.ptr), selectedText.len); } } - // Copy ANSI text to clipboard on Windows 9x - // Convert from Unicode text, so other ANSI programs can - // paste the text - // Windows NT, 2k, XP automatically generates CF_TEXT - if (!IsNT() && uhand) { - HGLOBAL hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, - selectedText.len); - if (hand) { - char *ptr = static_cast<char *>(::GlobalLock(hand)); - ::WideCharToMultiByte(CP_ACP, 0, uptr, -1, ptr, GlobalSize(hand), - NULL, NULL); - ::GlobalUnlock(hand); - ::SetClipboardData(CF_TEXT, hand); + if (uniText) { + if (!IsNT()) { + // Copy ANSI text to clipboard on Windows 9x + // Convert from Unicode text, so other ANSI programs can + // paste the text + // Windows NT, 2k, XP automatically generates CF_TEXT + GlobalMemory ansiText; + ansiText.Allocate(selectedText.len); + if (ansiText) { + ::WideCharToMultiByte(CP_ACP, 0, static_cast<wchar_t *>(uniText.ptr), -1, + static_cast<char *>(ansiText.ptr), selectedText.len, NULL, NULL); + ansiText.SetClip(CF_TEXT); + } } - } - - if (uhand) { - ::GlobalUnlock(uhand); - ::SetClipboardData(CF_UNICODETEXT, uhand); - } - - // There was a failure - try to copy at least ANSI text - if (!uhand) { - HGLOBAL hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, - selectedText.len); - if (hand) { - char *ptr = static_cast<char *>(::GlobalLock(hand)); - memcpy(ptr, selectedText.s, selectedText.len); - ::GlobalUnlock(hand); - ::SetClipboardData(CF_TEXT, hand); + uniText.SetClip(CF_UNICODETEXT); + } else { + // There was a failure - try to copy at least ANSI text + GlobalMemory ansiText; + ansiText.Allocate(selectedText.len); + if (ansiText) { + memcpy(static_cast<char *>(ansiText.ptr), selectedText.s, selectedText.len); + ansiText.SetClip(CF_TEXT); } } @@ -2059,25 +2083,20 @@ STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) { pSTM->tymed = TYMED_HGLOBAL; //Platform::DebugPrintf("DOB GetData OK %d %x %x\n", lenDrag, pFEIn, pSTM); - HGLOBAL hand; + GlobalMemory text; if (pFEIn->cfFormat == CF_UNICODETEXT) { int uchars = UCS2Length(drag.s, drag.len); - hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 2 * (uchars)); - if (hand) { - wchar_t *uptr = static_cast<wchar_t *>(::GlobalLock(hand)); - UCS2FromUTF8(drag.s, drag.len, uptr, uchars); + text.Allocate(2 * uchars); + if (text) { + UCS2FromUTF8(drag.s, drag.len, static_cast<wchar_t *>(text.ptr), uchars); } } else { - hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, drag.len); - if (hand) { - char *ptr = static_cast<char *>(::GlobalLock(hand)); - for (int i = 0; i < drag.len; i++) { - ptr[i] = drag.s[i]; - } + text.Allocate(drag.len); + if (text) { + memcpy(static_cast<char *>(text.ptr), drag.s, drag.len); } } - ::GlobalUnlock(hand); - pSTM->hGlobal = hand; + pSTM->hGlobal = text.Unlock(); pSTM->pUnkForRelease = 0; return S_OK; } |