aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--doc/ScintillaHistory.html12
-rw-r--r--win32/ScintillaWin.cxx180
2 files changed, 73 insertions, 119 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index e7dbf3834..4ed002f36 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -561,6 +561,18 @@
</li>
</ul>
<h3>
+ <a href="https://www.scintilla.org/scite431.zip">Release 4.3.1</a>
+ </h3>
+ <ul>
+ <li>
+ Released 16 January 2020.
+ </li>
+ <li>
+ Fix drag and drop between different encodings by always providing CF_UNICODETEXT only.
+ <a href="https://sourceforge.net/p/scintilla/bugs/2151/">Bug #2151</a>.
+ </li>
+ </ul>
+ <h3>
<a href="https://www.scintilla.org/scite430.zip">Release 4.3.0</a>
</h3>
<ul>
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index cdaa091a3..bcb4feae9 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -252,6 +252,8 @@ public:
}
};
+class GlobalMemory;
+
}
/**
@@ -381,6 +383,7 @@ class ScintillaWin :
LRESULT ImeOnReconvert(LPARAM lParam);
void GetIntelliMouseParameters() noexcept;
+ void CopyToGlobal(GlobalMemory &gmUnicode, const SelectionText &selectedText);
void CopyToClipboard(const SelectionText &selectedText) override;
void ScrollMessage(WPARAM wParam);
void HorizontalScrollMessage(WPARAM wParam);
@@ -2285,6 +2288,15 @@ bool OpenClipboardRetry(HWND hwnd) noexcept {
return false;
}
+bool SupportedFormat(const FORMATETC *pFE) noexcept {
+ return
+ pFE->cfFormat == CF_UNICODETEXT &&
+ pFE->ptd == nullptr &&
+ (pFE->dwAspect & DVASPECT_CONTENT) != 0 &&
+ pFE->lindex == -1 &&
+ (pFE->tymed & TYMED_HGLOBAL) != 0;
+}
+
}
void ScintillaWin::Paste() {
@@ -2491,28 +2503,16 @@ STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
return S_OK;
}
- const bool formatOK = (pFE->cfFormat == CF_TEXT) ||
- ((pFE->cfFormat == CF_UNICODETEXT) && pd->sci->IsUnicodeMode());
- if (!formatOK ||
- pFE->ptd != nullptr ||
- (pFE->dwAspect & DVASPECT_CONTENT) == 0 ||
- pFE->lindex != -1 ||
- (pFE->tymed & TYMED_HGLOBAL) == 0
- ) {
- //Platform::DebugPrintf("DOB QueryGetData No %x\n",pFE->cfFormat);
- //return DATA_E_FORMATETC;
+ if (SupportedFormat(pFE)) {
+ return S_OK;
+ } else {
return S_FALSE;
}
- //Platform::DebugPrintf("DOB QueryGetData OK %x\n",pFE->cfFormat);
- return S_OK;
}
-STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *pd, FORMATETC *, FORMATETC *pFEOut) {
+STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *, FORMATETC *, FORMATETC *pFEOut) {
//Platform::DebugPrintf("DOB GetCanon\n");
- if (pd->sci->IsUnicodeMode())
- pFEOut->cfFormat = CF_UNICODETEXT;
- else
- pFEOut->cfFormat = CF_TEXT;
+ pFEOut->cfFormat = CF_UNICODETEXT;
pFEOut->ptd = nullptr;
pFEOut->dwAspect = DVASPECT_CONTENT;
pFEOut->lindex = -1;
@@ -2532,14 +2532,8 @@ STDMETHODIMP DataObject_EnumFormatEtc(DataObject *pd, DWORD dwDirection, IEnumFO
*ppEnum = nullptr;
return E_FAIL;
}
- FormatEnumerator *pfe;
- if (pd->sci->IsUnicodeMode()) {
- CLIPFORMAT formats[] = {CF_UNICODETEXT, CF_TEXT};
- pfe = new FormatEnumerator(0, formats, std::size(formats));
- } else {
- CLIPFORMAT formats[] = {CF_TEXT};
- pfe = new FormatEnumerator(0, formats, std::size(formats));
- }
+ CLIPFORMAT formats[] = {CF_UNICODETEXT};
+ FormatEnumerator *pfe = new FormatEnumerator(0, formats, std::size(formats));
return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC,
reinterpret_cast<void **>(ppEnum));
} catch (std::bad_alloc &) {
@@ -2791,37 +2785,37 @@ void ScintillaWin::GetIntelliMouseParameters() noexcept {
::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
}
-void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
- if (!::OpenClipboardRetry(MainHWND())) {
- return;
- }
- ::EmptyClipboard();
-
- GlobalMemory uniText;
-
- // Default Scintilla behaviour in Unicode mode
+void ScintillaWin::CopyToGlobal(GlobalMemory &gmUnicode, const SelectionText &selectedText) {
+ const std::string_view svSelected(selectedText.Data(), selectedText.LengthWithTerminator());
if (IsUnicodeMode()) {
- const std::string_view sv(selectedText.Data(), selectedText.LengthWithTerminator());
- const size_t uchars = UTF16Length(sv);
- uniText.Allocate(2 * uchars);
- if (uniText) {
- UTF16FromUTF8(sv,
- static_cast<wchar_t *>(uniText.ptr), uchars);
+ const size_t uchars = UTF16Length(svSelected);
+ gmUnicode.Allocate(2 * uchars);
+ if (gmUnicode) {
+ UTF16FromUTF8(svSelected,
+ static_cast<wchar_t *>(gmUnicode.ptr), uchars);
}
} else {
// Not Unicode mode
// Convert to Unicode using the current Scintilla code page
const UINT cpSrc = CodePageFromCharSet(
- selectedText.characterSet, selectedText.codePage);
- const std::string_view svSelected(selectedText.Data(), selectedText.LengthWithTerminator());
+ selectedText.characterSet, selectedText.codePage);
const size_t uLen = WideCharLenFromMultiByte(cpSrc, svSelected);
- uniText.Allocate(2 * uLen);
- if (uniText) {
+ gmUnicode.Allocate(2 * uLen);
+ if (gmUnicode) {
WideCharFromMultiByte(cpSrc, svSelected,
- static_cast<wchar_t *>(uniText.ptr), uLen);
+ static_cast<wchar_t *>(gmUnicode.ptr), uLen);
}
}
+}
+
+void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
+ if (!::OpenClipboardRetry(MainHWND())) {
+ return;
+ }
+ ::EmptyClipboard();
+ GlobalMemory uniText;
+ CopyToGlobal(uniText, selectedText);
if (uniText) {
uniText.SetClip(CF_UNICODETEXT);
}
@@ -3009,17 +3003,12 @@ STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyStat
FORMATETC fmtu = {CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
const HRESULT hrHasUText = pIDataSource->QueryGetData(&fmtu);
hasOKText = (hrHasUText == S_OK);
- if (!hasOKText) {
- FORMATETC fmte = {CF_TEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- const HRESULT hrHasText = pIDataSource->QueryGetData(&fmte);
- hasOKText = (hrHasText == S_OK);
- }
- if (!hasOKText) {
+ if (hasOKText) {
+ *pdwEffect = EffectFromState(grfKeyState);
+ } else {
*pdwEffect = DROPEFFECT_NONE;
- return S_OK;
}
- *pdwEffect = EffectFromState(grfKeyState);
return S_OK;
}
@@ -3064,61 +3053,33 @@ STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
SetDragPosition(SelectionPosition(Sci::invalidPosition));
- STGMEDIUM medium {};
-
- std::vector<char> data; // Includes terminating NUL
-
- FORMATETC fmtu = {CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- HRESULT hr = pIDataSource->GetData(&fmtu, &medium);
- if (SUCCEEDED(hr) && medium.hGlobal) {
+ std::string putf;
+ FORMATETC fmtu = {CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
+ STGMEDIUM medium{};
+ const HRESULT hr = pIDataSource->GetData(&fmtu, &medium);
+ if (!SUCCEEDED(hr)) {
+ return hr;
+ }
+ if (medium.hGlobal) {
GlobalMemory memUDrop(medium.hGlobal);
- const wchar_t *udata = static_cast<const wchar_t *>(memUDrop.ptr);
- if (udata) {
- if (IsUnicodeMode()) {
- const size_t tlen = memUDrop.Size();
- // Convert UTF-16 to UTF-8
- const std::wstring_view wsv(udata, tlen / 2);
- const size_t dataLen = UTF8Length(wsv);
- data.resize(dataLen);
- UTF8FromUTF16(wsv, &data[0], dataLen);
- } else {
- // Convert UTF-16 to ANSI
- //
- // Default Scintilla behavior in Unicode mode
- // CF_UNICODETEXT available, but not in Unicode mode
- // Convert from Unicode to current Scintilla code page
- const UINT cpDest = CodePageOfDocument();
- const int tlen = MultiByteLenFromWideChar(cpDest, udata);
- data.resize(tlen);
- MultiByteFromWideChar(cpDest, udata, &data[0], tlen);
- }
+ if (const wchar_t *uptr = static_cast<const wchar_t *>(memUDrop.ptr)) {
+ putf = EncodeWString(uptr);
}
memUDrop.Unlock();
- } else {
- FORMATETC fmte = {CF_TEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- hr = pIDataSource->GetData(&fmte, &medium);
- if (SUCCEEDED(hr) && medium.hGlobal) {
- GlobalMemory memDrop(medium.hGlobal);
- const char *cdata = static_cast<const char *>(memDrop.ptr);
- if (cdata)
- data.assign(cdata, cdata+strlen(cdata));
- memDrop.Unlock();
- }
}
- if (!SUCCEEDED(hr) || data.empty()) {
- //Platform::DebugPrintf("Bad data format: 0x%x\n", hres);
- return hr;
+ if (putf.empty()) {
+ return S_OK;
}
FORMATETC fmtr = {cfColumnSelect, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
- const HRESULT hrRectangular = pIDataSource->QueryGetData(&fmtr);
+ const bool isRectangular = SUCCEEDED(pIDataSource->QueryGetData(&fmtr));
POINT rpt = {pt.x, pt.y};
::ScreenToClient(MainHWND(), &rpt);
const SelectionPosition movePos = SPositionFromLocation(PointFromPOINT(rpt), false, false, UserVirtualSpace());
- DropAt(movePos, &data[0], data.size(), *pdwEffect == DROPEFFECT_MOVE, hrRectangular == S_OK);
+ DropAt(movePos, putf.c_str(), putf.size(), *pdwEffect == DROPEFFECT_MOVE, isRectangular);
// Free data
if (medium.pUnkForRelease)
@@ -3135,36 +3096,17 @@ STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
/// Implement important part of IDataObject
STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
- const bool formatOK = (pFEIn->cfFormat == CF_TEXT) ||
- ((pFEIn->cfFormat == CF_UNICODETEXT) && IsUnicodeMode());
- if (!formatOK ||
- pFEIn->ptd != nullptr ||
- (pFEIn->dwAspect & DVASPECT_CONTENT) == 0 ||
- pFEIn->lindex != -1 ||
- (pFEIn->tymed & TYMED_HGLOBAL) == 0
- ) {
+ if (!SupportedFormat(pFEIn)) {
//Platform::DebugPrintf("DOB GetData No %d %x %x fmt=%x\n", lenDrag, pFEIn, pSTM, pFEIn->cfFormat);
return DATA_E_FORMATETC;
}
+
pSTM->tymed = TYMED_HGLOBAL;
//Platform::DebugPrintf("DOB GetData OK %d %x %x\n", lenDrag, pFEIn, pSTM);
- GlobalMemory text;
- if (pFEIn->cfFormat == CF_UNICODETEXT) {
- const std::string_view sv(drag.Data(), drag.LengthWithTerminator());
- const size_t uchars = UTF16Length(sv);
- text.Allocate(2 * uchars);
- if (text) {
- UTF16FromUTF8(sv,
- static_cast<wchar_t *>(text.ptr), uchars);
- }
- } else {
- text.Allocate(drag.LengthWithTerminator());
- if (text) {
- memcpy(text.ptr, drag.Data(), drag.LengthWithTerminator());
- }
- }
- pSTM->hGlobal = text ? text.Unlock() : 0;
+ GlobalMemory uniText;
+ CopyToGlobal(uniText, drag);
+ pSTM->hGlobal = uniText ? uniText.Unlock() : 0;
pSTM->pUnkForRelease = nullptr;
return S_OK;
}