diff options
-rw-r--r-- | doc/ScintillaHistory.html | 6 | ||||
-rw-r--r-- | src/UniConversion.cxx | 4 | ||||
-rw-r--r-- | src/UniConversion.h | 4 | ||||
-rw-r--r-- | win32/ScintillaWin.cxx | 73 |
4 files changed, 58 insertions, 29 deletions
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index d554633db..1c7943845 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -478,6 +478,7 @@ <td>Jordan Jueckstock</td> </tr><tr> <td>Yury Dubinsky</td> + <td>Sam Hocevar</td> </tr> </table> <p> @@ -507,6 +508,11 @@ selection. </li> <li> + On Windows, fix non-BMP input through WM_CHAR and allow WM_UNICHAR to work + with non-BMP characters and on non-Unicode documents. + <a href="http://sourceforge.net/p/scintilla/bugs/1779/">Bug #1779</a>. + </li> + <li> On GTK+ on OS X, fix warning during destruction. <a href="http://sourceforge.net/p/scintilla/bugs/1777/">Bug #1777</a>. </li> diff --git a/src/UniConversion.cxx b/src/UniConversion.cxx index c12ca34c2..4da9e102a 100644 --- a/src/UniConversion.cxx +++ b/src/UniConversion.cxx @@ -19,10 +19,6 @@ using namespace Scintilla; namespace Scintilla { #endif -enum { SURROGATE_TRAIL_FIRST = 0xDC00 }; -enum { SURROGATE_TRAIL_LAST = 0xDFFF }; -enum { SUPPLEMENTAL_PLANE_FIRST = 0x10000 }; - unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) { unsigned int len = 0; for (unsigned int i = 0; i < tlen && uptr[i];) { diff --git a/src/UniConversion.h b/src/UniConversion.h index 08898cac3..aeb13f0c2 100644 --- a/src/UniConversion.h +++ b/src/UniConversion.h @@ -57,6 +57,10 @@ inline bool UTF8IsNEL(const unsigned char *us) { enum { SURROGATE_LEAD_FIRST = 0xD800 }; enum { SURROGATE_LEAD_LAST = 0xDBFF }; +enum { SURROGATE_TRAIL_FIRST = 0xDC00 }; +enum { SURROGATE_TRAIL_LAST = 0xDFFF }; +enum { SUPPLEMENTAL_PLANE_FIRST = 0x10000 }; + inline unsigned int UTF16CharLength(wchar_t uch) { return ((uch >= SURROGATE_LEAD_FIRST) && (uch <= SURROGATE_LEAD_LAST)) ? 2 : 1; } diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index d0ea62a31..92df2aad6 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -100,6 +100,14 @@ #define UNICODE_NOCHAR 0xFFFF #endif +#ifndef IS_HIGH_SURROGATE +#define IS_HIGH_SURROGATE(x) ((x) >= SURROGATE_LEAD_FIRST && (x) <= SURROGATE_LEAD_LAST) +#endif + +#ifndef IS_LOW_SURROGATE +#define IS_LOW_SURROGATE(x) ((x) >= SURROGATE_TRAIL_FIRST && (x) <= SURROGATE_TRAIL_LAST) +#endif + #ifndef MK_ALT #define MK_ALT 32 #endif @@ -212,6 +220,7 @@ class ScintillaWin : public ScintillaBase { bool lastKeyDownConsumed; + wchar_t lastHighSurrogateChar; bool capturedMouse; bool trackedMouseLeave; @@ -269,6 +278,7 @@ class ScintillaWin : virtual bool DragThreshold(Point ptStart, Point ptNow); virtual void StartDrag(); int TargetAsUTF8(char *text); + void AddCharUTF16(wchar_t const *wcs, unsigned int wclen); int EncodedFromUTF8(char *utf8, char *encoded) const; sptr_t WndPaint(uptr_t wParam); @@ -383,6 +393,7 @@ ATOM ScintillaWin::callClassAtom = 0; ScintillaWin::ScintillaWin(HWND hwnd) { lastKeyDownConsumed = false; + lastHighSurrogateChar = 0; capturedMouse = false; trackedMouseLeave = false; @@ -729,6 +740,26 @@ int ScintillaWin::EncodedFromUTF8(char *utf8, char *encoded) const { } } +// Add one character from a UTF-16 string, by converting to either UTF-8 or +// the current codepage. Code is similar to HandleCompositionWindowed(). +void ScintillaWin::AddCharUTF16(wchar_t const *wcs, unsigned int wclen) { + if (IsUnicodeMode()) { + char utfval[maxLenInputIME * 3]; + unsigned int len = UTF8Length(wcs, wclen); + UTF8FromUTF16(wcs, wclen, utfval, len); + utfval[len] = '\0'; + AddCharUTF(utfval, len); + } else { + UINT cpDest = CodePageOfDocument(); + char inBufferCP[maxLenInputIME * 2]; + int size = ::WideCharToMultiByte(cpDest, + 0, wcs, wclen, inBufferCP, sizeof(inBufferCP) - 1, 0, 0); + for (int i=0; i<size; i++) { + AddChar(inBufferCP[i]); + } + } +} + sptr_t ScintillaWin::WndPaint(uptr_t wParam) { //ElapsedTime et; @@ -1414,40 +1445,32 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam case WM_CHAR: if (((wParam >= 128) || !iscntrl(static_cast<int>(wParam))) || !lastKeyDownConsumed) { - wchar_t wcs[2] = {static_cast<wchar_t>(wParam), 0}; - if (IsUnicodeMode()) { - // For a wide character version of the window: - char utfval[UTF8MaxBytes]; - unsigned int len = UTF8Length(wcs, 1); - UTF8FromUTF16(wcs, 1, utfval, len); - AddCharUTF(utfval, len); - } else { - UINT cpDest = CodePageOfDocument(); - char inBufferCP[20]; - int size = ::WideCharToMultiByte(cpDest, - 0, wcs, 1, inBufferCP, sizeof(inBufferCP) - 1, 0, 0); - inBufferCP[size] = '\0'; - AddCharUTF(inBufferCP, size); + wchar_t wcs[3] = {static_cast<wchar_t>(wParam), 0}; + unsigned int wclen = 1; + if (IS_HIGH_SURROGATE(wcs[0])) { + // If this is a high surrogate character, we need a second one + lastHighSurrogateChar = wcs[0]; + return 0; + } else if (IS_LOW_SURROGATE(wcs[0])) { + wcs[1] = wcs[0]; + wcs[0] = lastHighSurrogateChar; + lastHighSurrogateChar = 0; + wclen = 2; } + AddCharUTF16(wcs, wclen); } return 0; case WM_UNICHAR: if (wParam == UNICODE_NOCHAR) { - return IsUnicodeMode() ? 1 : 0; + return TRUE; } else if (lastKeyDownConsumed) { return 1; } else { - if (IsUnicodeMode()) { - char utfval[UTF8MaxBytes]; - wchar_t wcs[2] = {static_cast<wchar_t>(wParam), 0}; - unsigned int len = UTF8Length(wcs, 1); - UTF8FromUTF16(wcs, 1, utfval, len); - AddCharUTF(utfval, len); - return 1; - } else { - return 0; - } + wchar_t wcs[3] = {0}; + unsigned int wclen = UTF16FromUTF32Character(wParam, wcs); + AddCharUTF16(wcs, wclen); + return FALSE; } case WM_SYSKEYDOWN: |