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;  } | 
