diff options
Diffstat (limited to 'win32')
| -rw-r--r-- | win32/ScintillaWin.cxx | 93 | 
1 files changed, 87 insertions, 6 deletions
| diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index d0f99c532..a509ef0ec 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -197,6 +197,7 @@ class ScintillaWin :  	virtual void StartDrag();  	sptr_t WndPaint(uptr_t wParam);  	sptr_t HandleComposition(uptr_t wParam, sptr_t lParam); +	UINT CodePageOfDocument();  	virtual bool ValidCodePage(int codePage) const;  	virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);  	virtual bool SetIdle(bool on); @@ -215,6 +216,7 @@ class ScintillaWin :  	virtual int GetCtrlID();  	virtual void NotifyParent(SCNotification scn);  	virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt); +	virtual std::string CaseMapString(const std::string &s, int caseMapping);  	virtual void Copy();  	virtual void CopyAllowLine();  	virtual bool CanPaste(); @@ -587,6 +589,10 @@ static unsigned int SciMessageFromEM(unsigned int iMessage) {  }  static UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) { +	if (documentCodePage == SC_CP_UTF8) { +		// The system calls here are a little slow so avoid if known case. +		return SC_CP_UTF8; +	}  	CHARSETINFO ci = { 0, 0, { { 0, 0, 0, 0 }, { 0, 0 } } };  	BOOL bci = ::TranslateCharsetInfo((DWORD*)characterSet,  		&ci, TCI_SRCCHARSET); @@ -604,6 +610,10 @@ static UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) {  	return cp;  } +UINT ScintillaWin::CodePageOfDocument() { +	return CodePageFromCharSet(vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage); +} +  sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	try {  		//Platform::DebugPrintf("S M:%x WP:%x L:%x\n", iMessage, wParam, lParam); @@ -800,8 +810,7 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam  						UTF8FromUTF16(wcs, 1, utfval, len);  						AddCharUTF(utfval, len);  					} else { -						UINT cpDest = CodePageFromCharSet( -							vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage); +						UINT cpDest = CodePageOfDocument();  						char inBufferCP[20];  						int size = ::WideCharToMultiByte(cpDest,  							0, wcs, 1, inBufferCP, sizeof(inBufferCP) - 1, 0, 0); @@ -1289,6 +1298,80 @@ void ScintillaWin::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt)  			  MAKELPARAM(pt.x, pt.y));  } +std::string ScintillaWin::CaseMapString(const std::string &s, int caseMapping) { +	if (s.size() == 0) +		return std::string(); + +	if (caseMapping == cmSame) +		return s; + +	UINT cpDoc = CodePageOfDocument(); + +	unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, s.c_str(), s.size(), NULL, NULL); +	if (lengthUTF16 == 0)	// Failed to convert +		return s; + +	DWORD mapFlags = LCMAP_LINGUISTIC_CASING |  +		((caseMapping == cmUpper) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE); + +	// Many conversions performed by search function are short so optimize this case. +	enum { shortSize=20 }; + +	if (s.size() > shortSize) { +		// Use dynamic allocations for long strings + +		// Change text to UTF-16 +		std::vector<wchar_t> vwcText(lengthUTF16); +		::MultiByteToWideChar(cpDoc, 0, s.c_str(), s.size(), &vwcText[0], lengthUTF16); + +		// Change case +		int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, +			&vwcText[0], lengthUTF16, NULL, 0); +		std::vector<wchar_t> vwcConverted(charsConverted); +		::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,  +			&vwcText[0], lengthUTF16, &vwcConverted[0], charsConverted); + +		// Change back to document encoding +		unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0, +			&vwcConverted[0], vwcConverted.size(),  +			NULL, 0, NULL, 0); +		std::vector<char> vcConverted(lengthConverted); +		::WideCharToMultiByte(cpDoc, 0,  +			&vwcConverted[0], vwcConverted.size(),  +			&vcConverted[0], vcConverted.size(), NULL, 0); + +		return std::string(&vcConverted[0], vcConverted.size()); + +	} else { +		// Use static allocations for short strings as much faster +		// A factor of 15 for single character strings + +		// Change text to UTF-16 +		wchar_t vwcText[shortSize]; +		::MultiByteToWideChar(cpDoc, 0, s.c_str(), s.size(), vwcText, lengthUTF16); + +		// Change case +		int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, +			vwcText, lengthUTF16, NULL, 0); +		// Full mapping may produce up to 3 characters per input character +		wchar_t vwcConverted[shortSize*3]; +		::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, vwcText, lengthUTF16, +			vwcConverted, charsConverted); + +		// Change back to document encoding +		unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0, +			vwcConverted, charsConverted,  +			NULL, 0, NULL, 0); +		// Each UTF-16 code unit may need up to 3 bytes in UTF-8 +		char vcConverted[shortSize * 3 * 3]; +		::WideCharToMultiByte(cpDoc, 0,  +			vwcConverted, charsConverted,  +			vcConverted, lengthConverted, NULL, 0); + +		return std::string(vcConverted, lengthConverted); +	} +} +  void ScintillaWin::Copy() {  	//Platform::DebugPrintf("Copy\n");  	if (!sel.Empty()) { @@ -1409,8 +1492,7 @@ void ScintillaWin::Paste() {  			} else {  				// CF_UNICODETEXT available, but not in Unicode mode  				// Convert from Unicode to current Scintilla code page -				UINT cpDest = CodePageFromCharSet( -					vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage); +				UINT cpDest = CodePageOfDocument();  				len = ::WideCharToMultiByte(cpDest, 0, uptr, memUSelection.Size() / 2,  				                            NULL, 0, NULL, NULL) - 1; // subtract 0 terminator  				putf = new char[len + 1]; @@ -2237,8 +2319,7 @@ STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,  				// Default Scintilla behavior in Unicode mode  				// CF_UNICODETEXT available, but not in Unicode mode  				// Convert from Unicode to current Scintilla code page -				UINT cpDest = CodePageFromCharSet( -					vs.styles[STYLE_DEFAULT].characterSet, pdoc->dbcsCodePage); +				UINT cpDest = CodePageOfDocument();  				int tlen = ::WideCharToMultiByte(cpDest, 0, udata, -1,  					NULL, 0, NULL, NULL) - 1; // subtract 0 terminator  				data = new char[tlen + 1]; | 
