]> Pileus Git - ~andy/gtk/commitdiff
Add new keysyms from X11R6.4 (including EuroSign).
authorTor Lillqvist <tml@iki.fi>
Sun, 31 Oct 1999 21:35:39 +0000 (21:35 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Sun, 31 Oct 1999 21:35:39 +0000 (21:35 +0000)
1999-10-31  Tor Lillqvist  <tml@iki.fi>

* gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including
EuroSign).

* gdk/gdktypes.h: Add note about wchar_t not necessarily being the
same type as GdkWChar, especially on Win32.

* gdk/win32/*.c: Change gdk_root_parent to be a pointer.

* gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode
before passing to Windows GDI for drawing etc. Convert to the
system default codepage before passing to Windows as window
titles.

* gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to
support changing input locale on the fly.

* gdk/win32/gdkevent.c: Support input language (keyboard locale)
on-the-fly changes. Convert incoming characters from the current
codepage to Unicode (and then to a UTF-8 multi-byte string) based
on the current input language. Use keysym<->Unicode mapping tables
and functions borrowed from xterm sources.

Support IMEs (Input Method Editors) for CJK languages. On non-CJK
editions of Win9x, use the ActiveX-based Active IMM (Input Method
Manager) if available. IMEs and the Active IMM are available under
the disguise of Chinese, Korean and Japanese support for IE and
Outlook Express from "Windows Update" for Win98. On Win2k, the CJK
support is present in all editions (as long as you install it).

Call DispatchMessage from gdk_events_queue() (and thus
gdk_WindowProc()), instead of duplicating the code in
gdk_WindowProc().

Reworked the grab handling and propagation code, factored out
duplicated code snippets into separate functions. Other cleanups,
too.

* gdk/win32/surrogate-dimm.h: Provide just the bits we need from
the <dimm.h> header describing the Active IMM.

* gdk/win32/gdkfont.c: Pretend to support fontsets, but so far
just do the same as for "single" fonts.

* gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from
gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle
the new keysyms from gdkkeysyms.h.

* gtk/gtkfontsel.c (Win32): Load the font for the preview as a
fontset, so that gtkentry uses wide characters.

* gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call
GTk+'s system directory "gtk+", not "gtk".

45 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
README.win32
config.h.win32
gdk/gdkkeysyms.h
gdk/gdktypes.h
gdk/win32/gdk.c
gdk/win32/gdkconfig.h
gdk/win32/gdkdnd-win32.c
gdk/win32/gdkdnd.c
gdk/win32/gdkdraw.c
gdk/win32/gdkdrawable-win32.c
gdk/win32/gdkevents-win32.c
gdk/win32/gdkevents.c
gdk/win32/gdkfont-win32.c
gdk/win32/gdkfont.c
gdk/win32/gdkgc-win32.c
gdk/win32/gdkgc.c
gdk/win32/gdkglobals-win32.c
gdk/win32/gdkglobals.c
gdk/win32/gdkim-win32.c
gdk/win32/gdkim.c
gdk/win32/gdkinput-win32.c
gdk/win32/gdkinput.c
gdk/win32/gdkmain-win32.c
gdk/win32/gdkpixmap-win32.c
gdk/win32/gdkpixmap.c
gdk/win32/gdkprivate-win32.h
gdk/win32/gdkprivate.h
gdk/win32/gdkselection-win32.c
gdk/win32/gdkselection.c
gdk/win32/gdkwin32.h
gdk/win32/gdkwindow-win32.c
gdk/win32/gdkwindow.c
gdk/win32/gdkx.h
gdk/win32/makefile.cygwin
gdk/win32/surrogate-dimm.h [new file with mode: 0644]
gtk/gtkfontsel.c
gtk/gtkmain.c
gtk/gtkrc.c

index 75a65f2f94fa1804024f5f955126d96e5cd09baa..58777a85fc5b6aff67300308a8cdb0ca18573b75 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+1999-10-31  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including
+       EuroSign).
+
+       * gdk/gdktypes.h: Add note about wchar_t not necessarily being the
+       same type as GdkWChar, especially on Win32.
+
+       * gdk/win32/*.c: Change gdk_root_parent to be a pointer.
+
+       * gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode
+       before passing to Windows GDI for drawing etc. Convert to the
+       system default codepage before passing to Windows as window
+       titles.
+
+       * gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to
+       support changing input locale on the fly.
+
+       * gdk/win32/gdkevent.c: Support input language (keyboard locale)
+       on-the-fly changes. Convert incoming characters from the current
+       codepage to Unicode (and then to a UTF-8 multi-byte string) based
+       on the current input language. Use keysym<->Unicode mapping tables
+       and functions borrowed from xterm sources.
+
+       Support IMEs (Input Method Editors) for CJK languages. On non-CJK
+       editions of Win9x, use the ActiveX-based Active IMM (Input Method
+       Manager) if available. IMEs and the Active IMM are available under
+       the disguise of Chinese, Korean and Japanese support for IE and
+       Outlook Express from "Windows Update" for Win98. On Win2k, the CJK
+       support is present in all editions (as long as you install it).
+
+       Call DispatchMessage from gdk_events_queue() (and thus
+       gdk_WindowProc()), instead of duplicating the code in
+       gdk_WindowProc().
+
+       Reworked the grab handling and propagation code, factored out
+       duplicated code snippets into separate functions. Other cleanups,
+       too.
+
+       * gdk/win32/surrogate-dimm.h: Provide just the bits we need from
+       the <dimm.h> header describing the Active IMM.
+
+       * gdk/win32/gdkfont.c: Pretend to support fontsets, but so far
+       just do the same as for "single" fonts.
+
+       * gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from
+       gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle
+       the new keysyms from gdkkeysyms.h.
+
+       * gtk/gtkfontsel.c (Win32): Load the font for the preview as a
+       fontset, so that gtkentry uses wide characters.
+
+       * gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call
+       GTk+'s system directory "gtk+", not "gtk".
+
 Sat Oct 30 13:17:18 BST 1999 Tony Gale <gale@gtk.org>
 
        * docs/gtkfaq.sgml: FAQ update
index 75a65f2f94fa1804024f5f955126d96e5cd09baa..58777a85fc5b6aff67300308a8cdb0ca18573b75 100644 (file)
@@ -1,3 +1,58 @@
+1999-10-31  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including
+       EuroSign).
+
+       * gdk/gdktypes.h: Add note about wchar_t not necessarily being the
+       same type as GdkWChar, especially on Win32.
+
+       * gdk/win32/*.c: Change gdk_root_parent to be a pointer.
+
+       * gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode
+       before passing to Windows GDI for drawing etc. Convert to the
+       system default codepage before passing to Windows as window
+       titles.
+
+       * gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to
+       support changing input locale on the fly.
+
+       * gdk/win32/gdkevent.c: Support input language (keyboard locale)
+       on-the-fly changes. Convert incoming characters from the current
+       codepage to Unicode (and then to a UTF-8 multi-byte string) based
+       on the current input language. Use keysym<->Unicode mapping tables
+       and functions borrowed from xterm sources.
+
+       Support IMEs (Input Method Editors) for CJK languages. On non-CJK
+       editions of Win9x, use the ActiveX-based Active IMM (Input Method
+       Manager) if available. IMEs and the Active IMM are available under
+       the disguise of Chinese, Korean and Japanese support for IE and
+       Outlook Express from "Windows Update" for Win98. On Win2k, the CJK
+       support is present in all editions (as long as you install it).
+
+       Call DispatchMessage from gdk_events_queue() (and thus
+       gdk_WindowProc()), instead of duplicating the code in
+       gdk_WindowProc().
+
+       Reworked the grab handling and propagation code, factored out
+       duplicated code snippets into separate functions. Other cleanups,
+       too.
+
+       * gdk/win32/surrogate-dimm.h: Provide just the bits we need from
+       the <dimm.h> header describing the Active IMM.
+
+       * gdk/win32/gdkfont.c: Pretend to support fontsets, but so far
+       just do the same as for "single" fonts.
+
+       * gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from
+       gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle
+       the new keysyms from gdkkeysyms.h.
+
+       * gtk/gtkfontsel.c (Win32): Load the font for the preview as a
+       fontset, so that gtkentry uses wide characters.
+
+       * gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call
+       GTk+'s system directory "gtk+", not "gtk".
+
 Sat Oct 30 13:17:18 BST 1999 Tony Gale <gale@gtk.org>
 
        * docs/gtkfaq.sgml: FAQ update
index 75a65f2f94fa1804024f5f955126d96e5cd09baa..58777a85fc5b6aff67300308a8cdb0ca18573b75 100644 (file)
@@ -1,3 +1,58 @@
+1999-10-31  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including
+       EuroSign).
+
+       * gdk/gdktypes.h: Add note about wchar_t not necessarily being the
+       same type as GdkWChar, especially on Win32.
+
+       * gdk/win32/*.c: Change gdk_root_parent to be a pointer.
+
+       * gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode
+       before passing to Windows GDI for drawing etc. Convert to the
+       system default codepage before passing to Windows as window
+       titles.
+
+       * gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to
+       support changing input locale on the fly.
+
+       * gdk/win32/gdkevent.c: Support input language (keyboard locale)
+       on-the-fly changes. Convert incoming characters from the current
+       codepage to Unicode (and then to a UTF-8 multi-byte string) based
+       on the current input language. Use keysym<->Unicode mapping tables
+       and functions borrowed from xterm sources.
+
+       Support IMEs (Input Method Editors) for CJK languages. On non-CJK
+       editions of Win9x, use the ActiveX-based Active IMM (Input Method
+       Manager) if available. IMEs and the Active IMM are available under
+       the disguise of Chinese, Korean and Japanese support for IE and
+       Outlook Express from "Windows Update" for Win98. On Win2k, the CJK
+       support is present in all editions (as long as you install it).
+
+       Call DispatchMessage from gdk_events_queue() (and thus
+       gdk_WindowProc()), instead of duplicating the code in
+       gdk_WindowProc().
+
+       Reworked the grab handling and propagation code, factored out
+       duplicated code snippets into separate functions. Other cleanups,
+       too.
+
+       * gdk/win32/surrogate-dimm.h: Provide just the bits we need from
+       the <dimm.h> header describing the Active IMM.
+
+       * gdk/win32/gdkfont.c: Pretend to support fontsets, but so far
+       just do the same as for "single" fonts.
+
+       * gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from
+       gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle
+       the new keysyms from gdkkeysyms.h.
+
+       * gtk/gtkfontsel.c (Win32): Load the font for the preview as a
+       fontset, so that gtkentry uses wide characters.
+
+       * gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call
+       GTk+'s system directory "gtk+", not "gtk".
+
 Sat Oct 30 13:17:18 BST 1999 Tony Gale <gale@gtk.org>
 
        * docs/gtkfaq.sgml: FAQ update
index 75a65f2f94fa1804024f5f955126d96e5cd09baa..58777a85fc5b6aff67300308a8cdb0ca18573b75 100644 (file)
@@ -1,3 +1,58 @@
+1999-10-31  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including
+       EuroSign).
+
+       * gdk/gdktypes.h: Add note about wchar_t not necessarily being the
+       same type as GdkWChar, especially on Win32.
+
+       * gdk/win32/*.c: Change gdk_root_parent to be a pointer.
+
+       * gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode
+       before passing to Windows GDI for drawing etc. Convert to the
+       system default codepage before passing to Windows as window
+       titles.
+
+       * gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to
+       support changing input locale on the fly.
+
+       * gdk/win32/gdkevent.c: Support input language (keyboard locale)
+       on-the-fly changes. Convert incoming characters from the current
+       codepage to Unicode (and then to a UTF-8 multi-byte string) based
+       on the current input language. Use keysym<->Unicode mapping tables
+       and functions borrowed from xterm sources.
+
+       Support IMEs (Input Method Editors) for CJK languages. On non-CJK
+       editions of Win9x, use the ActiveX-based Active IMM (Input Method
+       Manager) if available. IMEs and the Active IMM are available under
+       the disguise of Chinese, Korean and Japanese support for IE and
+       Outlook Express from "Windows Update" for Win98. On Win2k, the CJK
+       support is present in all editions (as long as you install it).
+
+       Call DispatchMessage from gdk_events_queue() (and thus
+       gdk_WindowProc()), instead of duplicating the code in
+       gdk_WindowProc().
+
+       Reworked the grab handling and propagation code, factored out
+       duplicated code snippets into separate functions. Other cleanups,
+       too.
+
+       * gdk/win32/surrogate-dimm.h: Provide just the bits we need from
+       the <dimm.h> header describing the Active IMM.
+
+       * gdk/win32/gdkfont.c: Pretend to support fontsets, but so far
+       just do the same as for "single" fonts.
+
+       * gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from
+       gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle
+       the new keysyms from gdkkeysyms.h.
+
+       * gtk/gtkfontsel.c (Win32): Load the font for the preview as a
+       fontset, so that gtkentry uses wide characters.
+
+       * gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call
+       GTk+'s system directory "gtk+", not "gtk".
+
 Sat Oct 30 13:17:18 BST 1999 Tony Gale <gale@gtk.org>
 
        * docs/gtkfaq.sgml: FAQ update
index 75a65f2f94fa1804024f5f955126d96e5cd09baa..58777a85fc5b6aff67300308a8cdb0ca18573b75 100644 (file)
@@ -1,3 +1,58 @@
+1999-10-31  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including
+       EuroSign).
+
+       * gdk/gdktypes.h: Add note about wchar_t not necessarily being the
+       same type as GdkWChar, especially on Win32.
+
+       * gdk/win32/*.c: Change gdk_root_parent to be a pointer.
+
+       * gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode
+       before passing to Windows GDI for drawing etc. Convert to the
+       system default codepage before passing to Windows as window
+       titles.
+
+       * gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to
+       support changing input locale on the fly.
+
+       * gdk/win32/gdkevent.c: Support input language (keyboard locale)
+       on-the-fly changes. Convert incoming characters from the current
+       codepage to Unicode (and then to a UTF-8 multi-byte string) based
+       on the current input language. Use keysym<->Unicode mapping tables
+       and functions borrowed from xterm sources.
+
+       Support IMEs (Input Method Editors) for CJK languages. On non-CJK
+       editions of Win9x, use the ActiveX-based Active IMM (Input Method
+       Manager) if available. IMEs and the Active IMM are available under
+       the disguise of Chinese, Korean and Japanese support for IE and
+       Outlook Express from "Windows Update" for Win98. On Win2k, the CJK
+       support is present in all editions (as long as you install it).
+
+       Call DispatchMessage from gdk_events_queue() (and thus
+       gdk_WindowProc()), instead of duplicating the code in
+       gdk_WindowProc().
+
+       Reworked the grab handling and propagation code, factored out
+       duplicated code snippets into separate functions. Other cleanups,
+       too.
+
+       * gdk/win32/surrogate-dimm.h: Provide just the bits we need from
+       the <dimm.h> header describing the Active IMM.
+
+       * gdk/win32/gdkfont.c: Pretend to support fontsets, but so far
+       just do the same as for "single" fonts.
+
+       * gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from
+       gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle
+       the new keysyms from gdkkeysyms.h.
+
+       * gtk/gtkfontsel.c (Win32): Load the font for the preview as a
+       fontset, so that gtkentry uses wide characters.
+
+       * gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call
+       GTk+'s system directory "gtk+", not "gtk".
+
 Sat Oct 30 13:17:18 BST 1999 Tony Gale <gale@gtk.org>
 
        * docs/gtkfaq.sgml: FAQ update
index 75a65f2f94fa1804024f5f955126d96e5cd09baa..58777a85fc5b6aff67300308a8cdb0ca18573b75 100644 (file)
@@ -1,3 +1,58 @@
+1999-10-31  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including
+       EuroSign).
+
+       * gdk/gdktypes.h: Add note about wchar_t not necessarily being the
+       same type as GdkWChar, especially on Win32.
+
+       * gdk/win32/*.c: Change gdk_root_parent to be a pointer.
+
+       * gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode
+       before passing to Windows GDI for drawing etc. Convert to the
+       system default codepage before passing to Windows as window
+       titles.
+
+       * gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to
+       support changing input locale on the fly.
+
+       * gdk/win32/gdkevent.c: Support input language (keyboard locale)
+       on-the-fly changes. Convert incoming characters from the current
+       codepage to Unicode (and then to a UTF-8 multi-byte string) based
+       on the current input language. Use keysym<->Unicode mapping tables
+       and functions borrowed from xterm sources.
+
+       Support IMEs (Input Method Editors) for CJK languages. On non-CJK
+       editions of Win9x, use the ActiveX-based Active IMM (Input Method
+       Manager) if available. IMEs and the Active IMM are available under
+       the disguise of Chinese, Korean and Japanese support for IE and
+       Outlook Express from "Windows Update" for Win98. On Win2k, the CJK
+       support is present in all editions (as long as you install it).
+
+       Call DispatchMessage from gdk_events_queue() (and thus
+       gdk_WindowProc()), instead of duplicating the code in
+       gdk_WindowProc().
+
+       Reworked the grab handling and propagation code, factored out
+       duplicated code snippets into separate functions. Other cleanups,
+       too.
+
+       * gdk/win32/surrogate-dimm.h: Provide just the bits we need from
+       the <dimm.h> header describing the Active IMM.
+
+       * gdk/win32/gdkfont.c: Pretend to support fontsets, but so far
+       just do the same as for "single" fonts.
+
+       * gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from
+       gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle
+       the new keysyms from gdkkeysyms.h.
+
+       * gtk/gtkfontsel.c (Win32): Load the font for the preview as a
+       fontset, so that gtkentry uses wide characters.
+
+       * gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call
+       GTk+'s system directory "gtk+", not "gtk".
+
 Sat Oct 30 13:17:18 BST 1999 Tony Gale <gale@gtk.org>
 
        * docs/gtkfaq.sgml: FAQ update
index 75a65f2f94fa1804024f5f955126d96e5cd09baa..58777a85fc5b6aff67300308a8cdb0ca18573b75 100644 (file)
@@ -1,3 +1,58 @@
+1999-10-31  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/gdkkeysyms.h: Add new keysyms from X11R6.4 (including
+       EuroSign).
+
+       * gdk/gdktypes.h: Add note about wchar_t not necessarily being the
+       same type as GdkWChar, especially on Win32.
+
+       * gdk/win32/*.c: Change gdk_root_parent to be a pointer.
+
+       * gdk/win32/*.c: Assume all strings are UTF-8. Convert to Unicode
+       before passing to Windows GDI for drawing etc. Convert to the
+       system default codepage before passing to Windows as window
+       titles.
+
+       * gdk/win32/gdkprivate.h: Add more fields to GdkWindowPrivate to
+       support changing input locale on the fly.
+
+       * gdk/win32/gdkevent.c: Support input language (keyboard locale)
+       on-the-fly changes. Convert incoming characters from the current
+       codepage to Unicode (and then to a UTF-8 multi-byte string) based
+       on the current input language. Use keysym<->Unicode mapping tables
+       and functions borrowed from xterm sources.
+
+       Support IMEs (Input Method Editors) for CJK languages. On non-CJK
+       editions of Win9x, use the ActiveX-based Active IMM (Input Method
+       Manager) if available. IMEs and the Active IMM are available under
+       the disguise of Chinese, Korean and Japanese support for IE and
+       Outlook Express from "Windows Update" for Win98. On Win2k, the CJK
+       support is present in all editions (as long as you install it).
+
+       Call DispatchMessage from gdk_events_queue() (and thus
+       gdk_WindowProc()), instead of duplicating the code in
+       gdk_WindowProc().
+
+       Reworked the grab handling and propagation code, factored out
+       duplicated code snippets into separate functions. Other cleanups,
+       too.
+
+       * gdk/win32/surrogate-dimm.h: Provide just the bits we need from
+       the <dimm.h> header describing the Active IMM.
+
+       * gdk/win32/gdkfont.c: Pretend to support fontsets, but so far
+       just do the same as for "single" fonts.
+
+       * gdk/win32/gdk.c: Call CoInitialize() (COM initialisation) from
+       gdk_init_check, and CoUninitialize() from gdk_exit_func. Handle
+       the new keysyms from gdkkeysyms.h.
+
+       * gtk/gtkfontsel.c (Win32): Load the font for the preview as a
+       fontset, so that gtkentry uses wide characters.
+
+       * gtk/gtkrc.c (Win32): Get the locale with gwin_getlocale(). Call
+       GTk+'s system directory "gtk+", not "gtk".
+
 Sat Oct 30 13:17:18 BST 1999 Tony Gale <gale@gtk.org>
 
        * docs/gtkfaq.sgml: FAQ update
index e085036c7b1e00e900ddc73d595b7328ba3d2a1f..9dec77d994d8615f8947cd8cc82b03eeae51afe2 100644 (file)
@@ -3,29 +3,31 @@ correct as the Unix/X11 version. For more information about the Win32
 port, see http://www.gimp.org/tml/gimp/win32/ or
 http://www.iki.fi/tml/gimp/win32/ .
 
-To build GTk+ on Win32, you need either Microsoft compiler and tools,
-or gcc-2.95 or later running under cygwin-b20.1. Compile in gdk\win32
-and gtk with `nmake -f makefile.msc` or `make -f
-makefile.cygwin`. Before doing a install, check the BIN definition in
-gdk\win32\makefile.msc (or makefile.cygwin) and gtk\makefile.msc (or
-makefile.cygwin).
+To build GTk+ on Win32, you need either the Microsoft compiler and
+tools, or gcc-2.95 or later running under cygwin-b20.1 or
+later. Compile in gdk\win32 and gtk with `nmake -f makefile.msc` or
+`make -f makefile.cygwin`. Before doing a install, check the BIN
+definition in gdk\win32\makefile.msc (or makefile.cygwin) and
+gtk\makefile.msc (or makefile.cygwin).
 
 See the README.win32 file in the GLib distribution for instructions
 how to build with gcc.
 
 The tablet support uses the Wintab API. The Wintab development kit can
 be downloaded from http://www.pointing.com. If you don't care for
-that, undefine HAVE_WINTAB in config.h.win32 before building.
+that, undefine HAVE_WINTAB in config.h.win32 and remove references to
+the wntab32x library from the makefile before building.
 
 GTk+ wants to be built with the GNU "intl" library for
 internationalisation (i18n). Get the version ported to Win32 (not a
 very big deal) from tml's web site mentioned above. We build the
-"intl" library to a DLL called gnu-intl.dll to reduce name clash
-risks. If you don't want any i18n stuff, undefine ENABLE_NLS,
-HAVE_GETTEXT and HAVE_LIBINTL in the config.h.win32 file, and remove
-references to the gnu-intl library from the makefiles.
+"intl" library as a DLL called gnu-intl.dll (the "gnu" prefix is used
+to reduce name clash risks). If you don't want any i18n stuff,
+undefine ENABLE_NLS, HAVE_GETTEXT and HAVE_LIBINTL in the
+config.h.win32 file, and remove references to the gnu-intl library
+from the makefiles.
 
 Note that while the GNU gettext package is under the GPL, the "intl"
-library part as distributed with GNU libc is under the LGPL (like GTk+
+part of it as distributed with GNU libc is under the LGPL (like GTk+
 or GLib). We want the LGPL one, even if they are the same, more or
 less.
index eb6e053c4c9e323843c8d950a6508460bff361e5..a4483282bbbf71867f2b7374d1b6180d4279cf8f 100755 (executable)
@@ -1,4 +1,4 @@
-/* config.h.win32.  Handcrafted for Microsoft C */
+/* config.h.win32.  Handcrafted for Microsoft C and gcc -mno-cygwin */
 
 #if ! (defined(_MSC_VER) || defined(__GNUC__))
 #error Unrecognized Win32 compiler, edit config.h.win32 by hand
 
 /* Define if you have the Wintab programmer's kit */
 #define HAVE_WINTAB 1
+
+/* Define if you have the <dimm.h> header file
+ * (available in the Platform SDK)
+*/
+#ifdef _MSC_VER
+#define HAVE_DIMM_H 1
+#endif
index cc3ed517e6ce5b32c188136586526f1b62a159b5..56798d4e6cf03d03e96de664150f055e104bb26a 100644 (file)
@@ -10,6 +10,7 @@
 #define GDK_Escape 0xFF1B
 #define GDK_Delete 0xFFFF
 #define GDK_Multi_key 0xFF20
+#define GDK_Codeinput 0xFF37
 #define GDK_SingleCandidate 0xFF3C
 #define GDK_MultipleCandidate 0xFF3D
 #define GDK_PreviousCandidate 0xFF3E
@@ -30,6 +31,7 @@
 #define GDK_Kana_Shift 0xFF2E
 #define GDK_Eisu_Shift 0xFF2F
 #define GDK_Eisu_toggle 0xFF30
+#define GDK_Kanji_Bangou 0xFF37
 #define GDK_Zen_Koho 0xFF3D
 #define GDK_Mae_Koho 0xFF3E
 #define GDK_Home 0xFF50
 #define GDK_uogonek 0x3f9
 #define GDK_utilde 0x3fd
 #define GDK_umacron 0x3fe
+#define GDK_OE 0x13bc
+#define GDK_oe 0x13bd
+#define GDK_Ydiaeresis 0x13be
 #define GDK_overline 0x47e
 #define GDK_kana_fullstop 0x4a1
 #define GDK_kana_openingbracket 0x4a2
 #define GDK_Hangul_J_KkogjiDalrinIeung 0xef9
 #define GDK_Hangul_J_YeorinHieuh 0xefa
 #define GDK_Korean_Won 0xeff
+#define GDK_EcuSign 0x20a0
+#define GDK_ColonSign 0x20a1
+#define GDK_CruzeiroSign 0x20a2
+#define GDK_FFrancSign 0x20a3
+#define GDK_LiraSign 0x20a4
+#define GDK_MillSign 0x20a5
+#define GDK_NairaSign 0x20a6
+#define GDK_PesetaSign 0x20a7
+#define GDK_RupeeSign 0x20a8
+#define GDK_WonSign 0x20a9
+#define GDK_NewSheqelSign 0x20aa
+#define GDK_DongSign 0x20ab
+#define GDK_EuroSign 0x20ac
index d96f07386f8a5b030bd4eea1bd5439cf17cf3db0..de5d6ac8a9a19827c06658b76783a4452d371784 100644 (file)
@@ -68,6 +68,11 @@ typedef struct _GdkPoint           GdkPoint;
 typedef struct _GdkRectangle         GdkRectangle;
 typedef struct _GdkSegment           GdkSegment;
 
+/*
+ * Note that on some platforms the wchar_t type
+ * is not the same as GdkWChar. For instance
+ * on Win32, wchar_t is unsigned short.
+ */
 typedef guint32                            GdkWChar;
 typedef gulong                     GdkAtom;
  
index 5a44835c5d0da9cb65796e4be903530874f98eff..9e5cb9f0cabb2f6dea1bdc292df2e1b03e719241 100644 (file)
 #include "gdkinputprivate.h"
 #include "gdkkeysyms.h"
 
+#include <objbase.h>
+
 static void     gdkx_XConvertCase      (KeySym        symbol,
                                         KeySym       *lower,
                                         KeySym       *upper);
-#define XConvertCase gdkx_XConvertCase
-
 static void        gdk_exit_func                (void);
 
 
@@ -234,6 +234,9 @@ gdk_init_check (int    *argc,
   
   gdk_ProgInstance = GetModuleHandle (NULL);
   gdk_DC = CreateDC ("DISPLAY", NULL, NULL, NULL);
+  gdk_root_window = GetDesktopWindow ();
+
+  CoInitialize (NULL);
 
   gdk_selection_request_msg = RegisterWindowMessage ("gdk-selection-request");
   gdk_selection_notify_msg = RegisterWindowMessage ("gdk-selection-notify");
@@ -247,8 +250,6 @@ gdk_init_check (int    *argc,
   gdk_progclass = g_basename (g_get_prgname ());
   gdk_progclass[0] = toupper (gdk_progclass[0]);
 
-  gdk_root_window = HWND_DESKTOP;
-
   g_atexit (gdk_exit_func);
   
   gdk_events_init ();
@@ -333,7 +334,7 @@ gdk_screen_width (void)
 {
   gint return_val;
   
-  return_val = gdk_root_parent.drawable.width;
+  return_val = gdk_root_parent->drawable.width;
 
   return return_val;
 }
@@ -358,7 +359,7 @@ gdk_screen_height (void)
 {
   gint return_val;
   
-  return_val = gdk_root_parent.drawable.height;
+  return_val = gdk_root_parent->drawable.height;
 
   return return_val;
 }
@@ -498,6 +499,9 @@ gdk_exit_func (void)
       gdk_input_exit ();
       gdk_key_repeat_restore ();
       gdk_dnd_exit ();
+
+      CoUninitialize ();
+
       DeleteDC (gdk_DC);
       gdk_DC = NULL;
       gdk_initialized = 0;
@@ -1670,6 +1674,22 @@ static struct gdk_key {
   { 0x000ef9, "Hangul_J_KkogjiDalrinIeung" },
   { 0x000efa, "Hangul_J_YeorinHieuh" },
   { 0x000eff, "Korean_Won" },
+  { 0x0013bc, "OE" },
+  { 0x0013bd, "oe" },
+  { 0x0013be, "Ydiaeresis" },
+  { 0x0020a0, "EcuSign" },
+  { 0x0020a1, "ColonSign" },
+  { 0x0020a2, "CruzeiroSign" },
+  { 0x0020a3, "FFrancSign" },
+  { 0x0020a4, "LiraSign" },
+  { 0x0020a5, "MillSign" },
+  { 0x0020a6, "NairaSign" },
+  { 0x0020a7, "PesetaSign" },
+  { 0x0020a8, "RupeeSign" },
+  { 0x0020a9, "WonSign" },
+  { 0x0020aa, "NewSheqelSign" },
+  { 0x0020ab, "DongSign" },
+  { 0x0020ac, "EuroSign" },
   { 0x00fd01, "3270_Duplicate" },
   { 0x00fd02, "3270_FieldMark" },
   { 0x00fd03, "3270_Right2" },
@@ -1826,11 +1846,21 @@ static struct gdk_key {
   { 0x00ff2e, "Kana_Shift" },
   { 0x00ff2f, "Eisu_Shift" },
   { 0x00ff30, "Eisu_toggle" },
+  { 0x00ff31, "Hangul" },
+  { 0x00ff32, "Hangul_Start" },
+  { 0x00ff33, "Hangul_End" },
+  { 0x00ff34, "Hangul_Hanja" },
+  { 0x00ff35, "Hangul_Jamo" },
+  { 0x00ff36, "Hangul_Romaja" },
+  { 0x00ff37, "Codeinput" },
+  { 0x00ff38, "Hangul_Jeonja" },
+  { 0x00ff39, "Hangul_Banja" },
+  { 0x00ff3a, "Hangul_PreHanja" },
+  { 0x00ff3b, "Hangul_PostHanja" },
   { 0x00ff3c, "SingleCandidate" },
   { 0x00ff3d, "MultipleCandidate" },
-  { 0x00ff3d, "Zen_Koho" },
-  { 0x00ff3e, "Mae_Koho" },
   { 0x00ff3e, "PreviousCandidate" },
+  { 0x00ff3f, "Hangul_Special" },
   { 0x00ff50, "Home" },
   { 0x00ff51, "Left" },
   { 0x00ff52, "Up" },
@@ -1949,21 +1979,6 @@ static struct gdk_key {
   { 0x00ffed, "Hyper_L" },
   { 0x00ffee, "Hyper_R" },
   { 0x00ffff, "Delete" },
-  { 0x00ff31, "Hangul" },
-  { 0x00ff32, "Hangul_Start" },
-  { 0x00ff33, "Hangul_End" },
-  { 0x00ff34, "Hangul_Hanja" },
-  { 0x00ff35, "Hangul_Jamo" },
-  { 0x00ff36, "Hangul_Romaja" },
-  { 0x00ff37, "Hangul_Codeinput" },
-  { 0x00ff38, "Hangul_Jeonja" },
-  { 0x00ff39, "Hangul_Banja" },
-  { 0x00ff3a, "Hangul_PreHanja" },
-  { 0x00ff3b, "Hangul_PostHanja" },
-  { 0x00ff3c, "Hangul_SingleCandidate" },
-  { 0x00ff3d, "Hangul_MultipleCandidate" },
-  { 0x00ff3e, "Hangul_PreviousCandidate" },
-  { 0x00ff3f, "Hangul_Special" },
   { 0xffffff, "VoidSymbol" },
 };
 
@@ -1985,7 +2000,7 @@ gdk_keyval_name (guint          keyval)
             GDK_NUM_KEYS, sizeof (struct gdk_key),
             gdk_keys_keyval_compare);
   if (found != NULL)
-    return found->name;
+    return (gchar *) found->name;
   else
     return NULL;
 }
@@ -2037,7 +2052,7 @@ gdk_keyval_to_upper (guint          keyval)
       KeySym lower_val = 0;
       KeySym upper_val = 0;
       
-      XConvertCase (keyval, &lower_val, &upper_val);
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
       return upper_val;
     }
   return 0;
@@ -2051,7 +2066,7 @@ gdk_keyval_to_lower (guint          keyval)
       KeySym lower_val = 0;
       KeySym upper_val = 0;
       
-      XConvertCase (keyval, &lower_val, &upper_val);
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
       return lower_val;
     }
   return 0;
@@ -2065,7 +2080,7 @@ gdk_keyval_is_upper (guint          keyval)
       KeySym lower_val = 0;
       KeySym upper_val = 0;
       
-      XConvertCase (keyval, &lower_val, &upper_val);
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
       return upper_val == keyval;
     }
   return TRUE;
@@ -2079,7 +2094,7 @@ gdk_keyval_is_lower (guint        keyval)
       KeySym lower_val = 0;
       KeySym upper_val = 0;
       
-      XConvertCase (keyval, &lower_val, &upper_val);
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
       return lower_val == keyval;
     }
   return TRUE;
index ee334e28d5d810da4364b96c50921a5be2a26d69..2fd8ca1b3c0714c9c22ff61532808466261786f6 100644 (file)
@@ -5,3 +5,4 @@
 #ifdef _MSC_VER
 #define GDK_HAVE_WCTYPE_H 1
 #endif
+#define GDK_USE_UTF8_MBS 1
index 5a220c6423315d695f4c32582f273bac0dd27449..1c7f42a99db5a73da0d6cb5732db63063a4d3276 100644 (file)
@@ -38,6 +38,8 @@
 
 #ifdef OLE2_DND
 #include <ole2.h>
+#else
+#include <objbase.h>
 #endif
 
 #ifdef _MSC_VER                        /* These aren't in mingw32 */
@@ -596,7 +598,7 @@ gdk_dropfiles_filter (GdkXEvent *xev,
       private = (GdkDragContextPrivate *) context;
       context->protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
       context->is_source = FALSE;
-      context->source_window = (GdkWindow *) &gdk_root_parent;
+      context->source_window = (GdkWindow *) gdk_root_parent;
       context->dest_window = event->any.window;
       gdk_window_ref (context->dest_window);
       /* WM_DROPFILES drops are always file names */
@@ -638,7 +640,7 @@ gdk_dropfiles_filter (GdkXEvent *xev,
            }
          g_string_append (result, "\015\012");
        }
-      gdk_sel_prop_store ((GdkWindow *) &gdk_root_parent,
+      gdk_sel_prop_store ((GdkWindow *) gdk_root_parent,
                          text_uri_list_atom, 8, result->str, result->len + 1);
 
       DragFinish (hdrop);
index 5a220c6423315d695f4c32582f273bac0dd27449..1c7f42a99db5a73da0d6cb5732db63063a4d3276 100644 (file)
@@ -38,6 +38,8 @@
 
 #ifdef OLE2_DND
 #include <ole2.h>
+#else
+#include <objbase.h>
 #endif
 
 #ifdef _MSC_VER                        /* These aren't in mingw32 */
@@ -596,7 +598,7 @@ gdk_dropfiles_filter (GdkXEvent *xev,
       private = (GdkDragContextPrivate *) context;
       context->protocol = GDK_DRAG_PROTO_WIN32_DROPFILES;
       context->is_source = FALSE;
-      context->source_window = (GdkWindow *) &gdk_root_parent;
+      context->source_window = (GdkWindow *) gdk_root_parent;
       context->dest_window = event->any.window;
       gdk_window_ref (context->dest_window);
       /* WM_DROPFILES drops are always file names */
@@ -638,7 +640,7 @@ gdk_dropfiles_filter (GdkXEvent *xev,
            }
          g_string_append (result, "\015\012");
        }
-      gdk_sel_prop_store ((GdkWindow *) &gdk_root_parent,
+      gdk_sel_prop_store ((GdkWindow *) gdk_root_parent,
                          text_uri_list_atom, 8, result->str, result->len + 1);
 
       DragFinish (hdrop);
index 593c98cd80a9f21bfb73c72399829191834a1a2b..85ca076ccecdbc980b983f1399bd0fbd8e69dcf9 100644 (file)
@@ -469,47 +469,35 @@ gdk_draw_text (GdkDrawable *drawable,
   if (text_length == 0)
     return;
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
   font_private = (GdkFontPrivate*) font;
 
-  if (font->type == GDK_FONT_FONT)
-    {
-      hdc = gdk_gc_predraw (drawable_private, gc_private);
-      xfont = (HFONT) font_private->xfont;
-
-      GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
-                              "+%d+%d font: %#x \"%.*s\" length: %d\n",
-                              drawable_private->xwindow,
-                              gc_private, gc_private->xgc,
-                              x, y, xfont,
-                              (text_length > 10 ? 10 : text_length),
-                              text, text_length));
-      
-      if ((oldfont = SelectObject (hdc, xfont)) == NULL)
-       g_warning ("gdk_draw_text: SelectObject failed");
-      if (font_private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
-                                          text, text_length,
-                                          wcstr, text_length)) == 0)
-           g_warning ("gdk_draw_text: MultiByteToWideChar failed");
-         else if (!TextOutW (hdc, x, y, wcstr, wlen))
-           g_warning ("gdk_draw_text: TextOutW failed");
-         g_free (wcstr);
-       }
-      else
-       {
-         if (!TextOutA (hdc, x, y, text, text_length))
-           g_warning ("gdk_draw_text: TextOutA failed");
-       }
-      if (oldfont != NULL)
-       SelectObject (hdc, oldfont);
-      gdk_gc_postdraw (drawable_private, gc_private);
-    }
-  else
-    g_error ("undefined font type");
+  hdc = gdk_gc_predraw (drawable_private, gc_private);
+  xfont = (HFONT) font_private->xfont;
+
+  GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
+                          "+%d+%d font: %#x \"%.*s\" length: %d\n",
+                          drawable_private->xwindow,
+                          gc_private, gc_private->xgc,
+                          x, y, xfont,
+                          (text_length > 10 ? 10 : text_length),
+                          text, text_length));
+  
+  if ((oldfont = SelectObject (hdc, xfont)) == NULL)
+    g_warning ("gdk_draw_text: SelectObject failed");
+
+  wcstr = g_new (wchar_t, text_length);
+  if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
+    g_warning ("gdk_draw_text: gdk_nmbstowchar_ts failed");
+  else if (!TextOutW (hdc, x, y, wcstr, wlen))
+    g_warning ("gdk_draw_text: TextOutW failed");
+  g_free (wcstr);
+  if (oldfont != NULL)
+    SelectObject (hdc, oldfont);
+  gdk_gc_postdraw (drawable_private, gc_private);
 }
 
 void
@@ -521,6 +509,8 @@ gdk_draw_text_wc (GdkDrawable        *drawable,
                  const GdkWChar *text,
                  gint            text_length)
 {
+  HDC hdc;
+  HGDIOBJ oldfont;
   GdkDrawablePrivate *drawable_private;
   GdkFontPrivate *font_private;
   GdkGCPrivate *gc_private;
@@ -539,68 +529,40 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
   if (text_length == 0)
     return;
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
   font_private = (GdkFontPrivate*) font;
 
-  if (font->type == GDK_FONT_FONT)
-    {
-      HDC hdc;
-      HFONT xfont;
-      HGDIOBJ oldfont;
+  hdc = gdk_gc_predraw (drawable_private, gc_private);
 
-      hdc = gdk_gc_predraw (drawable_private, gc_private);
-      xfont = (HFONT) font_private->xfont;
-
-      GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
-                              "+%d+%d font: %#x length: %d\n",
-                              drawable_private->xwindow,
-                              gc_private, gc_private->xgc,
-                              x, y, xfont,
-                              text_length));
+  GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
+                          "+%d+%d font: %#x length: %d\n",
+                          drawable_private->xwindow,
+                          gc_private, gc_private->xgc,
+                          x, y, font_private->xfont,
+                          text_length));
       
-      if ((oldfont = SelectObject (hdc, xfont)) == NULL)
-         g_warning ("gdk_draw_text_wc: SelectObject failed");
-#if 0 /* No. Don't use TextOutW directly. Compare to the X11 version,
-       * it uses plain XDrawString for GDK_FONT_FONT fonts, too.
-       * TextOutW by definition interprets the string as Unicode.
-       * We don't have that, but either chars from some single-byte codepage
-       * or from a DBCS.
-       */
+  if ((oldfont = SelectObject (hdc, font_private->xfont)) == NULL)
+    g_warning ("gdk_draw_text_wc: SelectObject failed");
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
+    {
       wcstr = g_new (wchar_t, text_length);
       for (i = 0; i < text_length; i++)
        wcstr[i] = text[i];
-      if (!TextOutW (hdc, x, y, wcstr, text_length))
-       g_warning ("gdk_draw_text_wc: TextOutW failed");
-      g_free (wcstr);
-#else
-      str = g_new (guchar, text_length);
-      for (i = 0; i < text_length; i++)
-       str[i] = text[i];
-      if (font_private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
-                                          str, text_length,
-                                          wcstr, text_length)) == 0)
-           g_warning ("gdk_draw_text: MultiByteToWideChar failed");
-         else if (!TextOutW (hdc, x, y, wcstr, wlen))
-           g_warning ("gdk_draw_text_wc: TextOutW failed");
-         g_free (wcstr);
-       }
-      else
-       {
-         if (!TextOutA (hdc, x, y, str, text_length))
-           g_warning ("gdk_draw_text_wc: TextOutA failed");
-       }
-      g_free (str);
-#endif
-      if (oldfont != NULL)
-       SelectObject (hdc, oldfont);
-      gdk_gc_postdraw (drawable_private, gc_private);
     }
   else
-    g_error ("undefined font type");
+    wcstr = (wchar_t *) text;
+
+  if (!TextOutW (hdc, x, y, wcstr, text_length))
+    g_warning ("gdk_draw_text_wc: TextOutW failed");
+
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
+    g_free (wcstr);
+  if (oldfont != NULL)
+    SelectObject (hdc, oldfont);
+  gdk_gc_postdraw (drawable_private, gc_private);
 }
 
 void
index 593c98cd80a9f21bfb73c72399829191834a1a2b..85ca076ccecdbc980b983f1399bd0fbd8e69dcf9 100644 (file)
@@ -469,47 +469,35 @@ gdk_draw_text (GdkDrawable *drawable,
   if (text_length == 0)
     return;
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
   font_private = (GdkFontPrivate*) font;
 
-  if (font->type == GDK_FONT_FONT)
-    {
-      hdc = gdk_gc_predraw (drawable_private, gc_private);
-      xfont = (HFONT) font_private->xfont;
-
-      GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
-                              "+%d+%d font: %#x \"%.*s\" length: %d\n",
-                              drawable_private->xwindow,
-                              gc_private, gc_private->xgc,
-                              x, y, xfont,
-                              (text_length > 10 ? 10 : text_length),
-                              text, text_length));
-      
-      if ((oldfont = SelectObject (hdc, xfont)) == NULL)
-       g_warning ("gdk_draw_text: SelectObject failed");
-      if (font_private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
-                                          text, text_length,
-                                          wcstr, text_length)) == 0)
-           g_warning ("gdk_draw_text: MultiByteToWideChar failed");
-         else if (!TextOutW (hdc, x, y, wcstr, wlen))
-           g_warning ("gdk_draw_text: TextOutW failed");
-         g_free (wcstr);
-       }
-      else
-       {
-         if (!TextOutA (hdc, x, y, text, text_length))
-           g_warning ("gdk_draw_text: TextOutA failed");
-       }
-      if (oldfont != NULL)
-       SelectObject (hdc, oldfont);
-      gdk_gc_postdraw (drawable_private, gc_private);
-    }
-  else
-    g_error ("undefined font type");
+  hdc = gdk_gc_predraw (drawable_private, gc_private);
+  xfont = (HFONT) font_private->xfont;
+
+  GDK_NOTE (MISC, g_print ("gdk_draw_text: %#x (%d) %#x "
+                          "+%d+%d font: %#x \"%.*s\" length: %d\n",
+                          drawable_private->xwindow,
+                          gc_private, gc_private->xgc,
+                          x, y, xfont,
+                          (text_length > 10 ? 10 : text_length),
+                          text, text_length));
+  
+  if ((oldfont = SelectObject (hdc, xfont)) == NULL)
+    g_warning ("gdk_draw_text: SelectObject failed");
+
+  wcstr = g_new (wchar_t, text_length);
+  if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
+    g_warning ("gdk_draw_text: gdk_nmbstowchar_ts failed");
+  else if (!TextOutW (hdc, x, y, wcstr, wlen))
+    g_warning ("gdk_draw_text: TextOutW failed");
+  g_free (wcstr);
+  if (oldfont != NULL)
+    SelectObject (hdc, oldfont);
+  gdk_gc_postdraw (drawable_private, gc_private);
 }
 
 void
@@ -521,6 +509,8 @@ gdk_draw_text_wc (GdkDrawable        *drawable,
                  const GdkWChar *text,
                  gint            text_length)
 {
+  HDC hdc;
+  HGDIOBJ oldfont;
   GdkDrawablePrivate *drawable_private;
   GdkFontPrivate *font_private;
   GdkGCPrivate *gc_private;
@@ -539,68 +529,40 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
   if (text_length == 0)
     return;
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
   font_private = (GdkFontPrivate*) font;
 
-  if (font->type == GDK_FONT_FONT)
-    {
-      HDC hdc;
-      HFONT xfont;
-      HGDIOBJ oldfont;
+  hdc = gdk_gc_predraw (drawable_private, gc_private);
 
-      hdc = gdk_gc_predraw (drawable_private, gc_private);
-      xfont = (HFONT) font_private->xfont;
-
-      GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
-                              "+%d+%d font: %#x length: %d\n",
-                              drawable_private->xwindow,
-                              gc_private, gc_private->xgc,
-                              x, y, xfont,
-                              text_length));
+  GDK_NOTE (MISC, g_print ("gdk_draw_text_wc: %#x (%d) %#x "
+                          "+%d+%d font: %#x length: %d\n",
+                          drawable_private->xwindow,
+                          gc_private, gc_private->xgc,
+                          x, y, font_private->xfont,
+                          text_length));
       
-      if ((oldfont = SelectObject (hdc, xfont)) == NULL)
-         g_warning ("gdk_draw_text_wc: SelectObject failed");
-#if 0 /* No. Don't use TextOutW directly. Compare to the X11 version,
-       * it uses plain XDrawString for GDK_FONT_FONT fonts, too.
-       * TextOutW by definition interprets the string as Unicode.
-       * We don't have that, but either chars from some single-byte codepage
-       * or from a DBCS.
-       */
+  if ((oldfont = SelectObject (hdc, font_private->xfont)) == NULL)
+    g_warning ("gdk_draw_text_wc: SelectObject failed");
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
+    {
       wcstr = g_new (wchar_t, text_length);
       for (i = 0; i < text_length; i++)
        wcstr[i] = text[i];
-      if (!TextOutW (hdc, x, y, wcstr, text_length))
-       g_warning ("gdk_draw_text_wc: TextOutW failed");
-      g_free (wcstr);
-#else
-      str = g_new (guchar, text_length);
-      for (i = 0; i < text_length; i++)
-       str[i] = text[i];
-      if (font_private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
-                                          str, text_length,
-                                          wcstr, text_length)) == 0)
-           g_warning ("gdk_draw_text: MultiByteToWideChar failed");
-         else if (!TextOutW (hdc, x, y, wcstr, wlen))
-           g_warning ("gdk_draw_text_wc: TextOutW failed");
-         g_free (wcstr);
-       }
-      else
-       {
-         if (!TextOutA (hdc, x, y, str, text_length))
-           g_warning ("gdk_draw_text_wc: TextOutA failed");
-       }
-      g_free (str);
-#endif
-      if (oldfont != NULL)
-       SelectObject (hdc, oldfont);
-      gdk_gc_postdraw (drawable_private, gc_private);
     }
   else
-    g_error ("undefined font type");
+    wcstr = (wchar_t *) text;
+
+  if (!TextOutW (hdc, x, y, wcstr, text_length))
+    g_warning ("gdk_draw_text_wc: TextOutW failed");
+
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
+    g_free (wcstr);
+  if (oldfont != NULL)
+    SelectObject (hdc, oldfont);
+  gdk_gc_postdraw (drawable_private, gc_private);
 }
 
 void
index 53097d20b741efe05fb6f4b06489106ceb04ebb6..7ac8169786d662eb6477c8151c63e029fa89d17f 100644 (file)
 
 #include "config.h"
 
+#define NEW_PROPAGATION_CODE
+
+#define USE_DISPATCHMESSAGE
+
+/* Cannot use TrackMouseEvent, as the stupid WM_MOUSELEAVE message
+ * doesn't tell us where the mouse has gone. Thus we cannot use it to
+ * generate a correct GdkNotifyType. Pity, as using TrackMouseEvent
+ * otherwise would make it possible to reliably generate
+ * GDK_LEAVE_NOTIFY events, which would help get rid of those pesky
+ * tooltips sometimes popping up in the wrong place.
+ */
+/* define USE_TRACKMOUSEEVENT */
+
 #include <stdio.h>
 
+#include <windows.h>
+
+#ifdef HAVE_WINTAB
+#include <wintab.h>
+#endif
+
+#include <objbase.h>
+#include <imm.h>
+
+#ifdef HAVE_DIMM_H
+#include <dimm.h>
+#else
+#include "surrogate-dimm.h"
+#endif
+
 #include "gdk.h"
-#include "gdkprivate.h"
 #include "gdkx.h"
 
 #include "gdkkeysyms.h"
 
-#ifdef HAVE_WINTAB
-#include <wintab.h>
-#endif
 #include "gdkinputprivate.h"
 
 #define PING() printf("%s: %d\n",__FILE__,__LINE__),fflush(stdout)
 
+#define WINDOW_PRIVATE(wp) ((GdkWindowPrivate *) (wp))
+
 typedef struct _GdkIOClosure GdkIOClosure;
 typedef struct _GdkEventPrivate GdkEventPrivate;
 
@@ -80,10 +106,10 @@ struct _GdkEventPrivate
 
 static GdkEvent *gdk_event_new         (void);
 static GdkFilterReturn
-               gdk_event_apply_filters (MSG      *xevent,
+                gdk_event_apply_filters(MSG      *xevent,
                                         GdkEvent *event,
                                         GList    *filters);
-static gint     gdk_event_translate    (GdkEvent *event, 
+static gboolean  gdk_event_translate   (GdkEvent *event, 
                                         MSG      *xevent,
                                         gboolean *ret_val_flagp,
                                         gint     *ret_valp);
@@ -125,7 +151,7 @@ static GdkWindow *k_grab_window = NULL; /* Window the holds the
 static GList *client_filters;  /* Filters for client messages */
 
 static gboolean p_grab_automatic;
-static GdkEventMask p_grab_event_mask;
+static GdkEventMask p_grab_mask;
 static gboolean p_grab_owner_events, k_grab_owner_events;
 static HCURSOR p_grab_cursor;
 
@@ -158,22 +184,26 @@ static UINT gdk_ping_msg;
 static gboolean ignore_WM_CHAR = FALSE;
 static gboolean is_AltGr_key = FALSE;
 
+static IActiveIMMApp *paimmapp = NULL;
+static IActiveIMMMessagePumpOwner *paimmmpo = NULL;
+
 LRESULT CALLBACK 
-gdk_WindowProc(HWND hwnd,
-              UINT message,
-              WPARAM wParam,
-              LPARAM lParam)
+gdk_WindowProc (HWND hWnd,
+               UINT message,
+               WPARAM wParam,
+               LPARAM lParam)
 {
   GdkEvent event;
   GdkEvent *eventp;
   MSG msg;
   DWORD pos;
+  LRESULT lres;
   gint ret_val;
   gboolean ret_val_flag;
 
-  GDK_NOTE (EVENTS, g_print ("gdk_WindowProc: %#x\n", message));
+  GDK_NOTE (EVENTS, g_print ("gdk_WindowProc: %#x %#.03x\n", hWnd, message));
 
-  msg.hwnd = hwnd;
+  msg.hwnd = hWnd;
   msg.message = message;
   msg.wParam = wParam;
   msg.lParam = lParam;
@@ -182,12 +212,14 @@ gdk_WindowProc(HWND hwnd,
   msg.pt.x = LOWORD (pos);
   msg.pt.y = HIWORD (pos);
 
+  ((GdkEventPrivate *)&event)->flags |= GDK_EVENT_PENDING;
   if (gdk_event_translate (&event, &msg, &ret_val_flag, &ret_val))
     {
+      ((GdkEventPrivate *)&event)->flags &= ~GDK_EVENT_PENDING;
 #if 1
-      /* Compress configure events */
       if (event.any.type == GDK_CONFIGURE)
        {
+         /* Compress configure events */
          GList *list = queued_events;
 
          while (list != NULL
@@ -203,6 +235,29 @@ gdk_WindowProc(HWND hwnd,
              return FALSE;
            }
        }
+      else if (event.any.type == GDK_EXPOSE)
+       {
+         /* Compress expose events */
+         GList *list = queued_events;
+
+         while (list != NULL
+                && (((GdkEvent *)list->data)->any.type != GDK_EXPOSE
+                    || ((GdkEvent *)list->data)->any.window != event.any.window))
+           list = list->next;
+         if (list != NULL)
+           {
+             GdkRectangle u;
+
+             gdk_rectangle_union (&event.expose.area,
+                                  &((GdkEvent *)list->data)->expose.area,
+                                  &u);
+             ((GdkEvent *)list->data)->expose.area = u;
+             gdk_window_unref (event.any.window);
+             /* Wake up WaitMessage */
+             PostMessage (NULL, gdk_ping_msg, 0, 0);
+             return FALSE;
+           }
+       }
 #endif
       eventp = gdk_event_new ();
       *eventp = event;
@@ -240,7 +295,13 @@ gdk_WindowProc(HWND hwnd,
   if (ret_val_flag)
     return ret_val;
   else
-    return DefWindowProc (hwnd, message, wParam, lParam);
+    {
+      if (paimmapp == NULL
+         || (*paimmapp->lpVtbl->OnDefWindowProc) (paimmapp, hWnd, message, wParam, lParam, &lres) == S_FALSE)
+       return DefWindowProc (hWnd, message, wParam, lParam);
+      else
+       return lres;
+    }
 }
 
 /*********************************************
@@ -319,8 +380,18 @@ gdk_event_queue_append (GdkEvent *event)
 void 
 gdk_events_init (void)
 {
+  HRESULT hres;
+  HMODULE user32;
+  HINSTANCE commctrl32;
+
   if (g_pipe_readable_msg == 0)
     g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
+  GDK_NOTE (EVENTS, g_print ("g-pipe-readable = %#.03x\n",
+                            g_pipe_readable_msg));
+
+  gdk_ping_msg = RegisterWindowMessage ("gdk-ping");
+  GDK_NOTE (EVENTS, g_print ("gdk-ping = %#.03x\n",
+                            gdk_ping_msg));
 
   g_source_add (GDK_PRIORITY_EVENTS, TRUE, &event_funcs, NULL, NULL, NULL);
 
@@ -336,7 +407,34 @@ gdk_events_init (void)
   button_number[0] = -1;
   button_number[1] = -1;
 
-  gdk_ping_msg = RegisterWindowMessage ("gdk-ping");
+  hres = CoCreateInstance (&CLSID_CActiveIMM,
+                          NULL,
+                          CLSCTX_ALL,
+                          &IID_IActiveIMMApp,
+                          (LPVOID *) &paimmapp);
+  
+  if (hres == S_OK)
+    {
+      GDK_NOTE (EVENTS, g_print ("IActiveIMMApp created %#x\n",
+                                paimmapp));
+      (*paimmapp->lpVtbl->Activate) (paimmapp, TRUE);
+      
+      hres = (*paimmapp->lpVtbl->QueryInterface) (paimmapp, &IID_IActiveIMMMessagePumpOwner, &paimmmpo);
+      GDK_NOTE (EVENTS, g_print ("IActiveIMMMessagePumpOwner created %#x\n",
+                                paimmmpo));
+      (paimmmpo->lpVtbl->Start) (paimmmpo);
+    }
+
+#ifdef USE_TRACKMOUSEEVENT
+  user32 = GetModuleHandle ("user32.dll");
+  if ((p_TrackMouseEvent = GetProcAddress (user32, "TrackMouseEvent")) == NULL)
+    {
+      if ((commctrl32 = LoadLibrary ("commctrl32.dll")) != NULL)
+       p_TrackMouseEvent = GetProcAddress (commctrl32, "_TrackMouseEvent");
+    }
+  if (p_TrackMouseEvent != NULL)
+    GDK_NOTE (EVENTS, g_print ("Using TrackMouseEvent to detect leave events\n"));
+#endif
 }
 
 /*
@@ -809,12 +907,16 @@ gdk_pointer_grab (GdkWindow *       window,
     {
       if (!GDK_DRAWABLE_DESTROYED (window))
       {
-       GDK_NOTE (EVENTS, g_print ("gdk_pointer_grab: %#x %s %#x\n",
+       GDK_NOTE (EVENTS, g_print ("gdk_pointer_grab: %#x %s %#x%s%s\n",
                                   xwindow,
                                   (owner_events ? "TRUE" : "FALSE"),
-                                  xcursor));
-       p_grab_event_mask = event_mask;
-       p_grab_owner_events = owner_events != 0;
+                                  xcursor,
+                                  (event_mask & GDK_BUTTON_PRESS_MASK) ?
+                                  " PRESS" : "",
+                                  (event_mask & GDK_BUTTON_RELEASE_MASK) ?
+                                  " RELEASE" : ""));
+       p_grab_mask = event_mask;
+       p_grab_owner_events = (owner_events != 0);
        p_grab_automatic = FALSE;
 
 #if 0 /* Menus don't work if we use mouse capture. Pity, because many other
@@ -1076,15 +1178,1887 @@ gdk_add_client_message_filter (GdkAtom       message_type,
   client_filters = g_list_prepend (client_filters, filter);
 }
 
+/* Thanks to Markus G. Kuhn <mkuhn@acm.org> for the ksysym<->Unicode
+ * mapping functions, from the xterm sources.
+ */
+
+struct k2u {
+  unsigned short keysym;
+  unsigned short ucs;
+} k2utab[] = {
+  { 0x01a1, 0x0104 }, /*                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
+  { 0x01a2, 0x02d8 }, /*                       breve ˘ BREVE */
+  { 0x01a3, 0x0141 }, /*                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
+  { 0x01a5, 0x013d }, /*                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
+  { 0x01a6, 0x015a }, /*                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
+  { 0x01a9, 0x0160 }, /*                      Scaron Š LATIN CAPITAL LETTER S WITH CARON */
+  { 0x01aa, 0x015e }, /*                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
+  { 0x01ab, 0x0164 }, /*                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
+  { 0x01ac, 0x0179 }, /*                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
+  { 0x01ae, 0x017d }, /*                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
+  { 0x01af, 0x017b }, /*                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+  { 0x01b1, 0x0105 }, /*                     aogonek ą LATIN SMALL LETTER A WITH OGONEK */
+  { 0x01b2, 0x02db }, /*                      ogonek ˛ OGONEK */
+  { 0x01b3, 0x0142 }, /*                     lstroke ł LATIN SMALL LETTER L WITH STROKE */
+  { 0x01b5, 0x013e }, /*                      lcaron ľ LATIN SMALL LETTER L WITH CARON */
+  { 0x01b6, 0x015b }, /*                      sacute ś LATIN SMALL LETTER S WITH ACUTE */
+  { 0x01b7, 0x02c7 }, /*                       caron ˇ CARON */
+  { 0x01b9, 0x0161 }, /*                      scaron š LATIN SMALL LETTER S WITH CARON */
+  { 0x01ba, 0x015f }, /*                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
+  { 0x01bb, 0x0165 }, /*                      tcaron ť LATIN SMALL LETTER T WITH CARON */
+  { 0x01bc, 0x017a }, /*                      zacute ź LATIN SMALL LETTER Z WITH ACUTE */
+  { 0x01bd, 0x02dd }, /*                 doubleacute ˝ DOUBLE ACUTE ACCENT */
+  { 0x01be, 0x017e }, /*                      zcaron ž LATIN SMALL LETTER Z WITH CARON */
+  { 0x01bf, 0x017c }, /*                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
+  { 0x01c0, 0x0154 }, /*                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
+  { 0x01c3, 0x0102 }, /*                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
+  { 0x01c5, 0x0139 }, /*                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
+  { 0x01c6, 0x0106 }, /*                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
+  { 0x01c8, 0x010c }, /*                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
+  { 0x01ca, 0x0118 }, /*                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
+  { 0x01cc, 0x011a }, /*                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
+  { 0x01cf, 0x010e }, /*                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
+  { 0x01d0, 0x0110 }, /*                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
+  { 0x01d1, 0x0143 }, /*                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
+  { 0x01d2, 0x0147 }, /*                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
+  { 0x01d5, 0x0150 }, /*                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+  { 0x01d8, 0x0158 }, /*                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
+  { 0x01d9, 0x016e }, /*                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
+  { 0x01db, 0x0170 }, /*                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+  { 0x01de, 0x0162 }, /*                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
+  { 0x01e0, 0x0155 }, /*                      racute ŕ LATIN SMALL LETTER R WITH ACUTE */
+  { 0x01e3, 0x0103 }, /*                      abreve ă LATIN SMALL LETTER A WITH BREVE */
+  { 0x01e5, 0x013a }, /*                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
+  { 0x01e6, 0x0107 }, /*                      cacute ć LATIN SMALL LETTER C WITH ACUTE */
+  { 0x01e8, 0x010d }, /*                      ccaron č LATIN SMALL LETTER C WITH CARON */
+  { 0x01ea, 0x0119 }, /*                     eogonek ę LATIN SMALL LETTER E WITH OGONEK */
+  { 0x01ec, 0x011b }, /*                      ecaron ě LATIN SMALL LETTER E WITH CARON */
+  { 0x01ef, 0x010f }, /*                      dcaron ď LATIN SMALL LETTER D WITH CARON */
+  { 0x01f0, 0x0111 }, /*                     dstroke đ LATIN SMALL LETTER D WITH STROKE */
+  { 0x01f1, 0x0144 }, /*                      nacute ń LATIN SMALL LETTER N WITH ACUTE */
+  { 0x01f2, 0x0148 }, /*                      ncaron ň LATIN SMALL LETTER N WITH CARON */
+  { 0x01f5, 0x0151 }, /*                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+  { 0x01f8, 0x0159 }, /*                      rcaron ř LATIN SMALL LETTER R WITH CARON */
+  { 0x01f9, 0x016f }, /*                       uring ů LATIN SMALL LETTER U WITH RING ABOVE */
+  { 0x01fb, 0x0171 }, /*                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+  { 0x01fe, 0x0163 }, /*                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
+  { 0x01ff, 0x02d9 }, /*                    abovedot ˙ DOT ABOVE */
+  { 0x02a1, 0x0126 }, /*                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
+  { 0x02a6, 0x0124 }, /*                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+  { 0x02a9, 0x0130 }, /*                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
+  { 0x02ab, 0x011e }, /*                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
+  { 0x02ac, 0x0134 }, /*                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+  { 0x02b1, 0x0127 }, /*                     hstroke ħ LATIN SMALL LETTER H WITH STROKE */
+  { 0x02b6, 0x0125 }, /*                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
+  { 0x02b9, 0x0131 }, /*                    idotless ı LATIN SMALL LETTER DOTLESS I */
+  { 0x02bb, 0x011f }, /*                      gbreve ğ LATIN SMALL LETTER G WITH BREVE */
+  { 0x02bc, 0x0135 }, /*                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
+  { 0x02c5, 0x010a }, /*                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
+  { 0x02c6, 0x0108 }, /*                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+  { 0x02d5, 0x0120 }, /*                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
+  { 0x02d8, 0x011c }, /*                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+  { 0x02dd, 0x016c }, /*                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
+  { 0x02de, 0x015c }, /*                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+  { 0x02e5, 0x010b }, /*                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
+  { 0x02e6, 0x0109 }, /*                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
+  { 0x02f5, 0x0121 }, /*                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
+  { 0x02f8, 0x011d }, /*                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
+  { 0x02fd, 0x016d }, /*                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
+  { 0x02fe, 0x015d }, /*                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
+  { 0x03a2, 0x0138 }, /*                         kra ĸ LATIN SMALL LETTER KRA */
+  { 0x03a3, 0x0156 }, /*                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
+  { 0x03a5, 0x0128 }, /*                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
+  { 0x03a6, 0x013b }, /*                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
+  { 0x03aa, 0x0112 }, /*                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
+  { 0x03ab, 0x0122 }, /*                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
+  { 0x03ac, 0x0166 }, /*                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
+  { 0x03b3, 0x0157 }, /*                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
+  { 0x03b5, 0x0129 }, /*                      itilde ĩ LATIN SMALL LETTER I WITH TILDE */
+  { 0x03b6, 0x013c }, /*                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
+  { 0x03ba, 0x0113 }, /*                     emacron ē LATIN SMALL LETTER E WITH MACRON */
+  { 0x03bb, 0x0123 }, /*                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
+  { 0x03bc, 0x0167 }, /*                      tslash ŧ LATIN SMALL LETTER T WITH STROKE */
+  { 0x03bd, 0x014a }, /*                         ENG Ŋ LATIN CAPITAL LETTER ENG */
+  { 0x03bf, 0x014b }, /*                         eng ŋ LATIN SMALL LETTER ENG */
+  { 0x03c0, 0x0100 }, /*                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
+  { 0x03c7, 0x012e }, /*                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
+  { 0x03cc, 0x0116 }, /*                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
+  { 0x03cf, 0x012a }, /*                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
+  { 0x03d1, 0x0145 }, /*                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
+  { 0x03d2, 0x014c }, /*                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
+  { 0x03d3, 0x0136 }, /*                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
+  { 0x03d9, 0x0172 }, /*                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
+  { 0x03dd, 0x0168 }, /*                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
+  { 0x03de, 0x016a }, /*                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
+  { 0x03e0, 0x0101 }, /*                     amacron ā LATIN SMALL LETTER A WITH MACRON */
+  { 0x03e7, 0x012f }, /*                     iogonek į LATIN SMALL LETTER I WITH OGONEK */
+  { 0x03ec, 0x0117 }, /*                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
+  { 0x03ef, 0x012b }, /*                     imacron ī LATIN SMALL LETTER I WITH MACRON */
+  { 0x03f1, 0x0146 }, /*                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
+  { 0x03f2, 0x014d }, /*                     omacron ō LATIN SMALL LETTER O WITH MACRON */
+  { 0x03f3, 0x0137 }, /*                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
+  { 0x03f9, 0x0173 }, /*                     uogonek ų LATIN SMALL LETTER U WITH OGONEK */
+  { 0x03fd, 0x0169 }, /*                      utilde ũ LATIN SMALL LETTER U WITH TILDE */
+  { 0x03fe, 0x016b }, /*                     umacron ū LATIN SMALL LETTER U WITH MACRON */
+  { 0x047e, 0x203e }, /*                    overline ‾ OVERLINE */
+  { 0x04a1, 0x3002 }, /*               kana_fullstop 。 IDEOGRAPHIC FULL STOP */
+  { 0x04a2, 0x300c }, /*         kana_openingbracket 「 LEFT CORNER BRACKET */
+  { 0x04a3, 0x300d }, /*         kana_closingbracket 」 RIGHT CORNER BRACKET */
+  { 0x04a4, 0x3001 }, /*                  kana_comma 、 IDEOGRAPHIC COMMA */
+  { 0x04a5, 0x30fb }, /*            kana_conjunctive ・ KATAKANA MIDDLE DOT */
+  { 0x04a6, 0x30f2 }, /*                     kana_WO ヲ KATAKANA LETTER WO */
+  { 0x04a7, 0x30a1 }, /*                      kana_a ァ KATAKANA LETTER SMALL A */
+  { 0x04a8, 0x30a3 }, /*                      kana_i ィ KATAKANA LETTER SMALL I */
+  { 0x04a9, 0x30a5 }, /*                      kana_u ゥ KATAKANA LETTER SMALL U */
+  { 0x04aa, 0x30a7 }, /*                      kana_e ェ KATAKANA LETTER SMALL E */
+  { 0x04ab, 0x30a9 }, /*                      kana_o ォ KATAKANA LETTER SMALL O */
+  { 0x04ac, 0x30e3 }, /*                     kana_ya ャ KATAKANA LETTER SMALL YA */
+  { 0x04ad, 0x30e5 }, /*                     kana_yu ュ KATAKANA LETTER SMALL YU */
+  { 0x04ae, 0x30e7 }, /*                     kana_yo ョ KATAKANA LETTER SMALL YO */
+  { 0x04af, 0x30c3 }, /*                    kana_tsu ッ KATAKANA LETTER SMALL TU */
+  { 0x04b0, 0x30fc }, /*              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+  { 0x04b1, 0x30a2 }, /*                      kana_A ア KATAKANA LETTER A */
+  { 0x04b2, 0x30a4 }, /*                      kana_I イ KATAKANA LETTER I */
+  { 0x04b3, 0x30a6 }, /*                      kana_U ウ KATAKANA LETTER U */
+  { 0x04b4, 0x30a8 }, /*                      kana_E エ KATAKANA LETTER E */
+  { 0x04b5, 0x30aa }, /*                      kana_O オ KATAKANA LETTER O */
+  { 0x04b6, 0x30ab }, /*                     kana_KA カ KATAKANA LETTER KA */
+  { 0x04b7, 0x30ad }, /*                     kana_KI キ KATAKANA LETTER KI */
+  { 0x04b8, 0x30af }, /*                     kana_KU ク KATAKANA LETTER KU */
+  { 0x04b9, 0x30b1 }, /*                     kana_KE ケ KATAKANA LETTER KE */
+  { 0x04ba, 0x30b3 }, /*                     kana_KO コ KATAKANA LETTER KO */
+  { 0x04bb, 0x30b5 }, /*                     kana_SA サ KATAKANA LETTER SA */
+  { 0x04bc, 0x30b7 }, /*                    kana_SHI シ KATAKANA LETTER SI */
+  { 0x04bd, 0x30b9 }, /*                     kana_SU ス KATAKANA LETTER SU */
+  { 0x04be, 0x30bb }, /*                     kana_SE セ KATAKANA LETTER SE */
+  { 0x04bf, 0x30bd }, /*                     kana_SO ソ KATAKANA LETTER SO */
+  { 0x04c0, 0x30bf }, /*                     kana_TA タ KATAKANA LETTER TA */
+  { 0x04c1, 0x30c1 }, /*                    kana_CHI チ KATAKANA LETTER TI */
+  { 0x04c2, 0x30c4 }, /*                    kana_TSU ツ KATAKANA LETTER TU */
+  { 0x04c3, 0x30c6 }, /*                     kana_TE テ KATAKANA LETTER TE */
+  { 0x04c4, 0x30c8 }, /*                     kana_TO ト KATAKANA LETTER TO */
+  { 0x04c5, 0x30ca }, /*                     kana_NA ナ KATAKANA LETTER NA */
+  { 0x04c6, 0x30cb }, /*                     kana_NI ニ KATAKANA LETTER NI */
+  { 0x04c7, 0x30cc }, /*                     kana_NU ヌ KATAKANA LETTER NU */
+  { 0x04c8, 0x30cd }, /*                     kana_NE ネ KATAKANA LETTER NE */
+  { 0x04c9, 0x30ce }, /*                     kana_NO ノ KATAKANA LETTER NO */
+  { 0x04ca, 0x30cf }, /*                     kana_HA ハ KATAKANA LETTER HA */
+  { 0x04cb, 0x30d2 }, /*                     kana_HI ヒ KATAKANA LETTER HI */
+  { 0x04cc, 0x30d5 }, /*                     kana_FU フ KATAKANA LETTER HU */
+  { 0x04cd, 0x30d8 }, /*                     kana_HE ヘ KATAKANA LETTER HE */
+  { 0x04ce, 0x30db }, /*                     kana_HO ホ KATAKANA LETTER HO */
+  { 0x04cf, 0x30de }, /*                     kana_MA マ KATAKANA LETTER MA */
+  { 0x04d0, 0x30df }, /*                     kana_MI ミ KATAKANA LETTER MI */
+  { 0x04d1, 0x30e0 }, /*                     kana_MU ム KATAKANA LETTER MU */
+  { 0x04d2, 0x30e1 }, /*                     kana_ME メ KATAKANA LETTER ME */
+  { 0x04d3, 0x30e2 }, /*                     kana_MO モ KATAKANA LETTER MO */
+  { 0x04d4, 0x30e4 }, /*                     kana_YA ヤ KATAKANA LETTER YA */
+  { 0x04d5, 0x30e6 }, /*                     kana_YU ユ KATAKANA LETTER YU */
+  { 0x04d6, 0x30e8 }, /*                     kana_YO ヨ KATAKANA LETTER YO */
+  { 0x04d7, 0x30e9 }, /*                     kana_RA ラ KATAKANA LETTER RA */
+  { 0x04d8, 0x30ea }, /*                     kana_RI リ KATAKANA LETTER RI */
+  { 0x04d9, 0x30eb }, /*                     kana_RU ル KATAKANA LETTER RU */
+  { 0x04da, 0x30ec }, /*                     kana_RE レ KATAKANA LETTER RE */
+  { 0x04db, 0x30ed }, /*                     kana_RO ロ KATAKANA LETTER RO */
+  { 0x04dc, 0x30ef }, /*                     kana_WA ワ KATAKANA LETTER WA */
+  { 0x04dd, 0x30f3 }, /*                      kana_N ン KATAKANA LETTER N */
+  { 0x04de, 0x309b }, /*                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
+  { 0x04df, 0x309c }, /*             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+  { 0x05ac, 0x060c }, /*                Arabic_comma ، ARABIC COMMA */
+  { 0x05bb, 0x061b }, /*            Arabic_semicolon ؛ ARABIC SEMICOLON */
+  { 0x05bf, 0x061f }, /*        Arabic_question_mark ؟ ARABIC QUESTION MARK */
+  { 0x05c1, 0x0621 }, /*                Arabic_hamza ء ARABIC LETTER HAMZA */
+  { 0x05c2, 0x0622 }, /*          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
+  { 0x05c3, 0x0623 }, /*          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
+  { 0x05c4, 0x0624 }, /*           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
+  { 0x05c5, 0x0625 }, /*       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
+  { 0x05c6, 0x0626 }, /*           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
+  { 0x05c7, 0x0627 }, /*                 Arabic_alef ا ARABIC LETTER ALEF */
+  { 0x05c8, 0x0628 }, /*                  Arabic_beh ب ARABIC LETTER BEH */
+  { 0x05c9, 0x0629 }, /*           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
+  { 0x05ca, 0x062a }, /*                  Arabic_teh ت ARABIC LETTER TEH */
+  { 0x05cb, 0x062b }, /*                 Arabic_theh ث ARABIC LETTER THEH */
+  { 0x05cc, 0x062c }, /*                 Arabic_jeem ج ARABIC LETTER JEEM */
+  { 0x05cd, 0x062d }, /*                  Arabic_hah ح ARABIC LETTER HAH */
+  { 0x05ce, 0x062e }, /*                 Arabic_khah خ ARABIC LETTER KHAH */
+  { 0x05cf, 0x062f }, /*                  Arabic_dal د ARABIC LETTER DAL */
+  { 0x05d0, 0x0630 }, /*                 Arabic_thal ذ ARABIC LETTER THAL */
+  { 0x05d1, 0x0631 }, /*                   Arabic_ra ر ARABIC LETTER REH */
+  { 0x05d2, 0x0632 }, /*                 Arabic_zain ز ARABIC LETTER ZAIN */
+  { 0x05d3, 0x0633 }, /*                 Arabic_seen س ARABIC LETTER SEEN */
+  { 0x05d4, 0x0634 }, /*                Arabic_sheen ش ARABIC LETTER SHEEN */
+  { 0x05d5, 0x0635 }, /*                  Arabic_sad ص ARABIC LETTER SAD */
+  { 0x05d6, 0x0636 }, /*                  Arabic_dad ض ARABIC LETTER DAD */
+  { 0x05d7, 0x0637 }, /*                  Arabic_tah ط ARABIC LETTER TAH */
+  { 0x05d8, 0x0638 }, /*                  Arabic_zah ظ ARABIC LETTER ZAH */
+  { 0x05d9, 0x0639 }, /*                  Arabic_ain ع ARABIC LETTER AIN */
+  { 0x05da, 0x063a }, /*                Arabic_ghain غ ARABIC LETTER GHAIN */
+  { 0x05e0, 0x0640 }, /*              Arabic_tatweel ـ ARABIC TATWEEL */
+  { 0x05e1, 0x0641 }, /*                  Arabic_feh ف ARABIC LETTER FEH */
+  { 0x05e2, 0x0642 }, /*                  Arabic_qaf ق ARABIC LETTER QAF */
+  { 0x05e3, 0x0643 }, /*                  Arabic_kaf ك ARABIC LETTER KAF */
+  { 0x05e4, 0x0644 }, /*                  Arabic_lam ل ARABIC LETTER LAM */
+  { 0x05e5, 0x0645 }, /*                 Arabic_meem م ARABIC LETTER MEEM */
+  { 0x05e6, 0x0646 }, /*                 Arabic_noon ن ARABIC LETTER NOON */
+  { 0x05e7, 0x0647 }, /*                   Arabic_ha ه ARABIC LETTER HEH */
+  { 0x05e8, 0x0648 }, /*                  Arabic_waw و ARABIC LETTER WAW */
+  { 0x05e9, 0x0649 }, /*          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
+  { 0x05ea, 0x064a }, /*                  Arabic_yeh ي ARABIC LETTER YEH */
+  { 0x05eb, 0x064b }, /*             Arabic_fathatan ً ARABIC FATHATAN */
+  { 0x05ec, 0x064c }, /*             Arabic_dammatan ٌ ARABIC DAMMATAN */
+  { 0x05ed, 0x064d }, /*             Arabic_kasratan ٍ ARABIC KASRATAN */
+  { 0x05ee, 0x064e }, /*                Arabic_fatha َ ARABIC FATHA */
+  { 0x05ef, 0x064f }, /*                Arabic_damma ُ ARABIC DAMMA */
+  { 0x05f0, 0x0650 }, /*                Arabic_kasra ِ ARABIC KASRA */
+  { 0x05f1, 0x0651 }, /*               Arabic_shadda ّ ARABIC SHADDA */
+  { 0x05f2, 0x0652 }, /*                Arabic_sukun ْ ARABIC SUKUN */
+  { 0x06a1, 0x0452 }, /*                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
+  { 0x06a2, 0x0453 }, /*               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
+  { 0x06a3, 0x0451 }, /*                 Cyrillic_io ё CYRILLIC SMALL LETTER IO */
+  { 0x06a4, 0x0454 }, /*                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
+  { 0x06a5, 0x0455 }, /*               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
+  { 0x06a6, 0x0456 }, /*                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06a7, 0x0457 }, /*                Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
+  { 0x06a8, 0x0458 }, /*                 Cyrillic_je ј CYRILLIC SMALL LETTER JE */
+  { 0x06a9, 0x0459 }, /*                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
+  { 0x06aa, 0x045a }, /*                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
+  { 0x06ab, 0x045b }, /*                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
+  { 0x06ac, 0x045c }, /*               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
+  { 0x06ae, 0x045e }, /*         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
+  { 0x06af, 0x045f }, /*               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
+  { 0x06b0, 0x2116 }, /*                  numerosign № NUMERO SIGN */
+  { 0x06b1, 0x0402 }, /*                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
+  { 0x06b2, 0x0403 }, /*               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
+  { 0x06b3, 0x0401 }, /*                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
+  { 0x06b4, 0x0404 }, /*                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+  { 0x06b5, 0x0405 }, /*               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
+  { 0x06b6, 0x0406 }, /*                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06b7, 0x0407 }, /*                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
+  { 0x06b8, 0x0408 }, /*                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
+  { 0x06b9, 0x0409 }, /*                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
+  { 0x06ba, 0x040a }, /*                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
+  { 0x06bb, 0x040b }, /*                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
+  { 0x06bc, 0x040c }, /*               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
+  { 0x06be, 0x040e }, /*         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
+  { 0x06bf, 0x040f }, /*               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
+  { 0x06c0, 0x044e }, /*                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
+  { 0x06c1, 0x0430 }, /*                  Cyrillic_a а CYRILLIC SMALL LETTER A */
+  { 0x06c2, 0x0431 }, /*                 Cyrillic_be б CYRILLIC SMALL LETTER BE */
+  { 0x06c3, 0x0446 }, /*                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
+  { 0x06c4, 0x0434 }, /*                 Cyrillic_de д CYRILLIC SMALL LETTER DE */
+  { 0x06c5, 0x0435 }, /*                 Cyrillic_ie е CYRILLIC SMALL LETTER IE */
+  { 0x06c6, 0x0444 }, /*                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
+  { 0x06c7, 0x0433 }, /*                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
+  { 0x06c8, 0x0445 }, /*                 Cyrillic_ha х CYRILLIC SMALL LETTER HA */
+  { 0x06c9, 0x0438 }, /*                  Cyrillic_i и CYRILLIC SMALL LETTER I */
+  { 0x06ca, 0x0439 }, /*             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
+  { 0x06cb, 0x043a }, /*                 Cyrillic_ka к CYRILLIC SMALL LETTER KA */
+  { 0x06cc, 0x043b }, /*                 Cyrillic_el л CYRILLIC SMALL LETTER EL */
+  { 0x06cd, 0x043c }, /*                 Cyrillic_em м CYRILLIC SMALL LETTER EM */
+  { 0x06ce, 0x043d }, /*                 Cyrillic_en н CYRILLIC SMALL LETTER EN */
+  { 0x06cf, 0x043e }, /*                  Cyrillic_o о CYRILLIC SMALL LETTER O */
+  { 0x06d0, 0x043f }, /*                 Cyrillic_pe п CYRILLIC SMALL LETTER PE */
+  { 0x06d1, 0x044f }, /*                 Cyrillic_ya я CYRILLIC SMALL LETTER YA */
+  { 0x06d2, 0x0440 }, /*                 Cyrillic_er р CYRILLIC SMALL LETTER ER */
+  { 0x06d3, 0x0441 }, /*                 Cyrillic_es с CYRILLIC SMALL LETTER ES */
+  { 0x06d4, 0x0442 }, /*                 Cyrillic_te т CYRILLIC SMALL LETTER TE */
+  { 0x06d5, 0x0443 }, /*                  Cyrillic_u у CYRILLIC SMALL LETTER U */
+  { 0x06d6, 0x0436 }, /*                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
+  { 0x06d7, 0x0432 }, /*                 Cyrillic_ve в CYRILLIC SMALL LETTER VE */
+  { 0x06d8, 0x044c }, /*           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
+  { 0x06d9, 0x044b }, /*               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
+  { 0x06da, 0x0437 }, /*                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
+  { 0x06db, 0x0448 }, /*                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
+  { 0x06dc, 0x044d }, /*                  Cyrillic_e э CYRILLIC SMALL LETTER E */
+  { 0x06dd, 0x0449 }, /*              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
+  { 0x06de, 0x0447 }, /*                Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
+  { 0x06df, 0x044a }, /*           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
+  { 0x06e0, 0x042e }, /*                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
+  { 0x06e1, 0x0410 }, /*                  Cyrillic_A А CYRILLIC CAPITAL LETTER A */
+  { 0x06e2, 0x0411 }, /*                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
+  { 0x06e3, 0x0426 }, /*                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
+  { 0x06e4, 0x0414 }, /*                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
+  { 0x06e5, 0x0415 }, /*                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
+  { 0x06e6, 0x0424 }, /*                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
+  { 0x06e7, 0x0413 }, /*                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
+  { 0x06e8, 0x0425 }, /*                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
+  { 0x06e9, 0x0418 }, /*                  Cyrillic_I И CYRILLIC CAPITAL LETTER I */
+  { 0x06ea, 0x0419 }, /*             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
+  { 0x06eb, 0x041a }, /*                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
+  { 0x06ec, 0x041b }, /*                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
+  { 0x06ed, 0x041c }, /*                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
+  { 0x06ee, 0x041d }, /*                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
+  { 0x06ef, 0x041e }, /*                  Cyrillic_O О CYRILLIC CAPITAL LETTER O */
+  { 0x06f0, 0x041f }, /*                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
+  { 0x06f1, 0x042f }, /*                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
+  { 0x06f2, 0x0420 }, /*                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
+  { 0x06f3, 0x0421 }, /*                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
+  { 0x06f4, 0x0422 }, /*                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
+  { 0x06f5, 0x0423 }, /*                  Cyrillic_U У CYRILLIC CAPITAL LETTER U */
+  { 0x06f6, 0x0416 }, /*                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
+  { 0x06f7, 0x0412 }, /*                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
+  { 0x06f8, 0x042c }, /*           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
+  { 0x06f9, 0x042b }, /*               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
+  { 0x06fa, 0x0417 }, /*                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
+  { 0x06fb, 0x0428 }, /*                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
+  { 0x06fc, 0x042d }, /*                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
+  { 0x06fd, 0x0429 }, /*              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
+  { 0x06fe, 0x0427 }, /*                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
+  { 0x06ff, 0x042a }, /*           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
+  { 0x07a1, 0x0386 }, /*           Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
+  { 0x07a2, 0x0388 }, /*         Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
+  { 0x07a3, 0x0389 }, /*             Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
+  { 0x07a4, 0x038a }, /*            Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
+  { 0x07a5, 0x03aa }, /*         Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+  { 0x07a7, 0x038c }, /*         Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
+  { 0x07a8, 0x038e }, /*         Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
+  { 0x07a9, 0x03ab }, /*       Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07ab, 0x038f }, /*           Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
+  { 0x07ae, 0x0385 }, /*        Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
+  { 0x07af, 0x2015 }, /*              Greek_horizbar ― HORIZONTAL BAR */
+  { 0x07b1, 0x03ac }, /*           Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
+  { 0x07b2, 0x03ad }, /*         Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
+  { 0x07b3, 0x03ae }, /*             Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
+  { 0x07b4, 0x03af }, /*            Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
+  { 0x07b5, 0x03ca }, /*          Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+  { 0x07b6, 0x0390 }, /*    Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+  { 0x07b7, 0x03cc }, /*         Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
+  { 0x07b8, 0x03cd }, /*         Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
+  { 0x07b9, 0x03cb }, /*       Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+  { 0x07bb, 0x03ce }, /*           Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
+  { 0x07c1, 0x0391 }, /*                 Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
+  { 0x07c2, 0x0392 }, /*                  Greek_BETA Β GREEK CAPITAL LETTER BETA */
+  { 0x07c3, 0x0393 }, /*                 Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
+  { 0x07c4, 0x0394 }, /*                 Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
+  { 0x07c5, 0x0395 }, /*               Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
+  { 0x07c6, 0x0396 }, /*                  Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
+  { 0x07c7, 0x0397 }, /*                   Greek_ETA Η GREEK CAPITAL LETTER ETA */
+  { 0x07c8, 0x0398 }, /*                 Greek_THETA Θ GREEK CAPITAL LETTER THETA */
+  { 0x07c9, 0x0399 }, /*                  Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
+  { 0x07ca, 0x039a }, /*                 Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
+  { 0x07cb, 0x039b }, /*                Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
+  { 0x07cc, 0x039c }, /*                    Greek_MU Μ GREEK CAPITAL LETTER MU */
+  { 0x07cd, 0x039d }, /*                    Greek_NU Ν GREEK CAPITAL LETTER NU */
+  { 0x07ce, 0x039e }, /*                    Greek_XI Ξ GREEK CAPITAL LETTER XI */
+  { 0x07cf, 0x039f }, /*               Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
+  { 0x07d0, 0x03a0 }, /*                    Greek_PI Π GREEK CAPITAL LETTER PI */
+  { 0x07d1, 0x03a1 }, /*                   Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
+  { 0x07d2, 0x03a3 }, /*                 Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
+  { 0x07d4, 0x03a4 }, /*                   Greek_TAU Τ GREEK CAPITAL LETTER TAU */
+  { 0x07d5, 0x03a5 }, /*               Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
+  { 0x07d6, 0x03a6 }, /*                   Greek_PHI Φ GREEK CAPITAL LETTER PHI */
+  { 0x07d7, 0x03a7 }, /*                   Greek_CHI Χ GREEK CAPITAL LETTER CHI */
+  { 0x07d8, 0x03a8 }, /*                   Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
+  { 0x07d9, 0x03a9 }, /*                 Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
+  { 0x07e1, 0x03b1 }, /*                 Greek_alpha α GREEK SMALL LETTER ALPHA */
+  { 0x07e2, 0x03b2 }, /*                  Greek_beta β GREEK SMALL LETTER BETA */
+  { 0x07e3, 0x03b3 }, /*                 Greek_gamma γ GREEK SMALL LETTER GAMMA */
+  { 0x07e4, 0x03b4 }, /*                 Greek_delta δ GREEK SMALL LETTER DELTA */
+  { 0x07e5, 0x03b5 }, /*               Greek_epsilon ε GREEK SMALL LETTER EPSILON */
+  { 0x07e6, 0x03b6 }, /*                  Greek_zeta ζ GREEK SMALL LETTER ZETA */
+  { 0x07e7, 0x03b7 }, /*                   Greek_eta η GREEK SMALL LETTER ETA */
+  { 0x07e8, 0x03b8 }, /*                 Greek_theta θ GREEK SMALL LETTER THETA */
+  { 0x07e9, 0x03b9 }, /*                  Greek_iota ι GREEK SMALL LETTER IOTA */
+  { 0x07ea, 0x03ba }, /*                 Greek_kappa κ GREEK SMALL LETTER KAPPA */
+  { 0x07eb, 0x03bb }, /*                Greek_lambda λ GREEK SMALL LETTER LAMDA */
+  { 0x07ec, 0x03bc }, /*                    Greek_mu μ GREEK SMALL LETTER MU */
+  { 0x07ed, 0x03bd }, /*                    Greek_nu ν GREEK SMALL LETTER NU */
+  { 0x07ee, 0x03be }, /*                    Greek_xi ξ GREEK SMALL LETTER XI */
+  { 0x07ef, 0x03bf }, /*               Greek_omicron ο GREEK SMALL LETTER OMICRON */
+  { 0x07f0, 0x03c0 }, /*                    Greek_pi π GREEK SMALL LETTER PI */
+  { 0x07f1, 0x03c1 }, /*                   Greek_rho ρ GREEK SMALL LETTER RHO */
+  { 0x07f2, 0x03c3 }, /*                 Greek_sigma σ GREEK SMALL LETTER SIGMA */
+  { 0x07f3, 0x03c2 }, /*       Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
+  { 0x07f4, 0x03c4 }, /*                   Greek_tau τ GREEK SMALL LETTER TAU */
+  { 0x07f5, 0x03c5 }, /*               Greek_upsilon υ GREEK SMALL LETTER UPSILON */
+  { 0x07f6, 0x03c6 }, /*                   Greek_phi φ GREEK SMALL LETTER PHI */
+  { 0x07f7, 0x03c7 }, /*                   Greek_chi χ GREEK SMALL LETTER CHI */
+  { 0x07f8, 0x03c8 }, /*                   Greek_psi ψ GREEK SMALL LETTER PSI */
+  { 0x07f9, 0x03c9 }, /*                 Greek_omega ω GREEK SMALL LETTER OMEGA */
+/*  0x08a1                               leftradical ? ??? */
+/*  0x08a2                            topleftradical ? ??? */
+/*  0x08a3                            horizconnector ? ??? */
+  { 0x08a4, 0x2320 }, /*                 topintegral ⌠ TOP HALF INTEGRAL */
+  { 0x08a5, 0x2321 }, /*                 botintegral ⌡ BOTTOM HALF INTEGRAL */
+  { 0x08a6, 0x2502 }, /*               vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
+/*  0x08a7                          topleftsqbracket ? ??? */
+/*  0x08a8                          botleftsqbracket ? ??? */
+/*  0x08a9                         toprightsqbracket ? ??? */
+/*  0x08aa                         botrightsqbracket ? ??? */
+/*  0x08ab                             topleftparens ? ??? */
+/*  0x08ac                             botleftparens ? ??? */
+/*  0x08ad                            toprightparens ? ??? */
+/*  0x08ae                            botrightparens ? ??? */
+/*  0x08af                      leftmiddlecurlybrace ? ??? */
+/*  0x08b0                     rightmiddlecurlybrace ? ??? */
+/*  0x08b1                          topleftsummation ? ??? */
+/*  0x08b2                          botleftsummation ? ??? */
+/*  0x08b3                 topvertsummationconnector ? ??? */
+/*  0x08b4                 botvertsummationconnector ? ??? */
+/*  0x08b5                         toprightsummation ? ??? */
+/*  0x08b6                         botrightsummation ? ??? */
+/*  0x08b7                      rightmiddlesummation ? ??? */
+  { 0x08bc, 0x2264 }, /*               lessthanequal ≤ LESS-THAN OR EQUAL TO */
+  { 0x08bd, 0x2260 }, /*                    notequal ≠ NOT EQUAL TO */
+  { 0x08be, 0x2265 }, /*            greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
+  { 0x08bf, 0x222b }, /*                    integral ∫ INTEGRAL */
+  { 0x08c0, 0x2234 }, /*                   therefore ∴ THEREFORE */
+  { 0x08c1, 0x221d }, /*                   variation ∝ PROPORTIONAL TO */
+  { 0x08c2, 0x221e }, /*                    infinity ∞ INFINITY */
+  { 0x08c5, 0x2207 }, /*                       nabla ∇ NABLA */
+  { 0x08c8, 0x2245 }, /*                 approximate ≅ APPROXIMATELY EQUAL TO */
+/*  0x08c9                              similarequal ? ??? */
+  { 0x08cd, 0x21d4 }, /*                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
+  { 0x08ce, 0x21d2 }, /*                     implies ⇒ RIGHTWARDS DOUBLE ARROW */
+  { 0x08cf, 0x2261 }, /*                   identical ≡ IDENTICAL TO */
+  { 0x08d6, 0x221a }, /*                     radical √ SQUARE ROOT */
+  { 0x08da, 0x2282 }, /*                  includedin ⊂ SUBSET OF */
+  { 0x08db, 0x2283 }, /*                    includes ⊃ SUPERSET OF */
+  { 0x08dc, 0x2229 }, /*                intersection ∩ INTERSECTION */
+  { 0x08dd, 0x222a }, /*                       union ∪ UNION */
+  { 0x08de, 0x2227 }, /*                  logicaland ∧ LOGICAL AND */
+  { 0x08df, 0x2228 }, /*                   logicalor ∨ LOGICAL OR */
+  { 0x08ef, 0x2202 }, /*           partialderivative ∂ PARTIAL DIFFERENTIAL */
+  { 0x08f6, 0x0192 }, /*                    function ƒ LATIN SMALL LETTER F WITH HOOK */
+  { 0x08fb, 0x2190 }, /*                   leftarrow ← LEFTWARDS ARROW */
+  { 0x08fc, 0x2191 }, /*                     uparrow ↑ UPWARDS ARROW */
+  { 0x08fd, 0x2192 }, /*                  rightarrow → RIGHTWARDS ARROW */
+  { 0x08fe, 0x2193 }, /*                   downarrow ↓ DOWNWARDS ARROW */
+  { 0x09df, 0x2422 }, /*                       blank ␢ BLANK SYMBOL */
+  { 0x09e0, 0x25c6 }, /*                soliddiamond ◆ BLACK DIAMOND */
+  { 0x09e1, 0x2592 }, /*                checkerboard ▒ MEDIUM SHADE */
+  { 0x09e2, 0x2409 }, /*                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
+  { 0x09e3, 0x240c }, /*                          ff ␌ SYMBOL FOR FORM FEED */
+  { 0x09e4, 0x240d }, /*                          cr ␍ SYMBOL FOR CARRIAGE RETURN */
+  { 0x09e5, 0x240a }, /*                          lf ␊ SYMBOL FOR LINE FEED */
+  { 0x09e8, 0x2424 }, /*                          nl ␤ SYMBOL FOR NEWLINE */
+  { 0x09e9, 0x240b }, /*                          vt ␋ SYMBOL FOR VERTICAL TABULATION */
+  { 0x09ea, 0x2518 }, /*              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
+  { 0x09eb, 0x2510 }, /*               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
+  { 0x09ec, 0x250c }, /*                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+  { 0x09ed, 0x2514 }, /*               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
+  { 0x09ee, 0x253c }, /*               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+/*  0x09ef                            horizlinescan1 ? ??? */
+/*  0x09f0                            horizlinescan3 ? ??? */
+  { 0x09f1, 0x2500 }, /*              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
+/*  0x09f2                            horizlinescan7 ? ??? */
+/*  0x09f3                            horizlinescan9 ? ??? */
+  { 0x09f4, 0x251c }, /*                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+  { 0x09f5, 0x2524 }, /*                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+  { 0x09f6, 0x2534 }, /*                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+  { 0x09f7, 0x252c }, /*                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+  { 0x09f8, 0x2502 }, /*                     vertbar │ BOX DRAWINGS LIGHT VERTICAL */
+  { 0x0aa1, 0x2003 }, /*                     emspace   EM SPACE */
+  { 0x0aa2, 0x2002 }, /*                     enspace   EN SPACE */
+  { 0x0aa3, 0x2004 }, /*                    em3space   THREE-PER-EM SPACE */
+  { 0x0aa4, 0x2005 }, /*                    em4space   FOUR-PER-EM SPACE */
+  { 0x0aa5, 0x2007 }, /*                  digitspace   FIGURE SPACE */
+  { 0x0aa6, 0x2008 }, /*                  punctspace   PUNCTUATION SPACE */
+  { 0x0aa7, 0x2009 }, /*                   thinspace   THIN SPACE */
+  { 0x0aa8, 0x200a }, /*                   hairspace   HAIR SPACE */
+  { 0x0aa9, 0x2014 }, /*                      emdash — EM DASH */
+  { 0x0aaa, 0x2013 }, /*                      endash – EN DASH */
+/*  0x0aac                               signifblank ? ??? */
+  { 0x0aae, 0x2026 }, /*                    ellipsis … HORIZONTAL ELLIPSIS */
+/*  0x0aaf                           doubbaselinedot ? ??? */
+  { 0x0ab0, 0x2153 }, /*                    onethird ⅓ VULGAR FRACTION ONE THIRD */
+  { 0x0ab1, 0x2154 }, /*                   twothirds ⅔ VULGAR FRACTION TWO THIRDS */
+  { 0x0ab2, 0x2155 }, /*                    onefifth ⅕ VULGAR FRACTION ONE FIFTH */
+  { 0x0ab3, 0x2156 }, /*                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
+  { 0x0ab4, 0x2157 }, /*                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
+  { 0x0ab5, 0x2158 }, /*                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
+  { 0x0ab6, 0x2159 }, /*                    onesixth ⅙ VULGAR FRACTION ONE SIXTH */
+  { 0x0ab7, 0x215a }, /*                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
+  { 0x0ab8, 0x2105 }, /*                      careof ℅ CARE OF */
+  { 0x0abb, 0x2012 }, /*                     figdash ‒ FIGURE DASH */
+  { 0x0abc, 0x2329 }, /*            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
+  { 0x0abd, 0x002e }, /*                decimalpoint . FULL STOP */
+  { 0x0abe, 0x232a }, /*           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
+/*  0x0abf                                    marker ? ??? */
+  { 0x0ac3, 0x215b }, /*                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
+  { 0x0ac4, 0x215c }, /*                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
+  { 0x0ac5, 0x215d }, /*                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
+  { 0x0ac6, 0x215e }, /*                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
+  { 0x0ac9, 0x2122 }, /*                   trademark ™ TRADE MARK SIGN */
+  { 0x0aca, 0x2613 }, /*               signaturemark ☓ SALTIRE */
+/*  0x0acb                         trademarkincircle ? ??? */
+  { 0x0acc, 0x25c1 }, /*            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
+  { 0x0acd, 0x25b7 }, /*           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
+  { 0x0ace, 0x25cb }, /*                emopencircle ○ WHITE CIRCLE */
+  { 0x0acf, 0x25a1 }, /*             emopenrectangle □ WHITE SQUARE */
+  { 0x0ad0, 0x2018 }, /*         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
+  { 0x0ad1, 0x2019 }, /*        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
+  { 0x0ad2, 0x201c }, /*         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
+  { 0x0ad3, 0x201d }, /*        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
+  { 0x0ad4, 0x211e }, /*                prescription ℞ PRESCRIPTION TAKE */
+  { 0x0ad6, 0x2032 }, /*                     minutes ′ PRIME */
+  { 0x0ad7, 0x2033 }, /*                     seconds ″ DOUBLE PRIME */
+  { 0x0ad9, 0x271d }, /*                  latincross ✝ LATIN CROSS */
+/*  0x0ada                                  hexagram ? ??? */
+  { 0x0adb, 0x25ac }, /*            filledrectbullet ▬ BLACK RECTANGLE */
+  { 0x0adc, 0x25c0 }, /*         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
+  { 0x0add, 0x25b6 }, /*        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
+  { 0x0ade, 0x25cf }, /*              emfilledcircle ● BLACK CIRCLE */
+  { 0x0adf, 0x25a0 }, /*                emfilledrect ■ BLACK SQUARE */
+  { 0x0ae0, 0x25e6 }, /*            enopencircbullet ◦ WHITE BULLET */
+  { 0x0ae1, 0x25ab }, /*          enopensquarebullet ▫ WHITE SMALL SQUARE */
+  { 0x0ae2, 0x25ad }, /*              openrectbullet ▭ WHITE RECTANGLE */
+  { 0x0ae3, 0x25b3 }, /*             opentribulletup △ WHITE UP-POINTING TRIANGLE */
+  { 0x0ae4, 0x25bd }, /*           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
+  { 0x0ae5, 0x2606 }, /*                    openstar ☆ WHITE STAR */
+  { 0x0ae6, 0x2022 }, /*          enfilledcircbullet • BULLET */
+  { 0x0ae7, 0x25aa }, /*            enfilledsqbullet ▪ BLACK SMALL SQUARE */
+  { 0x0ae8, 0x25b2 }, /*           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
+  { 0x0ae9, 0x25bc }, /*         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
+  { 0x0aea, 0x261c }, /*                 leftpointer ☜ WHITE LEFT POINTING INDEX */
+  { 0x0aeb, 0x261e }, /*                rightpointer ☞ WHITE RIGHT POINTING INDEX */
+  { 0x0aec, 0x2663 }, /*                        club ♣ BLACK CLUB SUIT */
+  { 0x0aed, 0x2666 }, /*                     diamond ♦ BLACK DIAMOND SUIT */
+  { 0x0aee, 0x2665 }, /*                       heart ♥ BLACK HEART SUIT */
+  { 0x0af0, 0x2720 }, /*                maltesecross ✠ MALTESE CROSS */
+  { 0x0af1, 0x2020 }, /*                      dagger † DAGGER */
+  { 0x0af2, 0x2021 }, /*                doubledagger ‡ DOUBLE DAGGER */
+  { 0x0af3, 0x2713 }, /*                   checkmark ✓ CHECK MARK */
+  { 0x0af4, 0x2717 }, /*                 ballotcross ✗ BALLOT X */
+  { 0x0af5, 0x266f }, /*                musicalsharp ♯ MUSIC SHARP SIGN */
+  { 0x0af6, 0x266d }, /*                 musicalflat ♭ MUSIC FLAT SIGN */
+  { 0x0af7, 0x2642 }, /*                  malesymbol ♂ MALE SIGN */
+  { 0x0af8, 0x2640 }, /*                femalesymbol ♀ FEMALE SIGN */
+  { 0x0af9, 0x260e }, /*                   telephone ☎ BLACK TELEPHONE */
+  { 0x0afa, 0x2315 }, /*           telephonerecorder ⌕ TELEPHONE RECORDER */
+  { 0x0afb, 0x2117 }, /*         phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
+  { 0x0afc, 0x2038 }, /*                       caret ‸ CARET */
+  { 0x0afd, 0x201a }, /*          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
+  { 0x0afe, 0x201e }, /*          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
+/*  0x0aff                                    cursor ? ??? */
+  { 0x0ba3, 0x003c }, /*                   leftcaret < LESS-THAN SIGN */
+  { 0x0ba6, 0x003e }, /*                  rightcaret > GREATER-THAN SIGN */
+  { 0x0ba8, 0x2228 }, /*                   downcaret ∨ LOGICAL OR */
+  { 0x0ba9, 0x2227 }, /*                     upcaret ∧ LOGICAL AND */
+  { 0x0bc0, 0x00af }, /*                     overbar ¯ MACRON */
+  { 0x0bc2, 0x22a4 }, /*                    downtack ⊤ DOWN TACK */
+  { 0x0bc3, 0x2229 }, /*                      upshoe ∩ INTERSECTION */
+  { 0x0bc4, 0x230a }, /*                   downstile ⌊ LEFT FLOOR */
+  { 0x0bc6, 0x005f }, /*                    underbar _ LOW LINE */
+  { 0x0bca, 0x2218 }, /*                         jot ∘ RING OPERATOR */
+  { 0x0bcc, 0x2395 }, /*                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */
+  { 0x0bce, 0x22a5 }, /*                      uptack ⊥ UP TACK */
+  { 0x0bcf, 0x25cb }, /*                      circle ○ WHITE CIRCLE */
+  { 0x0bd3, 0x2308 }, /*                     upstile ⌈ LEFT CEILING */
+  { 0x0bd6, 0x222a }, /*                    downshoe ∪ UNION */
+  { 0x0bd8, 0x2283 }, /*                   rightshoe ⊃ SUPERSET OF */
+  { 0x0bda, 0x2282 }, /*                    leftshoe ⊂ SUBSET OF */
+  { 0x0bdc, 0x22a3 }, /*                    lefttack ⊣ LEFT TACK */
+  { 0x0bfc, 0x22a2 }, /*                   righttack ⊢ RIGHT TACK */
+  { 0x0cdf, 0x2017 }, /*        hebrew_doublelowline ‗ DOUBLE LOW LINE */
+  { 0x0ce0, 0x05d0 }, /*                hebrew_aleph א HEBREW LETTER ALEF */
+  { 0x0ce1, 0x05d1 }, /*                  hebrew_bet ב HEBREW LETTER BET */
+  { 0x0ce2, 0x05d2 }, /*                hebrew_gimel ג HEBREW LETTER GIMEL */
+  { 0x0ce3, 0x05d3 }, /*                hebrew_dalet ד HEBREW LETTER DALET */
+  { 0x0ce4, 0x05d4 }, /*                   hebrew_he ה HEBREW LETTER HE */
+  { 0x0ce5, 0x05d5 }, /*                  hebrew_waw ו HEBREW LETTER VAV */
+  { 0x0ce6, 0x05d6 }, /*                 hebrew_zain ז HEBREW LETTER ZAYIN */
+  { 0x0ce7, 0x05d7 }, /*                 hebrew_chet ח HEBREW LETTER HET */
+  { 0x0ce8, 0x05d8 }, /*                  hebrew_tet ט HEBREW LETTER TET */
+  { 0x0ce9, 0x05d9 }, /*                  hebrew_yod י HEBREW LETTER YOD */
+  { 0x0cea, 0x05da }, /*            hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
+  { 0x0ceb, 0x05db }, /*                 hebrew_kaph כ HEBREW LETTER KAF */
+  { 0x0cec, 0x05dc }, /*                hebrew_lamed ל HEBREW LETTER LAMED */
+  { 0x0ced, 0x05dd }, /*             hebrew_finalmem ם HEBREW LETTER FINAL MEM */
+  { 0x0cee, 0x05de }, /*                  hebrew_mem מ HEBREW LETTER MEM */
+  { 0x0cef, 0x05df }, /*             hebrew_finalnun ן HEBREW LETTER FINAL NUN */
+  { 0x0cf0, 0x05e0 }, /*                  hebrew_nun נ HEBREW LETTER NUN */
+  { 0x0cf1, 0x05e1 }, /*               hebrew_samech ס HEBREW LETTER SAMEKH */
+  { 0x0cf2, 0x05e2 }, /*                 hebrew_ayin ע HEBREW LETTER AYIN */
+  { 0x0cf3, 0x05e3 }, /*              hebrew_finalpe ף HEBREW LETTER FINAL PE */
+  { 0x0cf4, 0x05e4 }, /*                   hebrew_pe פ HEBREW LETTER PE */
+  { 0x0cf5, 0x05e5 }, /*            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
+  { 0x0cf6, 0x05e6 }, /*                 hebrew_zade צ HEBREW LETTER TSADI */
+  { 0x0cf7, 0x05e7 }, /*                 hebrew_qoph ק HEBREW LETTER QOF */
+  { 0x0cf8, 0x05e8 }, /*                 hebrew_resh ר HEBREW LETTER RESH */
+  { 0x0cf9, 0x05e9 }, /*                 hebrew_shin ש HEBREW LETTER SHIN */
+  { 0x0cfa, 0x05ea }, /*                  hebrew_taw ת HEBREW LETTER TAV */
+  { 0x0da1, 0x0e01 }, /*                  Thai_kokai ก THAI CHARACTER KO KAI */
+  { 0x0da2, 0x0e02 }, /*                Thai_khokhai ข THAI CHARACTER KHO KHAI */
+  { 0x0da3, 0x0e03 }, /*               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
+  { 0x0da4, 0x0e04 }, /*               Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
+  { 0x0da5, 0x0e05 }, /*                Thai_khokhon ฅ THAI CHARACTER KHO KHON */
+  { 0x0da6, 0x0e06 }, /*             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
+  { 0x0da7, 0x0e07 }, /*                 Thai_ngongu ง THAI CHARACTER NGO NGU */
+  { 0x0da8, 0x0e08 }, /*                Thai_chochan จ THAI CHARACTER CHO CHAN */
+  { 0x0da9, 0x0e09 }, /*               Thai_choching ฉ THAI CHARACTER CHO CHING */
+  { 0x0daa, 0x0e0a }, /*               Thai_chochang ช THAI CHARACTER CHO CHANG */
+  { 0x0dab, 0x0e0b }, /*                   Thai_soso ซ THAI CHARACTER SO SO */
+  { 0x0dac, 0x0e0c }, /*                Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
+  { 0x0dad, 0x0e0d }, /*                 Thai_yoying ญ THAI CHARACTER YO YING */
+  { 0x0dae, 0x0e0e }, /*                Thai_dochada ฎ THAI CHARACTER DO CHADA */
+  { 0x0daf, 0x0e0f }, /*                Thai_topatak ฏ THAI CHARACTER TO PATAK */
+  { 0x0db0, 0x0e10 }, /*                Thai_thothan ฐ THAI CHARACTER THO THAN */
+  { 0x0db1, 0x0e11 }, /*          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
+  { 0x0db2, 0x0e12 }, /*             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
+  { 0x0db3, 0x0e13 }, /*                  Thai_nonen ณ THAI CHARACTER NO NEN */
+  { 0x0db4, 0x0e14 }, /*                  Thai_dodek ด THAI CHARACTER DO DEK */
+  { 0x0db5, 0x0e15 }, /*                  Thai_totao ต THAI CHARACTER TO TAO */
+  { 0x0db6, 0x0e16 }, /*               Thai_thothung ถ THAI CHARACTER THO THUNG */
+  { 0x0db7, 0x0e17 }, /*              Thai_thothahan ท THAI CHARACTER THO THAHAN */
+  { 0x0db8, 0x0e18 }, /*               Thai_thothong ธ THAI CHARACTER THO THONG */
+  { 0x0db9, 0x0e19 }, /*                   Thai_nonu น THAI CHARACTER NO NU */
+  { 0x0dba, 0x0e1a }, /*               Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
+  { 0x0dbb, 0x0e1b }, /*                  Thai_popla ป THAI CHARACTER PO PLA */
+  { 0x0dbc, 0x0e1c }, /*               Thai_phophung ผ THAI CHARACTER PHO PHUNG */
+  { 0x0dbd, 0x0e1d }, /*                   Thai_fofa ฝ THAI CHARACTER FO FA */
+  { 0x0dbe, 0x0e1e }, /*                Thai_phophan พ THAI CHARACTER PHO PHAN */
+  { 0x0dbf, 0x0e1f }, /*                  Thai_fofan ฟ THAI CHARACTER FO FAN */
+  { 0x0dc0, 0x0e20 }, /*             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
+  { 0x0dc1, 0x0e21 }, /*                   Thai_moma ม THAI CHARACTER MO MA */
+  { 0x0dc2, 0x0e22 }, /*                  Thai_yoyak ย THAI CHARACTER YO YAK */
+  { 0x0dc3, 0x0e23 }, /*                  Thai_rorua ร THAI CHARACTER RO RUA */
+  { 0x0dc4, 0x0e24 }, /*                     Thai_ru ฤ THAI CHARACTER RU */
+  { 0x0dc5, 0x0e25 }, /*                 Thai_loling ล THAI CHARACTER LO LING */
+  { 0x0dc6, 0x0e26 }, /*                     Thai_lu ฦ THAI CHARACTER LU */
+  { 0x0dc7, 0x0e27 }, /*                 Thai_wowaen ว THAI CHARACTER WO WAEN */
+  { 0x0dc8, 0x0e28 }, /*                 Thai_sosala ศ THAI CHARACTER SO SALA */
+  { 0x0dc9, 0x0e29 }, /*                 Thai_sorusi ษ THAI CHARACTER SO RUSI */
+  { 0x0dca, 0x0e2a }, /*                  Thai_sosua ส THAI CHARACTER SO SUA */
+  { 0x0dcb, 0x0e2b }, /*                  Thai_hohip ห THAI CHARACTER HO HIP */
+  { 0x0dcc, 0x0e2c }, /*                Thai_lochula ฬ THAI CHARACTER LO CHULA */
+  { 0x0dcd, 0x0e2d }, /*                   Thai_oang อ THAI CHARACTER O ANG */
+  { 0x0dce, 0x0e2e }, /*               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
+  { 0x0dcf, 0x0e2f }, /*              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
+  { 0x0dd0, 0x0e30 }, /*                  Thai_saraa ะ THAI CHARACTER SARA A */
+  { 0x0dd1, 0x0e31 }, /*             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
+  { 0x0dd2, 0x0e32 }, /*                 Thai_saraaa า THAI CHARACTER SARA AA */
+  { 0x0dd3, 0x0e33 }, /*                 Thai_saraam ำ THAI CHARACTER SARA AM */
+  { 0x0dd4, 0x0e34 }, /*                  Thai_sarai ิ THAI CHARACTER SARA I */
+  { 0x0dd5, 0x0e35 }, /*                 Thai_saraii ี THAI CHARACTER SARA II */
+  { 0x0dd6, 0x0e36 }, /*                 Thai_saraue ึ THAI CHARACTER SARA UE */
+  { 0x0dd7, 0x0e37 }, /*                Thai_sarauee ื THAI CHARACTER SARA UEE */
+  { 0x0dd8, 0x0e38 }, /*                  Thai_sarau ุ THAI CHARACTER SARA U */
+  { 0x0dd9, 0x0e39 }, /*                 Thai_sarauu ู THAI CHARACTER SARA UU */
+  { 0x0dda, 0x0e3a }, /*                Thai_phinthu ฺ THAI CHARACTER PHINTHU */
+  { 0x0dde, 0x0e3e }, /*      Thai_maihanakat_maitho ฾ ??? */
+  { 0x0ddf, 0x0e3f }, /*                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
+  { 0x0de0, 0x0e40 }, /*                  Thai_sarae เ THAI CHARACTER SARA E */
+  { 0x0de1, 0x0e41 }, /*                 Thai_saraae แ THAI CHARACTER SARA AE */
+  { 0x0de2, 0x0e42 }, /*                  Thai_sarao โ THAI CHARACTER SARA O */
+  { 0x0de3, 0x0e43 }, /*          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
+  { 0x0de4, 0x0e44 }, /*         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
+  { 0x0de5, 0x0e45 }, /*            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
+  { 0x0de6, 0x0e46 }, /*               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
+  { 0x0de7, 0x0e47 }, /*              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
+  { 0x0de8, 0x0e48 }, /*                  Thai_maiek ่ THAI CHARACTER MAI EK */
+  { 0x0de9, 0x0e49 }, /*                 Thai_maitho ้ THAI CHARACTER MAI THO */
+  { 0x0dea, 0x0e4a }, /*                 Thai_maitri ๊ THAI CHARACTER MAI TRI */
+  { 0x0deb, 0x0e4b }, /*            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
+  { 0x0dec, 0x0e4c }, /*            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
+  { 0x0ded, 0x0e4d }, /*               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
+  { 0x0df0, 0x0e50 }, /*                 Thai_leksun ๐ THAI DIGIT ZERO */
+  { 0x0df1, 0x0e51 }, /*                Thai_leknung ๑ THAI DIGIT ONE */
+  { 0x0df2, 0x0e52 }, /*                Thai_leksong ๒ THAI DIGIT TWO */
+  { 0x0df3, 0x0e53 }, /*                 Thai_leksam ๓ THAI DIGIT THREE */
+  { 0x0df4, 0x0e54 }, /*                  Thai_leksi ๔ THAI DIGIT FOUR */
+  { 0x0df5, 0x0e55 }, /*                  Thai_lekha ๕ THAI DIGIT FIVE */
+  { 0x0df6, 0x0e56 }, /*                 Thai_lekhok ๖ THAI DIGIT SIX */
+  { 0x0df7, 0x0e57 }, /*                Thai_lekchet ๗ THAI DIGIT SEVEN */
+  { 0x0df8, 0x0e58 }, /*                Thai_lekpaet ๘ THAI DIGIT EIGHT */
+  { 0x0df9, 0x0e59 }, /*                 Thai_lekkao ๙ THAI DIGIT NINE */
+  { 0x0ea1, 0x3131 }, /*               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
+  { 0x0ea2, 0x3132 }, /*          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
+  { 0x0ea3, 0x3133 }, /*           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
+  { 0x0ea4, 0x3134 }, /*                Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
+  { 0x0ea5, 0x3135 }, /*           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
+  { 0x0ea6, 0x3136 }, /*           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
+  { 0x0ea7, 0x3137 }, /*               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
+  { 0x0ea8, 0x3138 }, /*          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
+  { 0x0ea9, 0x3139 }, /*                Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
+  { 0x0eaa, 0x313a }, /*          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
+  { 0x0eab, 0x313b }, /*           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
+  { 0x0eac, 0x313c }, /*           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
+  { 0x0ead, 0x313d }, /*            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
+  { 0x0eae, 0x313e }, /*           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
+  { 0x0eaf, 0x313f }, /*          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
+  { 0x0eb0, 0x3140 }, /*           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
+  { 0x0eb1, 0x3141 }, /*                Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
+  { 0x0eb2, 0x3142 }, /*                Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
+  { 0x0eb3, 0x3143 }, /*           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
+  { 0x0eb4, 0x3144 }, /*            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
+  { 0x0eb5, 0x3145 }, /*                 Hangul_Sios ㅅ HANGUL LETTER SIOS */
+  { 0x0eb6, 0x3146 }, /*            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
+  { 0x0eb7, 0x3147 }, /*                Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
+  { 0x0eb8, 0x3148 }, /*                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
+  { 0x0eb9, 0x3149 }, /*           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
+  { 0x0eba, 0x314a }, /*                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
+  { 0x0ebb, 0x314b }, /*               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
+  { 0x0ebc, 0x314c }, /*                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
+  { 0x0ebd, 0x314d }, /*               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
+  { 0x0ebe, 0x314e }, /*                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
+  { 0x0ebf, 0x314f }, /*                    Hangul_A ㅏ HANGUL LETTER A */
+  { 0x0ec0, 0x3150 }, /*                   Hangul_AE ㅐ HANGUL LETTER AE */
+  { 0x0ec1, 0x3151 }, /*                   Hangul_YA ㅑ HANGUL LETTER YA */
+  { 0x0ec2, 0x3152 }, /*                  Hangul_YAE ㅒ HANGUL LETTER YAE */
+  { 0x0ec3, 0x3153 }, /*                   Hangul_EO ㅓ HANGUL LETTER EO */
+  { 0x0ec4, 0x3154 }, /*                    Hangul_E ㅔ HANGUL LETTER E */
+  { 0x0ec5, 0x3155 }, /*                  Hangul_YEO ㅕ HANGUL LETTER YEO */
+  { 0x0ec6, 0x3156 }, /*                   Hangul_YE ㅖ HANGUL LETTER YE */
+  { 0x0ec7, 0x3157 }, /*                    Hangul_O ㅗ HANGUL LETTER O */
+  { 0x0ec8, 0x3158 }, /*                   Hangul_WA ㅘ HANGUL LETTER WA */
+  { 0x0ec9, 0x3159 }, /*                  Hangul_WAE ㅙ HANGUL LETTER WAE */
+  { 0x0eca, 0x315a }, /*                   Hangul_OE ㅚ HANGUL LETTER OE */
+  { 0x0ecb, 0x315b }, /*                   Hangul_YO ㅛ HANGUL LETTER YO */
+  { 0x0ecc, 0x315c }, /*                    Hangul_U ㅜ HANGUL LETTER U */
+  { 0x0ecd, 0x315d }, /*                  Hangul_WEO ㅝ HANGUL LETTER WEO */
+  { 0x0ece, 0x315e }, /*                   Hangul_WE ㅞ HANGUL LETTER WE */
+  { 0x0ecf, 0x315f }, /*                   Hangul_WI ㅟ HANGUL LETTER WI */
+  { 0x0ed0, 0x3160 }, /*                   Hangul_YU ㅠ HANGUL LETTER YU */
+  { 0x0ed1, 0x3161 }, /*                   Hangul_EU ㅡ HANGUL LETTER EU */
+  { 0x0ed2, 0x3162 }, /*                   Hangul_YI ㅢ HANGUL LETTER YI */
+  { 0x0ed3, 0x3163 }, /*                    Hangul_I ㅣ HANGUL LETTER I */
+  { 0x0ed4, 0x11a8 }, /*             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
+  { 0x0ed5, 0x11a9 }, /*        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
+  { 0x0ed6, 0x11aa }, /*         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
+  { 0x0ed7, 0x11ab }, /*              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
+  { 0x0ed8, 0x11ac }, /*         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
+  { 0x0ed9, 0x11ad }, /*         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
+  { 0x0eda, 0x11ae }, /*             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
+  { 0x0edb, 0x11af }, /*              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
+  { 0x0edc, 0x11b0 }, /*        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
+  { 0x0edd, 0x11b1 }, /*         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
+  { 0x0ede, 0x11b2 }, /*         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
+  { 0x0edf, 0x11b3 }, /*          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
+  { 0x0ee0, 0x11b4 }, /*         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
+  { 0x0ee1, 0x11b5 }, /*        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
+  { 0x0ee2, 0x11b6 }, /*         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
+  { 0x0ee3, 0x11b7 }, /*              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
+  { 0x0ee4, 0x11b8 }, /*              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
+  { 0x0ee5, 0x11b9 }, /*          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
+  { 0x0ee6, 0x11ba }, /*               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
+  { 0x0ee7, 0x11bb }, /*          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
+  { 0x0ee8, 0x11bc }, /*              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
+  { 0x0ee9, 0x11bd }, /*              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
+  { 0x0eea, 0x11be }, /*              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
+  { 0x0eeb, 0x11bf }, /*             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
+  { 0x0eec, 0x11c0 }, /*              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
+  { 0x0eed, 0x11c1 }, /*             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
+  { 0x0eee, 0x11c2 }, /*              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
+  { 0x0eef, 0x316d }, /*     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
+  { 0x0ef0, 0x3171 }, /*    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
+  { 0x0ef1, 0x3178 }, /*    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
+  { 0x0ef2, 0x317f }, /*              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
+/*  0x0ef3                  Hangul_KkogjiDalrinIeung ? ??? */
+  { 0x0ef4, 0x3184 }, /*   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
+  { 0x0ef5, 0x3186 }, /*          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
+  { 0x0ef6, 0x318d }, /*                Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
+  { 0x0ef7, 0x318e }, /*               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
+  { 0x0ef8, 0x11eb }, /*            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
+/*  0x0ef9                Hangul_J_KkogjiDalrinIeung ? ??? */
+  { 0x0efa, 0x11f9 }, /*        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
+  { 0x0eff, 0x20a9 }, /*                  Korean_Won ₩ WON SIGN */
+  { 0x13bc, 0x0152 }, /*                          OE Œ LATIN CAPITAL LIGATURE OE */
+  { 0x13bd, 0x0153 }, /*                          oe œ LATIN SMALL LIGATURE OE */
+  { 0x13be, 0x0178 }, /*                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
+  { 0x20a0, 0x20a0 }, /*                     EcuSign ₠ EURO-CURRENCY SIGN */
+  { 0x20a1, 0x20a1 }, /*                   ColonSign ₡ COLON SIGN */
+  { 0x20a2, 0x20a2 }, /*                CruzeiroSign ₢ CRUZEIRO SIGN */
+  { 0x20a3, 0x20a3 }, /*                  FFrancSign ₣ FRENCH FRANC SIGN */
+  { 0x20a4, 0x20a4 }, /*                    LiraSign ₤ LIRA SIGN */
+  { 0x20a5, 0x20a5 }, /*                    MillSign ₥ MILL SIGN */
+  { 0x20a6, 0x20a6 }, /*                   NairaSign ₦ NAIRA SIGN */
+  { 0x20a7, 0x20a7 }, /*                  PesetaSign ₧ PESETA SIGN */
+  { 0x20a8, 0x20a8 }, /*                   RupeeSign ₨ RUPEE SIGN */
+  { 0x20a9, 0x20a9 }, /*                     WonSign ₩ WON SIGN */
+  { 0x20aa, 0x20aa }, /*               NewSheqelSign ₪ NEW SHEQEL SIGN */
+  { 0x20ab, 0x20ab }, /*                    DongSign ₫ DONG SIGN */
+  { 0x20ac, 0x20ac }, /*                    EuroSign € EURO SIGN */
+};
+
+static guint
+keyval_to_unicode (guint keysym)
+{
+  int min = 0;
+  int max = sizeof(k2utab) / sizeof(k2utab[0]) - 1;
+  int mid;
+
+  /* First check for Latin-1 characters (1:1 mapping) */
+  if ((keysym >= 0x0020 && keysym <= 0x007e) ||
+      (keysym >= 0x00a0 && keysym <= 0x00ff))
+    return keysym;
+
+  /* Also check for directly encoded 24-bit UCS characters */
+  if ((keysym & 0xff000000) == 0x01000000)
+    return keysym & 0x00ffffff;
+
+  /* binary search in table */
+  while (max >= min) {
+    mid = (min + max) / 2;
+    if (k2utab[mid].keysym < keysym)
+      min = mid + 1;
+    else if (k2utab[mid].keysym > keysym)
+      max = mid - 1;
+    else {
+      /* found it */
+      return k2utab[mid].ucs;
+    }
+  }
+  
+  /* No matching Unicode value found */
+  return -1;
+}
+
+struct u2k {
+  unsigned short keysym;
+  unsigned short ucs;
+} u2ktab[] = {
+  { 0x0abd, 0x002e }, /*                decimalpoint . FULL STOP */
+  { 0x0ba3, 0x003c }, /*                   leftcaret < LESS-THAN SIGN */
+  { 0x0ba6, 0x003e }, /*                  rightcaret > GREATER-THAN SIGN */
+  { 0x0bc6, 0x005f }, /*                    underbar _ LOW LINE */
+  { 0x0bc0, 0x00af }, /*                     overbar ¯ MACRON */
+  { 0x03c0, 0x0100 }, /*                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
+  { 0x03e0, 0x0101 }, /*                     amacron ā LATIN SMALL LETTER A WITH MACRON */
+  { 0x01c3, 0x0102 }, /*                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
+  { 0x01e3, 0x0103 }, /*                      abreve ă LATIN SMALL LETTER A WITH BREVE */
+  { 0x01a1, 0x0104 }, /*                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
+  { 0x01b1, 0x0105 }, /*                     aogonek ą LATIN SMALL LETTER A WITH OGONEK */
+  { 0x01c6, 0x0106 }, /*                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
+  { 0x01e6, 0x0107 }, /*                      cacute ć LATIN SMALL LETTER C WITH ACUTE */
+  { 0x02c6, 0x0108 }, /*                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+  { 0x02e6, 0x0109 }, /*                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
+  { 0x02c5, 0x010a }, /*                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
+  { 0x02e5, 0x010b }, /*                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
+  { 0x01c8, 0x010c }, /*                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
+  { 0x01e8, 0x010d }, /*                      ccaron č LATIN SMALL LETTER C WITH CARON */
+  { 0x01cf, 0x010e }, /*                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
+  { 0x01ef, 0x010f }, /*                      dcaron ď LATIN SMALL LETTER D WITH CARON */
+  { 0x01d0, 0x0110 }, /*                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
+  { 0x01f0, 0x0111 }, /*                     dstroke đ LATIN SMALL LETTER D WITH STROKE */
+  { 0x03aa, 0x0112 }, /*                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
+  { 0x03ba, 0x0113 }, /*                     emacron ē LATIN SMALL LETTER E WITH MACRON */
+  { 0x03cc, 0x0116 }, /*                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
+  { 0x03ec, 0x0117 }, /*                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
+  { 0x01ca, 0x0118 }, /*                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
+  { 0x01ea, 0x0119 }, /*                     eogonek ę LATIN SMALL LETTER E WITH OGONEK */
+  { 0x01cc, 0x011a }, /*                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
+  { 0x01ec, 0x011b }, /*                      ecaron ě LATIN SMALL LETTER E WITH CARON */
+  { 0x02d8, 0x011c }, /*                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+  { 0x02f8, 0x011d }, /*                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
+  { 0x02ab, 0x011e }, /*                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
+  { 0x02bb, 0x011f }, /*                      gbreve ğ LATIN SMALL LETTER G WITH BREVE */
+  { 0x02d5, 0x0120 }, /*                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
+  { 0x02f5, 0x0121 }, /*                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
+  { 0x03ab, 0x0122 }, /*                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
+  { 0x03bb, 0x0123 }, /*                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
+  { 0x02a6, 0x0124 }, /*                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+  { 0x02b6, 0x0125 }, /*                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
+  { 0x02a1, 0x0126 }, /*                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
+  { 0x02b1, 0x0127 }, /*                     hstroke ħ LATIN SMALL LETTER H WITH STROKE */
+  { 0x03a5, 0x0128 }, /*                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
+  { 0x03b5, 0x0129 }, /*                      itilde ĩ LATIN SMALL LETTER I WITH TILDE */
+  { 0x03cf, 0x012a }, /*                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
+  { 0x03ef, 0x012b }, /*                     imacron ī LATIN SMALL LETTER I WITH MACRON */
+  { 0x03c7, 0x012e }, /*                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
+  { 0x03e7, 0x012f }, /*                     iogonek į LATIN SMALL LETTER I WITH OGONEK */
+  { 0x02a9, 0x0130 }, /*                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
+  { 0x02b9, 0x0131 }, /*                    idotless ı LATIN SMALL LETTER DOTLESS I */
+  { 0x02ac, 0x0134 }, /*                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+  { 0x02bc, 0x0135 }, /*                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
+  { 0x03d3, 0x0136 }, /*                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
+  { 0x03f3, 0x0137 }, /*                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
+  { 0x03a2, 0x0138 }, /*                         kra ĸ LATIN SMALL LETTER KRA */
+  { 0x01c5, 0x0139 }, /*                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
+  { 0x01e5, 0x013a }, /*                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
+  { 0x03a6, 0x013b }, /*                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
+  { 0x03b6, 0x013c }, /*                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
+  { 0x01a5, 0x013d }, /*                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
+  { 0x01b5, 0x013e }, /*                      lcaron ľ LATIN SMALL LETTER L WITH CARON */
+  { 0x01a3, 0x0141 }, /*                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
+  { 0x01b3, 0x0142 }, /*                     lstroke ł LATIN SMALL LETTER L WITH STROKE */
+  { 0x01d1, 0x0143 }, /*                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
+  { 0x01f1, 0x0144 }, /*                      nacute ń LATIN SMALL LETTER N WITH ACUTE */
+  { 0x03d1, 0x0145 }, /*                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
+  { 0x03f1, 0x0146 }, /*                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
+  { 0x01d2, 0x0147 }, /*                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
+  { 0x01f2, 0x0148 }, /*                      ncaron ň LATIN SMALL LETTER N WITH CARON */
+  { 0x03bd, 0x014a }, /*                         ENG Ŋ LATIN CAPITAL LETTER ENG */
+  { 0x03bf, 0x014b }, /*                         eng ŋ LATIN SMALL LETTER ENG */
+  { 0x03d2, 0x014c }, /*                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
+  { 0x03f2, 0x014d }, /*                     omacron ō LATIN SMALL LETTER O WITH MACRON */
+  { 0x01d5, 0x0150 }, /*                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+  { 0x01f5, 0x0151 }, /*                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+  { 0x13bc, 0x0152 }, /*                          OE Œ LATIN CAPITAL LIGATURE OE */
+  { 0x13bd, 0x0153 }, /*                          oe œ LATIN SMALL LIGATURE OE */
+  { 0x01c0, 0x0154 }, /*                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
+  { 0x01e0, 0x0155 }, /*                      racute ŕ LATIN SMALL LETTER R WITH ACUTE */
+  { 0x03a3, 0x0156 }, /*                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
+  { 0x03b3, 0x0157 }, /*                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
+  { 0x01d8, 0x0158 }, /*                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
+  { 0x01f8, 0x0159 }, /*                      rcaron ř LATIN SMALL LETTER R WITH CARON */
+  { 0x01a6, 0x015a }, /*                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
+  { 0x01b6, 0x015b }, /*                      sacute ś LATIN SMALL LETTER S WITH ACUTE */
+  { 0x02de, 0x015c }, /*                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+  { 0x02fe, 0x015d }, /*                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
+  { 0x01aa, 0x015e }, /*                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
+  { 0x01ba, 0x015f }, /*                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
+  { 0x01a9, 0x0160 }, /*                      Scaron Š LATIN CAPITAL LETTER S WITH CARON */
+  { 0x01b9, 0x0161 }, /*                      scaron š LATIN SMALL LETTER S WITH CARON */
+  { 0x01de, 0x0162 }, /*                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
+  { 0x01fe, 0x0163 }, /*                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
+  { 0x01ab, 0x0164 }, /*                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
+  { 0x01bb, 0x0165 }, /*                      tcaron ť LATIN SMALL LETTER T WITH CARON */
+  { 0x03ac, 0x0166 }, /*                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
+  { 0x03bc, 0x0167 }, /*                      tslash ŧ LATIN SMALL LETTER T WITH STROKE */
+  { 0x03dd, 0x0168 }, /*                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
+  { 0x03fd, 0x0169 }, /*                      utilde ũ LATIN SMALL LETTER U WITH TILDE */
+  { 0x03de, 0x016a }, /*                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
+  { 0x03fe, 0x016b }, /*                     umacron ū LATIN SMALL LETTER U WITH MACRON */
+  { 0x02dd, 0x016c }, /*                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
+  { 0x02fd, 0x016d }, /*                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
+  { 0x01d9, 0x016e }, /*                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
+  { 0x01f9, 0x016f }, /*                       uring ů LATIN SMALL LETTER U WITH RING ABOVE */
+  { 0x01db, 0x0170 }, /*                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+  { 0x01fb, 0x0171 }, /*                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+  { 0x03d9, 0x0172 }, /*                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
+  { 0x03f9, 0x0173 }, /*                     uogonek ų LATIN SMALL LETTER U WITH OGONEK */
+  { 0x13be, 0x0178 }, /*                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
+  { 0x01ac, 0x0179 }, /*                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
+  { 0x01bc, 0x017a }, /*                      zacute ź LATIN SMALL LETTER Z WITH ACUTE */
+  { 0x01af, 0x017b }, /*                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+  { 0x01bf, 0x017c }, /*                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
+  { 0x01ae, 0x017d }, /*                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
+  { 0x01be, 0x017e }, /*                      zcaron ž LATIN SMALL LETTER Z WITH CARON */
+  { 0x08f6, 0x0192 }, /*                    function ƒ LATIN SMALL LETTER F WITH HOOK */
+  { 0x01b7, 0x02c7 }, /*                       caron ˇ CARON */
+  { 0x01a2, 0x02d8 }, /*                       breve ˘ BREVE */
+  { 0x01ff, 0x02d9 }, /*                    abovedot ˙ DOT ABOVE */
+  { 0x01b2, 0x02db }, /*                      ogonek ˛ OGONEK */
+  { 0x01bd, 0x02dd }, /*                 doubleacute ˝ DOUBLE ACUTE ACCENT */
+  { 0x07ae, 0x0385 }, /*        Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
+  { 0x07a1, 0x0386 }, /*           Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
+  { 0x07a2, 0x0388 }, /*         Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
+  { 0x07a3, 0x0389 }, /*             Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
+  { 0x07a4, 0x038a }, /*            Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
+  { 0x07a7, 0x038c }, /*         Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
+  { 0x07a8, 0x038e }, /*         Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
+  { 0x07ab, 0x038f }, /*           Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
+  { 0x07b6, 0x0390 }, /*    Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+  { 0x07c1, 0x0391 }, /*                 Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
+  { 0x07c2, 0x0392 }, /*                  Greek_BETA Β GREEK CAPITAL LETTER BETA */
+  { 0x07c3, 0x0393 }, /*                 Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
+  { 0x07c4, 0x0394 }, /*                 Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
+  { 0x07c5, 0x0395 }, /*               Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
+  { 0x07c6, 0x0396 }, /*                  Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
+  { 0x07c7, 0x0397 }, /*                   Greek_ETA Η GREEK CAPITAL LETTER ETA */
+  { 0x07c8, 0x0398 }, /*                 Greek_THETA Θ GREEK CAPITAL LETTER THETA */
+  { 0x07c9, 0x0399 }, /*                  Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
+  { 0x07ca, 0x039a }, /*                 Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
+  { 0x07cb, 0x039b }, /*                Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
+  { 0x07cc, 0x039c }, /*                    Greek_MU Μ GREEK CAPITAL LETTER MU */
+  { 0x07cd, 0x039d }, /*                    Greek_NU Ν GREEK CAPITAL LETTER NU */
+  { 0x07ce, 0x039e }, /*                    Greek_XI Ξ GREEK CAPITAL LETTER XI */
+  { 0x07cf, 0x039f }, /*               Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
+  { 0x07d0, 0x03a0 }, /*                    Greek_PI Π GREEK CAPITAL LETTER PI */
+  { 0x07d1, 0x03a1 }, /*                   Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
+  { 0x07d2, 0x03a3 }, /*                 Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
+  { 0x07d4, 0x03a4 }, /*                   Greek_TAU Τ GREEK CAPITAL LETTER TAU */
+  { 0x07d5, 0x03a5 }, /*               Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
+  { 0x07d6, 0x03a6 }, /*                   Greek_PHI Φ GREEK CAPITAL LETTER PHI */
+  { 0x07d7, 0x03a7 }, /*                   Greek_CHI Χ GREEK CAPITAL LETTER CHI */
+  { 0x07d8, 0x03a8 }, /*                   Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
+  { 0x07d9, 0x03a9 }, /*                 Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
+  { 0x07a5, 0x03aa }, /*         Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+  { 0x07a9, 0x03ab }, /*       Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07b1, 0x03ac }, /*           Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
+  { 0x07b2, 0x03ad }, /*         Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
+  { 0x07b3, 0x03ae }, /*             Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
+  { 0x07b4, 0x03af }, /*            Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
+  { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+  { 0x07e1, 0x03b1 }, /*                 Greek_alpha α GREEK SMALL LETTER ALPHA */
+  { 0x07e2, 0x03b2 }, /*                  Greek_beta β GREEK SMALL LETTER BETA */
+  { 0x07e3, 0x03b3 }, /*                 Greek_gamma γ GREEK SMALL LETTER GAMMA */
+  { 0x07e4, 0x03b4 }, /*                 Greek_delta δ GREEK SMALL LETTER DELTA */
+  { 0x07e5, 0x03b5 }, /*               Greek_epsilon ε GREEK SMALL LETTER EPSILON */
+  { 0x07e6, 0x03b6 }, /*                  Greek_zeta ζ GREEK SMALL LETTER ZETA */
+  { 0x07e7, 0x03b7 }, /*                   Greek_eta η GREEK SMALL LETTER ETA */
+  { 0x07e8, 0x03b8 }, /*                 Greek_theta θ GREEK SMALL LETTER THETA */
+  { 0x07e9, 0x03b9 }, /*                  Greek_iota ι GREEK SMALL LETTER IOTA */
+  { 0x07ea, 0x03ba }, /*                 Greek_kappa κ GREEK SMALL LETTER KAPPA */
+  { 0x07eb, 0x03bb }, /*                Greek_lambda λ GREEK SMALL LETTER LAMDA */
+  { 0x07ec, 0x03bc }, /*                    Greek_mu μ GREEK SMALL LETTER MU */
+  { 0x07ed, 0x03bd }, /*                    Greek_nu ν GREEK SMALL LETTER NU */
+  { 0x07ee, 0x03be }, /*                    Greek_xi ξ GREEK SMALL LETTER XI */
+  { 0x07ef, 0x03bf }, /*               Greek_omicron ο GREEK SMALL LETTER OMICRON */
+  { 0x07f0, 0x03c0 }, /*                    Greek_pi π GREEK SMALL LETTER PI */
+  { 0x07f1, 0x03c1 }, /*                   Greek_rho ρ GREEK SMALL LETTER RHO */
+  { 0x07f3, 0x03c2 }, /*       Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
+  { 0x07f2, 0x03c3 }, /*                 Greek_sigma σ GREEK SMALL LETTER SIGMA */
+  { 0x07f4, 0x03c4 }, /*                   Greek_tau τ GREEK SMALL LETTER TAU */
+  { 0x07f5, 0x03c5 }, /*               Greek_upsilon υ GREEK SMALL LETTER UPSILON */
+  { 0x07f6, 0x03c6 }, /*                   Greek_phi φ GREEK SMALL LETTER PHI */
+  { 0x07f7, 0x03c7 }, /*                   Greek_chi χ GREEK SMALL LETTER CHI */
+  { 0x07f8, 0x03c8 }, /*                   Greek_psi ψ GREEK SMALL LETTER PSI */
+  { 0x07f9, 0x03c9 }, /*                 Greek_omega ω GREEK SMALL LETTER OMEGA */
+  { 0x07b5, 0x03ca }, /*          Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+  { 0x07b9, 0x03cb }, /*       Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07b7, 0x03cc }, /*         Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
+  { 0x07b8, 0x03cd }, /*         Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
+  { 0x07bb, 0x03ce }, /*           Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
+  { 0x06b3, 0x0401 }, /*                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
+  { 0x06b1, 0x0402 }, /*                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
+  { 0x06b2, 0x0403 }, /*               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
+  { 0x06b4, 0x0404 }, /*                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+  { 0x06b5, 0x0405 }, /*               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
+  { 0x06b6, 0x0406 }, /*                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06b7, 0x0407 }, /*                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
+  { 0x06b8, 0x0408 }, /*                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
+  { 0x06b9, 0x0409 }, /*                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
+  { 0x06ba, 0x040a }, /*                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
+  { 0x06bb, 0x040b }, /*                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
+  { 0x06bc, 0x040c }, /*               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
+  { 0x06be, 0x040e }, /*         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
+  { 0x06bf, 0x040f }, /*               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
+  { 0x06e1, 0x0410 }, /*                  Cyrillic_A А CYRILLIC CAPITAL LETTER A */
+  { 0x06e2, 0x0411 }, /*                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
+  { 0x06f7, 0x0412 }, /*                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
+  { 0x06e7, 0x0413 }, /*                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
+  { 0x06e4, 0x0414 }, /*                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
+  { 0x06e5, 0x0415 }, /*                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
+  { 0x06f6, 0x0416 }, /*                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
+  { 0x06fa, 0x0417 }, /*                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
+  { 0x06e9, 0x0418 }, /*                  Cyrillic_I И CYRILLIC CAPITAL LETTER I */
+  { 0x06ea, 0x0419 }, /*             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
+  { 0x06eb, 0x041a }, /*                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
+  { 0x06ec, 0x041b }, /*                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
+  { 0x06ed, 0x041c }, /*                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
+  { 0x06ee, 0x041d }, /*                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
+  { 0x06ef, 0x041e }, /*                  Cyrillic_O О CYRILLIC CAPITAL LETTER O */
+  { 0x06f0, 0x041f }, /*                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
+  { 0x06f2, 0x0420 }, /*                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
+  { 0x06f3, 0x0421 }, /*                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
+  { 0x06f4, 0x0422 }, /*                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
+  { 0x06f5, 0x0423 }, /*                  Cyrillic_U У CYRILLIC CAPITAL LETTER U */
+  { 0x06e6, 0x0424 }, /*                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
+  { 0x06e8, 0x0425 }, /*                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
+  { 0x06e3, 0x0426 }, /*                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
+  { 0x06fe, 0x0427 }, /*                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
+  { 0x06fb, 0x0428 }, /*                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
+  { 0x06fd, 0x0429 }, /*              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
+  { 0x06ff, 0x042a }, /*           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
+  { 0x06f9, 0x042b }, /*               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
+  { 0x06f8, 0x042c }, /*           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
+  { 0x06fc, 0x042d }, /*                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
+  { 0x06e0, 0x042e }, /*                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
+  { 0x06f1, 0x042f }, /*                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
+  { 0x06c1, 0x0430 }, /*                  Cyrillic_a а CYRILLIC SMALL LETTER A */
+  { 0x06c2, 0x0431 }, /*                 Cyrillic_be б CYRILLIC SMALL LETTER BE */
+  { 0x06d7, 0x0432 }, /*                 Cyrillic_ve в CYRILLIC SMALL LETTER VE */
+  { 0x06c7, 0x0433 }, /*                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
+  { 0x06c4, 0x0434 }, /*                 Cyrillic_de д CYRILLIC SMALL LETTER DE */
+  { 0x06c5, 0x0435 }, /*                 Cyrillic_ie е CYRILLIC SMALL LETTER IE */
+  { 0x06d6, 0x0436 }, /*                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
+  { 0x06da, 0x0437 }, /*                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
+  { 0x06c9, 0x0438 }, /*                  Cyrillic_i и CYRILLIC SMALL LETTER I */
+  { 0x06ca, 0x0439 }, /*             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
+  { 0x06cb, 0x043a }, /*                 Cyrillic_ka к CYRILLIC SMALL LETTER KA */
+  { 0x06cc, 0x043b }, /*                 Cyrillic_el л CYRILLIC SMALL LETTER EL */
+  { 0x06cd, 0x043c }, /*                 Cyrillic_em м CYRILLIC SMALL LETTER EM */
+  { 0x06ce, 0x043d }, /*                 Cyrillic_en н CYRILLIC SMALL LETTER EN */
+  { 0x06cf, 0x043e }, /*                  Cyrillic_o о CYRILLIC SMALL LETTER O */
+  { 0x06d0, 0x043f }, /*                 Cyrillic_pe п CYRILLIC SMALL LETTER PE */
+  { 0x06d2, 0x0440 }, /*                 Cyrillic_er р CYRILLIC SMALL LETTER ER */
+  { 0x06d3, 0x0441 }, /*                 Cyrillic_es с CYRILLIC SMALL LETTER ES */
+  { 0x06d4, 0x0442 }, /*                 Cyrillic_te т CYRILLIC SMALL LETTER TE */
+  { 0x06d5, 0x0443 }, /*                  Cyrillic_u у CYRILLIC SMALL LETTER U */
+  { 0x06c6, 0x0444 }, /*                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
+  { 0x06c8, 0x0445 }, /*                 Cyrillic_ha х CYRILLIC SMALL LETTER HA */
+  { 0x06c3, 0x0446 }, /*                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
+  { 0x06de, 0x0447 }, /*                Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
+  { 0x06db, 0x0448 }, /*                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
+  { 0x06dd, 0x0449 }, /*              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
+  { 0x06df, 0x044a }, /*           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
+  { 0x06d9, 0x044b }, /*               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
+  { 0x06d8, 0x044c }, /*           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
+  { 0x06dc, 0x044d }, /*                  Cyrillic_e э CYRILLIC SMALL LETTER E */
+  { 0x06c0, 0x044e }, /*                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
+  { 0x06d1, 0x044f }, /*                 Cyrillic_ya я CYRILLIC SMALL LETTER YA */
+  { 0x06a3, 0x0451 }, /*                 Cyrillic_io ё CYRILLIC SMALL LETTER IO */
+  { 0x06a1, 0x0452 }, /*                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
+  { 0x06a2, 0x0453 }, /*               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
+  { 0x06a4, 0x0454 }, /*                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
+  { 0x06a5, 0x0455 }, /*               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
+  { 0x06a6, 0x0456 }, /*                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06a7, 0x0457 }, /*                Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
+  { 0x06a8, 0x0458 }, /*                 Cyrillic_je ј CYRILLIC SMALL LETTER JE */
+  { 0x06a9, 0x0459 }, /*                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
+  { 0x06aa, 0x045a }, /*                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
+  { 0x06ab, 0x045b }, /*                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
+  { 0x06ac, 0x045c }, /*               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
+  { 0x06ae, 0x045e }, /*         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
+  { 0x06af, 0x045f }, /*               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
+  { 0x0ce0, 0x05d0 }, /*                hebrew_aleph א HEBREW LETTER ALEF */
+  { 0x0ce1, 0x05d1 }, /*                  hebrew_bet ב HEBREW LETTER BET */
+  { 0x0ce2, 0x05d2 }, /*                hebrew_gimel ג HEBREW LETTER GIMEL */
+  { 0x0ce3, 0x05d3 }, /*                hebrew_dalet ד HEBREW LETTER DALET */
+  { 0x0ce4, 0x05d4 }, /*                   hebrew_he ה HEBREW LETTER HE */
+  { 0x0ce5, 0x05d5 }, /*                  hebrew_waw ו HEBREW LETTER VAV */
+  { 0x0ce6, 0x05d6 }, /*                 hebrew_zain ז HEBREW LETTER ZAYIN */
+  { 0x0ce7, 0x05d7 }, /*                 hebrew_chet ח HEBREW LETTER HET */
+  { 0x0ce8, 0x05d8 }, /*                  hebrew_tet ט HEBREW LETTER TET */
+  { 0x0ce9, 0x05d9 }, /*                  hebrew_yod י HEBREW LETTER YOD */
+  { 0x0cea, 0x05da }, /*            hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
+  { 0x0ceb, 0x05db }, /*                 hebrew_kaph כ HEBREW LETTER KAF */
+  { 0x0cec, 0x05dc }, /*                hebrew_lamed ל HEBREW LETTER LAMED */
+  { 0x0ced, 0x05dd }, /*             hebrew_finalmem ם HEBREW LETTER FINAL MEM */
+  { 0x0cee, 0x05de }, /*                  hebrew_mem מ HEBREW LETTER MEM */
+  { 0x0cef, 0x05df }, /*             hebrew_finalnun ן HEBREW LETTER FINAL NUN */
+  { 0x0cf0, 0x05e0 }, /*                  hebrew_nun נ HEBREW LETTER NUN */
+  { 0x0cf1, 0x05e1 }, /*               hebrew_samech ס HEBREW LETTER SAMEKH */
+  { 0x0cf2, 0x05e2 }, /*                 hebrew_ayin ע HEBREW LETTER AYIN */
+  { 0x0cf3, 0x05e3 }, /*              hebrew_finalpe ף HEBREW LETTER FINAL PE */
+  { 0x0cf4, 0x05e4 }, /*                   hebrew_pe פ HEBREW LETTER PE */
+  { 0x0cf5, 0x05e5 }, /*            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
+  { 0x0cf6, 0x05e6 }, /*                 hebrew_zade צ HEBREW LETTER TSADI */
+  { 0x0cf7, 0x05e7 }, /*                 hebrew_qoph ק HEBREW LETTER QOF */
+  { 0x0cf8, 0x05e8 }, /*                 hebrew_resh ר HEBREW LETTER RESH */
+  { 0x0cf9, 0x05e9 }, /*                 hebrew_shin ש HEBREW LETTER SHIN */
+  { 0x0cfa, 0x05ea }, /*                  hebrew_taw ת HEBREW LETTER TAV */
+  { 0x05ac, 0x060c }, /*                Arabic_comma ، ARABIC COMMA */
+  { 0x05bb, 0x061b }, /*            Arabic_semicolon ؛ ARABIC SEMICOLON */
+  { 0x05bf, 0x061f }, /*        Arabic_question_mark ؟ ARABIC QUESTION MARK */
+  { 0x05c1, 0x0621 }, /*                Arabic_hamza ء ARABIC LETTER HAMZA */
+  { 0x05c2, 0x0622 }, /*          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
+  { 0x05c3, 0x0623 }, /*          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
+  { 0x05c4, 0x0624 }, /*           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
+  { 0x05c5, 0x0625 }, /*       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
+  { 0x05c6, 0x0626 }, /*           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
+  { 0x05c7, 0x0627 }, /*                 Arabic_alef ا ARABIC LETTER ALEF */
+  { 0x05c8, 0x0628 }, /*                  Arabic_beh ب ARABIC LETTER BEH */
+  { 0x05c9, 0x0629 }, /*           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
+  { 0x05ca, 0x062a }, /*                  Arabic_teh ت ARABIC LETTER TEH */
+  { 0x05cb, 0x062b }, /*                 Arabic_theh ث ARABIC LETTER THEH */
+  { 0x05cc, 0x062c }, /*                 Arabic_jeem ج ARABIC LETTER JEEM */
+  { 0x05cd, 0x062d }, /*                  Arabic_hah ح ARABIC LETTER HAH */
+  { 0x05ce, 0x062e }, /*                 Arabic_khah خ ARABIC LETTER KHAH */
+  { 0x05cf, 0x062f }, /*                  Arabic_dal د ARABIC LETTER DAL */
+  { 0x05d0, 0x0630 }, /*                 Arabic_thal ذ ARABIC LETTER THAL */
+  { 0x05d1, 0x0631 }, /*                   Arabic_ra ر ARABIC LETTER REH */
+  { 0x05d2, 0x0632 }, /*                 Arabic_zain ز ARABIC LETTER ZAIN */
+  { 0x05d3, 0x0633 }, /*                 Arabic_seen س ARABIC LETTER SEEN */
+  { 0x05d4, 0x0634 }, /*                Arabic_sheen ش ARABIC LETTER SHEEN */
+  { 0x05d5, 0x0635 }, /*                  Arabic_sad ص ARABIC LETTER SAD */
+  { 0x05d6, 0x0636 }, /*                  Arabic_dad ض ARABIC LETTER DAD */
+  { 0x05d7, 0x0637 }, /*                  Arabic_tah ط ARABIC LETTER TAH */
+  { 0x05d8, 0x0638 }, /*                  Arabic_zah ظ ARABIC LETTER ZAH */
+  { 0x05d9, 0x0639 }, /*                  Arabic_ain ع ARABIC LETTER AIN */
+  { 0x05da, 0x063a }, /*                Arabic_ghain غ ARABIC LETTER GHAIN */
+  { 0x05e0, 0x0640 }, /*              Arabic_tatweel ـ ARABIC TATWEEL */
+  { 0x05e1, 0x0641 }, /*                  Arabic_feh ف ARABIC LETTER FEH */
+  { 0x05e2, 0x0642 }, /*                  Arabic_qaf ق ARABIC LETTER QAF */
+  { 0x05e3, 0x0643 }, /*                  Arabic_kaf ك ARABIC LETTER KAF */
+  { 0x05e4, 0x0644 }, /*                  Arabic_lam ل ARABIC LETTER LAM */
+  { 0x05e5, 0x0645 }, /*                 Arabic_meem م ARABIC LETTER MEEM */
+  { 0x05e6, 0x0646 }, /*                 Arabic_noon ن ARABIC LETTER NOON */
+  { 0x05e7, 0x0647 }, /*                   Arabic_ha ه ARABIC LETTER HEH */
+  { 0x05e8, 0x0648 }, /*                  Arabic_waw و ARABIC LETTER WAW */
+  { 0x05e9, 0x0649 }, /*          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
+  { 0x05ea, 0x064a }, /*                  Arabic_yeh ي ARABIC LETTER YEH */
+  { 0x05eb, 0x064b }, /*             Arabic_fathatan ً ARABIC FATHATAN */
+  { 0x05ec, 0x064c }, /*             Arabic_dammatan ٌ ARABIC DAMMATAN */
+  { 0x05ed, 0x064d }, /*             Arabic_kasratan ٍ ARABIC KASRATAN */
+  { 0x05ee, 0x064e }, /*                Arabic_fatha َ ARABIC FATHA */
+  { 0x05ef, 0x064f }, /*                Arabic_damma ُ ARABIC DAMMA */
+  { 0x05f0, 0x0650 }, /*                Arabic_kasra ِ ARABIC KASRA */
+  { 0x05f1, 0x0651 }, /*               Arabic_shadda ّ ARABIC SHADDA */
+  { 0x05f2, 0x0652 }, /*                Arabic_sukun ْ ARABIC SUKUN */
+  { 0x0da1, 0x0e01 }, /*                  Thai_kokai ก THAI CHARACTER KO KAI */
+  { 0x0da2, 0x0e02 }, /*                Thai_khokhai ข THAI CHARACTER KHO KHAI */
+  { 0x0da3, 0x0e03 }, /*               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
+  { 0x0da4, 0x0e04 }, /*               Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
+  { 0x0da5, 0x0e05 }, /*                Thai_khokhon ฅ THAI CHARACTER KHO KHON */
+  { 0x0da6, 0x0e06 }, /*             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
+  { 0x0da7, 0x0e07 }, /*                 Thai_ngongu ง THAI CHARACTER NGO NGU */
+  { 0x0da8, 0x0e08 }, /*                Thai_chochan จ THAI CHARACTER CHO CHAN */
+  { 0x0da9, 0x0e09 }, /*               Thai_choching ฉ THAI CHARACTER CHO CHING */
+  { 0x0daa, 0x0e0a }, /*               Thai_chochang ช THAI CHARACTER CHO CHANG */
+  { 0x0dab, 0x0e0b }, /*                   Thai_soso ซ THAI CHARACTER SO SO */
+  { 0x0dac, 0x0e0c }, /*                Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
+  { 0x0dad, 0x0e0d }, /*                 Thai_yoying ญ THAI CHARACTER YO YING */
+  { 0x0dae, 0x0e0e }, /*                Thai_dochada ฎ THAI CHARACTER DO CHADA */
+  { 0x0daf, 0x0e0f }, /*                Thai_topatak ฏ THAI CHARACTER TO PATAK */
+  { 0x0db0, 0x0e10 }, /*                Thai_thothan ฐ THAI CHARACTER THO THAN */
+  { 0x0db1, 0x0e11 }, /*          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
+  { 0x0db2, 0x0e12 }, /*             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
+  { 0x0db3, 0x0e13 }, /*                  Thai_nonen ณ THAI CHARACTER NO NEN */
+  { 0x0db4, 0x0e14 }, /*                  Thai_dodek ด THAI CHARACTER DO DEK */
+  { 0x0db5, 0x0e15 }, /*                  Thai_totao ต THAI CHARACTER TO TAO */
+  { 0x0db6, 0x0e16 }, /*               Thai_thothung ถ THAI CHARACTER THO THUNG */
+  { 0x0db7, 0x0e17 }, /*              Thai_thothahan ท THAI CHARACTER THO THAHAN */
+  { 0x0db8, 0x0e18 }, /*               Thai_thothong ธ THAI CHARACTER THO THONG */
+  { 0x0db9, 0x0e19 }, /*                   Thai_nonu น THAI CHARACTER NO NU */
+  { 0x0dba, 0x0e1a }, /*               Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
+  { 0x0dbb, 0x0e1b }, /*                  Thai_popla ป THAI CHARACTER PO PLA */
+  { 0x0dbc, 0x0e1c }, /*               Thai_phophung ผ THAI CHARACTER PHO PHUNG */
+  { 0x0dbd, 0x0e1d }, /*                   Thai_fofa ฝ THAI CHARACTER FO FA */
+  { 0x0dbe, 0x0e1e }, /*                Thai_phophan พ THAI CHARACTER PHO PHAN */
+  { 0x0dbf, 0x0e1f }, /*                  Thai_fofan ฟ THAI CHARACTER FO FAN */
+  { 0x0dc0, 0x0e20 }, /*             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
+  { 0x0dc1, 0x0e21 }, /*                   Thai_moma ม THAI CHARACTER MO MA */
+  { 0x0dc2, 0x0e22 }, /*                  Thai_yoyak ย THAI CHARACTER YO YAK */
+  { 0x0dc3, 0x0e23 }, /*                  Thai_rorua ร THAI CHARACTER RO RUA */
+  { 0x0dc4, 0x0e24 }, /*                     Thai_ru ฤ THAI CHARACTER RU */
+  { 0x0dc5, 0x0e25 }, /*                 Thai_loling ล THAI CHARACTER LO LING */
+  { 0x0dc6, 0x0e26 }, /*                     Thai_lu ฦ THAI CHARACTER LU */
+  { 0x0dc7, 0x0e27 }, /*                 Thai_wowaen ว THAI CHARACTER WO WAEN */
+  { 0x0dc8, 0x0e28 }, /*                 Thai_sosala ศ THAI CHARACTER SO SALA */
+  { 0x0dc9, 0x0e29 }, /*                 Thai_sorusi ษ THAI CHARACTER SO RUSI */
+  { 0x0dca, 0x0e2a }, /*                  Thai_sosua ส THAI CHARACTER SO SUA */
+  { 0x0dcb, 0x0e2b }, /*                  Thai_hohip ห THAI CHARACTER HO HIP */
+  { 0x0dcc, 0x0e2c }, /*                Thai_lochula ฬ THAI CHARACTER LO CHULA */
+  { 0x0dcd, 0x0e2d }, /*                   Thai_oang อ THAI CHARACTER O ANG */
+  { 0x0dce, 0x0e2e }, /*               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
+  { 0x0dcf, 0x0e2f }, /*              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
+  { 0x0dd0, 0x0e30 }, /*                  Thai_saraa ะ THAI CHARACTER SARA A */
+  { 0x0dd1, 0x0e31 }, /*             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
+  { 0x0dd2, 0x0e32 }, /*                 Thai_saraaa า THAI CHARACTER SARA AA */
+  { 0x0dd3, 0x0e33 }, /*                 Thai_saraam ำ THAI CHARACTER SARA AM */
+  { 0x0dd4, 0x0e34 }, /*                  Thai_sarai ิ THAI CHARACTER SARA I */
+  { 0x0dd5, 0x0e35 }, /*                 Thai_saraii ี THAI CHARACTER SARA II */
+  { 0x0dd6, 0x0e36 }, /*                 Thai_saraue ึ THAI CHARACTER SARA UE */
+  { 0x0dd7, 0x0e37 }, /*                Thai_sarauee ื THAI CHARACTER SARA UEE */
+  { 0x0dd8, 0x0e38 }, /*                  Thai_sarau ุ THAI CHARACTER SARA U */
+  { 0x0dd9, 0x0e39 }, /*                 Thai_sarauu ู THAI CHARACTER SARA UU */
+  { 0x0dda, 0x0e3a }, /*                Thai_phinthu ฺ THAI CHARACTER PHINTHU */
+  { 0x0ddf, 0x0e3f }, /*                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
+  { 0x0de0, 0x0e40 }, /*                  Thai_sarae เ THAI CHARACTER SARA E */
+  { 0x0de1, 0x0e41 }, /*                 Thai_saraae แ THAI CHARACTER SARA AE */
+  { 0x0de2, 0x0e42 }, /*                  Thai_sarao โ THAI CHARACTER SARA O */
+  { 0x0de3, 0x0e43 }, /*          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
+  { 0x0de4, 0x0e44 }, /*         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
+  { 0x0de5, 0x0e45 }, /*            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
+  { 0x0de6, 0x0e46 }, /*               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
+  { 0x0de7, 0x0e47 }, /*              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
+  { 0x0de8, 0x0e48 }, /*                  Thai_maiek ่ THAI CHARACTER MAI EK */
+  { 0x0de9, 0x0e49 }, /*                 Thai_maitho ้ THAI CHARACTER MAI THO */
+  { 0x0dea, 0x0e4a }, /*                 Thai_maitri ๊ THAI CHARACTER MAI TRI */
+  { 0x0deb, 0x0e4b }, /*            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
+  { 0x0dec, 0x0e4c }, /*            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
+  { 0x0ded, 0x0e4d }, /*               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
+  { 0x0df0, 0x0e50 }, /*                 Thai_leksun ๐ THAI DIGIT ZERO */
+  { 0x0df1, 0x0e51 }, /*                Thai_leknung ๑ THAI DIGIT ONE */
+  { 0x0df2, 0x0e52 }, /*                Thai_leksong ๒ THAI DIGIT TWO */
+  { 0x0df3, 0x0e53 }, /*                 Thai_leksam ๓ THAI DIGIT THREE */
+  { 0x0df4, 0x0e54 }, /*                  Thai_leksi ๔ THAI DIGIT FOUR */
+  { 0x0df5, 0x0e55 }, /*                  Thai_lekha ๕ THAI DIGIT FIVE */
+  { 0x0df6, 0x0e56 }, /*                 Thai_lekhok ๖ THAI DIGIT SIX */
+  { 0x0df7, 0x0e57 }, /*                Thai_lekchet ๗ THAI DIGIT SEVEN */
+  { 0x0df8, 0x0e58 }, /*                Thai_lekpaet ๘ THAI DIGIT EIGHT */
+  { 0x0df9, 0x0e59 }, /*                 Thai_lekkao ๙ THAI DIGIT NINE */
+  { 0x0ed4, 0x11a8 }, /*             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
+  { 0x0ed5, 0x11a9 }, /*        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
+  { 0x0ed6, 0x11aa }, /*         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
+  { 0x0ed7, 0x11ab }, /*              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
+  { 0x0ed8, 0x11ac }, /*         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
+  { 0x0ed9, 0x11ad }, /*         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
+  { 0x0eda, 0x11ae }, /*             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
+  { 0x0edb, 0x11af }, /*              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
+  { 0x0edc, 0x11b0 }, /*        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
+  { 0x0edd, 0x11b1 }, /*         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
+  { 0x0ede, 0x11b2 }, /*         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
+  { 0x0edf, 0x11b3 }, /*          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
+  { 0x0ee0, 0x11b4 }, /*         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
+  { 0x0ee1, 0x11b5 }, /*        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
+  { 0x0ee2, 0x11b6 }, /*         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
+  { 0x0ee3, 0x11b7 }, /*              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
+  { 0x0ee4, 0x11b8 }, /*              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
+  { 0x0ee5, 0x11b9 }, /*          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
+  { 0x0ee6, 0x11ba }, /*               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
+  { 0x0ee7, 0x11bb }, /*          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
+  { 0x0ee8, 0x11bc }, /*              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
+  { 0x0ee9, 0x11bd }, /*              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
+  { 0x0eea, 0x11be }, /*              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
+  { 0x0eeb, 0x11bf }, /*             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
+  { 0x0eec, 0x11c0 }, /*              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
+  { 0x0eed, 0x11c1 }, /*             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
+  { 0x0eee, 0x11c2 }, /*              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
+  { 0x0ef8, 0x11eb }, /*            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
+  { 0x0efa, 0x11f9 }, /*        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
+  { 0x0aa2, 0x2002 }, /*                     enspace   EN SPACE */
+  { 0x0aa1, 0x2003 }, /*                     emspace   EM SPACE */
+  { 0x0aa3, 0x2004 }, /*                    em3space   THREE-PER-EM SPACE */
+  { 0x0aa4, 0x2005 }, /*                    em4space   FOUR-PER-EM SPACE */
+  { 0x0aa5, 0x2007 }, /*                  digitspace   FIGURE SPACE */
+  { 0x0aa6, 0x2008 }, /*                  punctspace   PUNCTUATION SPACE */
+  { 0x0aa7, 0x2009 }, /*                   thinspace   THIN SPACE */
+  { 0x0aa8, 0x200a }, /*                   hairspace   HAIR SPACE */
+  { 0x0abb, 0x2012 }, /*                     figdash ‒ FIGURE DASH */
+  { 0x0aaa, 0x2013 }, /*                      endash – EN DASH */
+  { 0x0aa9, 0x2014 }, /*                      emdash — EM DASH */
+  { 0x07af, 0x2015 }, /*              Greek_horizbar ― HORIZONTAL BAR */
+  { 0x0cdf, 0x2017 }, /*        hebrew_doublelowline ‗ DOUBLE LOW LINE */
+  { 0x0ad0, 0x2018 }, /*         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
+  { 0x0ad1, 0x2019 }, /*        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
+  { 0x0afd, 0x201a }, /*          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
+  { 0x0ad2, 0x201c }, /*         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
+  { 0x0ad3, 0x201d }, /*        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
+  { 0x0afe, 0x201e }, /*          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
+  { 0x0af1, 0x2020 }, /*                      dagger † DAGGER */
+  { 0x0af2, 0x2021 }, /*                doubledagger ‡ DOUBLE DAGGER */
+  { 0x0ae6, 0x2022 }, /*          enfilledcircbullet • BULLET */
+  { 0x0aae, 0x2026 }, /*                    ellipsis … HORIZONTAL ELLIPSIS */
+  { 0x0ad6, 0x2032 }, /*                     minutes ′ PRIME */
+  { 0x0ad7, 0x2033 }, /*                     seconds ″ DOUBLE PRIME */
+  { 0x0afc, 0x2038 }, /*                       caret ‸ CARET */
+  { 0x047e, 0x203e }, /*                    overline ‾ OVERLINE */
+  { 0x20a0, 0x20a0 }, /*                     EcuSign ₠ EURO-CURRENCY SIGN */
+  { 0x20a1, 0x20a1 }, /*                   ColonSign ₡ COLON SIGN */
+  { 0x20a2, 0x20a2 }, /*                CruzeiroSign ₢ CRUZEIRO SIGN */
+  { 0x20a3, 0x20a3 }, /*                  FFrancSign ₣ FRENCH FRANC SIGN */
+  { 0x20a4, 0x20a4 }, /*                    LiraSign ₤ LIRA SIGN */
+  { 0x20a5, 0x20a5 }, /*                    MillSign ₥ MILL SIGN */
+  { 0x20a6, 0x20a6 }, /*                   NairaSign ₦ NAIRA SIGN */
+  { 0x20a7, 0x20a7 }, /*                  PesetaSign ₧ PESETA SIGN */
+  { 0x20a8, 0x20a8 }, /*                   RupeeSign ₨ RUPEE SIGN */
+  { 0x0eff, 0x20a9 }, /*                  Korean_Won ₩ WON SIGN */
+  { 0x20a9, 0x20a9 }, /*                     WonSign ₩ WON SIGN */
+  { 0x20aa, 0x20aa }, /*               NewSheqelSign ₪ NEW SHEQEL SIGN */
+  { 0x20ab, 0x20ab }, /*                    DongSign ₫ DONG SIGN */
+  { 0x20ac, 0x20ac }, /*                    EuroSign € EURO SIGN */
+  { 0x0ab8, 0x2105 }, /*                      careof ℅ CARE OF */
+  { 0x06b0, 0x2116 }, /*                  numerosign № NUMERO SIGN */
+  { 0x0afb, 0x2117 }, /*         phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
+  { 0x0ad4, 0x211e }, /*                prescription ℞ PRESCRIPTION TAKE */
+  { 0x0ac9, 0x2122 }, /*                   trademark ™ TRADE MARK SIGN */
+  { 0x0ab0, 0x2153 }, /*                    onethird ⅓ VULGAR FRACTION ONE THIRD */
+  { 0x0ab1, 0x2154 }, /*                   twothirds ⅔ VULGAR FRACTION TWO THIRDS */
+  { 0x0ab2, 0x2155 }, /*                    onefifth ⅕ VULGAR FRACTION ONE FIFTH */
+  { 0x0ab3, 0x2156 }, /*                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
+  { 0x0ab4, 0x2157 }, /*                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
+  { 0x0ab5, 0x2158 }, /*                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
+  { 0x0ab6, 0x2159 }, /*                    onesixth ⅙ VULGAR FRACTION ONE SIXTH */
+  { 0x0ab7, 0x215a }, /*                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
+  { 0x0ac3, 0x215b }, /*                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
+  { 0x0ac4, 0x215c }, /*                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
+  { 0x0ac5, 0x215d }, /*                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
+  { 0x0ac6, 0x215e }, /*                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
+  { 0x08fb, 0x2190 }, /*                   leftarrow ← LEFTWARDS ARROW */
+  { 0x08fc, 0x2191 }, /*                     uparrow ↑ UPWARDS ARROW */
+  { 0x08fd, 0x2192 }, /*                  rightarrow → RIGHTWARDS ARROW */
+  { 0x08fe, 0x2193 }, /*                   downarrow ↓ DOWNWARDS ARROW */
+  { 0x08ce, 0x21d2 }, /*                     implies ⇒ RIGHTWARDS DOUBLE ARROW */
+  { 0x08cd, 0x21d4 }, /*                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
+  { 0x08ef, 0x2202 }, /*           partialderivative ∂ PARTIAL DIFFERENTIAL */
+  { 0x08c5, 0x2207 }, /*                       nabla ∇ NABLA */
+  { 0x0bca, 0x2218 }, /*                         jot ∘ RING OPERATOR */
+  { 0x08d6, 0x221a }, /*                     radical √ SQUARE ROOT */
+  { 0x08c1, 0x221d }, /*                   variation ∝ PROPORTIONAL TO */
+  { 0x08c2, 0x221e }, /*                    infinity ∞ INFINITY */
+  { 0x08de, 0x2227 }, /*                  logicaland ∧ LOGICAL AND */
+  { 0x0ba9, 0x2227 }, /*                     upcaret ∧ LOGICAL AND */
+  { 0x08df, 0x2228 }, /*                   logicalor ∨ LOGICAL OR */
+  { 0x0ba8, 0x2228 }, /*                   downcaret ∨ LOGICAL OR */
+  { 0x08dc, 0x2229 }, /*                intersection ∩ INTERSECTION */
+  { 0x0bc3, 0x2229 }, /*                      upshoe ∩ INTERSECTION */
+  { 0x08dd, 0x222a }, /*                       union ∪ UNION */
+  { 0x0bd6, 0x222a }, /*                    downshoe ∪ UNION */
+  { 0x08bf, 0x222b }, /*                    integral ∫ INTEGRAL */
+  { 0x08c0, 0x2234 }, /*                   therefore ∴ THEREFORE */
+  { 0x08c8, 0x2245 }, /*                 approximate ≅ APPROXIMATELY EQUAL TO */
+  { 0x08bd, 0x2260 }, /*                    notequal ≠ NOT EQUAL TO */
+  { 0x08cf, 0x2261 }, /*                   identical ≡ IDENTICAL TO */
+  { 0x08bc, 0x2264 }, /*               lessthanequal ≤ LESS-THAN OR EQUAL TO */
+  { 0x08be, 0x2265 }, /*            greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
+  { 0x08da, 0x2282 }, /*                  includedin ⊂ SUBSET OF */
+  { 0x0bda, 0x2282 }, /*                    leftshoe ⊂ SUBSET OF */
+  { 0x08db, 0x2283 }, /*                    includes ⊃ SUPERSET OF */
+  { 0x0bd8, 0x2283 }, /*                   rightshoe ⊃ SUPERSET OF */
+  { 0x0bfc, 0x22a2 }, /*                   righttack ⊢ RIGHT TACK */
+  { 0x0bdc, 0x22a3 }, /*                    lefttack ⊣ LEFT TACK */
+  { 0x0bc2, 0x22a4 }, /*                    downtack ⊤ DOWN TACK */
+  { 0x0bce, 0x22a5 }, /*                      uptack ⊥ UP TACK */
+  { 0x0bd3, 0x2308 }, /*                     upstile ⌈ LEFT CEILING */
+  { 0x0bc4, 0x230a }, /*                   downstile ⌊ LEFT FLOOR */
+  { 0x0afa, 0x2315 }, /*           telephonerecorder ⌕ TELEPHONE RECORDER */
+  { 0x08a4, 0x2320 }, /*                 topintegral ⌠ TOP HALF INTEGRAL */
+  { 0x08a5, 0x2321 }, /*                 botintegral ⌡ BOTTOM HALF INTEGRAL */
+  { 0x0abc, 0x2329 }, /*            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
+  { 0x0abe, 0x232a }, /*           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
+  { 0x0bcc, 0x2395 }, /*                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */
+  { 0x09e2, 0x2409 }, /*                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
+  { 0x09e5, 0x240a }, /*                          lf ␊ SYMBOL FOR LINE FEED */
+  { 0x09e9, 0x240b }, /*                          vt ␋ SYMBOL FOR VERTICAL TABULATION */
+  { 0x09e3, 0x240c }, /*                          ff ␌ SYMBOL FOR FORM FEED */
+  { 0x09e4, 0x240d }, /*                          cr ␍ SYMBOL FOR CARRIAGE RETURN */
+  { 0x09df, 0x2422 }, /*                       blank ␢ BLANK SYMBOL */
+  { 0x09e8, 0x2424 }, /*                          nl ␤ SYMBOL FOR NEWLINE */
+  { 0x09f1, 0x2500 }, /*              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
+  { 0x08a6, 0x2502 }, /*               vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
+  { 0x09f8, 0x2502 }, /*                     vertbar │ BOX DRAWINGS LIGHT VERTICAL */
+  { 0x09ec, 0x250c }, /*                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+  { 0x09eb, 0x2510 }, /*               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
+  { 0x09ed, 0x2514 }, /*               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
+  { 0x09ea, 0x2518 }, /*              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
+  { 0x09f4, 0x251c }, /*                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+  { 0x09f5, 0x2524 }, /*                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+  { 0x09f7, 0x252c }, /*                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+  { 0x09f6, 0x2534 }, /*                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+  { 0x09ee, 0x253c }, /*               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+  { 0x09e1, 0x2592 }, /*                checkerboard ▒ MEDIUM SHADE */
+  { 0x0adf, 0x25a0 }, /*                emfilledrect ■ BLACK SQUARE */
+  { 0x0acf, 0x25a1 }, /*             emopenrectangle □ WHITE SQUARE */
+  { 0x0ae7, 0x25aa }, /*            enfilledsqbullet ▪ BLACK SMALL SQUARE */
+  { 0x0ae1, 0x25ab }, /*          enopensquarebullet ▫ WHITE SMALL SQUARE */
+  { 0x0adb, 0x25ac }, /*            filledrectbullet ▬ BLACK RECTANGLE */
+  { 0x0ae2, 0x25ad }, /*              openrectbullet ▭ WHITE RECTANGLE */
+  { 0x0ae8, 0x25b2 }, /*           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
+  { 0x0ae3, 0x25b3 }, /*             opentribulletup △ WHITE UP-POINTING TRIANGLE */
+  { 0x0add, 0x25b6 }, /*        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
+  { 0x0acd, 0x25b7 }, /*           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
+  { 0x0ae9, 0x25bc }, /*         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
+  { 0x0ae4, 0x25bd }, /*           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
+  { 0x0adc, 0x25c0 }, /*         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
+  { 0x0acc, 0x25c1 }, /*            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
+  { 0x09e0, 0x25c6 }, /*                soliddiamond ◆ BLACK DIAMOND */
+  { 0x0ace, 0x25cb }, /*                emopencircle ○ WHITE CIRCLE */
+  { 0x0bcf, 0x25cb }, /*                      circle ○ WHITE CIRCLE */
+  { 0x0ade, 0x25cf }, /*              emfilledcircle ● BLACK CIRCLE */
+  { 0x0ae0, 0x25e6 }, /*            enopencircbullet ◦ WHITE BULLET */
+  { 0x0ae5, 0x2606 }, /*                    openstar ☆ WHITE STAR */
+  { 0x0af9, 0x260e }, /*                   telephone ☎ BLACK TELEPHONE */
+  { 0x0aca, 0x2613 }, /*               signaturemark ☓ SALTIRE */
+  { 0x0aea, 0x261c }, /*                 leftpointer ☜ WHITE LEFT POINTING INDEX */
+  { 0x0aeb, 0x261e }, /*                rightpointer ☞ WHITE RIGHT POINTING INDEX */
+  { 0x0af8, 0x2640 }, /*                femalesymbol ♀ FEMALE SIGN */
+  { 0x0af7, 0x2642 }, /*                  malesymbol ♂ MALE SIGN */
+  { 0x0aec, 0x2663 }, /*                        club ♣ BLACK CLUB SUIT */
+  { 0x0aee, 0x2665 }, /*                       heart ♥ BLACK HEART SUIT */
+  { 0x0aed, 0x2666 }, /*                     diamond ♦ BLACK DIAMOND SUIT */
+  { 0x0af6, 0x266d }, /*                 musicalflat ♭ MUSIC FLAT SIGN */
+  { 0x0af5, 0x266f }, /*                musicalsharp ♯ MUSIC SHARP SIGN */
+  { 0x0af3, 0x2713 }, /*                   checkmark ✓ CHECK MARK */
+  { 0x0af4, 0x2717 }, /*                 ballotcross ✗ BALLOT X */
+  { 0x0ad9, 0x271d }, /*                  latincross ✝ LATIN CROSS */
+  { 0x0af0, 0x2720 }, /*                maltesecross ✠ MALTESE CROSS */
+  { 0x04a4, 0x3001 }, /*                  kana_comma 、 IDEOGRAPHIC COMMA */
+  { 0x04a1, 0x3002 }, /*               kana_fullstop 。 IDEOGRAPHIC FULL STOP */
+  { 0x04a2, 0x300c }, /*         kana_openingbracket 「 LEFT CORNER BRACKET */
+  { 0x04a3, 0x300d }, /*         kana_closingbracket 」 RIGHT CORNER BRACKET */
+  { 0x04de, 0x309b }, /*                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
+  { 0x04df, 0x309c }, /*             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+  { 0x04a7, 0x30a1 }, /*                      kana_a ァ KATAKANA LETTER SMALL A */
+  { 0x04b1, 0x30a2 }, /*                      kana_A ア KATAKANA LETTER A */
+  { 0x04a8, 0x30a3 }, /*                      kana_i ィ KATAKANA LETTER SMALL I */
+  { 0x04b2, 0x30a4 }, /*                      kana_I イ KATAKANA LETTER I */
+  { 0x04a9, 0x30a5 }, /*                      kana_u ゥ KATAKANA LETTER SMALL U */
+  { 0x04b3, 0x30a6 }, /*                      kana_U ウ KATAKANA LETTER U */
+  { 0x04aa, 0x30a7 }, /*                      kana_e ェ KATAKANA LETTER SMALL E */
+  { 0x04b4, 0x30a8 }, /*                      kana_E エ KATAKANA LETTER E */
+  { 0x04ab, 0x30a9 }, /*                      kana_o ォ KATAKANA LETTER SMALL O */
+  { 0x04b5, 0x30aa }, /*                      kana_O オ KATAKANA LETTER O */
+  { 0x04b6, 0x30ab }, /*                     kana_KA カ KATAKANA LETTER KA */
+  { 0x04b7, 0x30ad }, /*                     kana_KI キ KATAKANA LETTER KI */
+  { 0x04b8, 0x30af }, /*                     kana_KU ク KATAKANA LETTER KU */
+  { 0x04b9, 0x30b1 }, /*                     kana_KE ケ KATAKANA LETTER KE */
+  { 0x04ba, 0x30b3 }, /*                     kana_KO コ KATAKANA LETTER KO */
+  { 0x04bb, 0x30b5 }, /*                     kana_SA サ KATAKANA LETTER SA */
+  { 0x04bc, 0x30b7 }, /*                    kana_SHI シ KATAKANA LETTER SI */
+  { 0x04bd, 0x30b9 }, /*                     kana_SU ス KATAKANA LETTER SU */
+  { 0x04be, 0x30bb }, /*                     kana_SE セ KATAKANA LETTER SE */
+  { 0x04bf, 0x30bd }, /*                     kana_SO ソ KATAKANA LETTER SO */
+  { 0x04c0, 0x30bf }, /*                     kana_TA タ KATAKANA LETTER TA */
+  { 0x04c1, 0x30c1 }, /*                    kana_CHI チ KATAKANA LETTER TI */
+  { 0x04af, 0x30c3 }, /*                    kana_tsu ッ KATAKANA LETTER SMALL TU */
+  { 0x04c2, 0x30c4 }, /*                    kana_TSU ツ KATAKANA LETTER TU */
+  { 0x04c3, 0x30c6 }, /*                     kana_TE テ KATAKANA LETTER TE */
+  { 0x04c4, 0x30c8 }, /*                     kana_TO ト KATAKANA LETTER TO */
+  { 0x04c5, 0x30ca }, /*                     kana_NA ナ KATAKANA LETTER NA */
+  { 0x04c6, 0x30cb }, /*                     kana_NI ニ KATAKANA LETTER NI */
+  { 0x04c7, 0x30cc }, /*                     kana_NU ヌ KATAKANA LETTER NU */
+  { 0x04c8, 0x30cd }, /*                     kana_NE ネ KATAKANA LETTER NE */
+  { 0x04c9, 0x30ce }, /*                     kana_NO ノ KATAKANA LETTER NO */
+  { 0x04ca, 0x30cf }, /*                     kana_HA ハ KATAKANA LETTER HA */
+  { 0x04cb, 0x30d2 }, /*                     kana_HI ヒ KATAKANA LETTER HI */
+  { 0x04cc, 0x30d5 }, /*                     kana_FU フ KATAKANA LETTER HU */
+  { 0x04cd, 0x30d8 }, /*                     kana_HE ヘ KATAKANA LETTER HE */
+  { 0x04ce, 0x30db }, /*                     kana_HO ホ KATAKANA LETTER HO */
+  { 0x04cf, 0x30de }, /*                     kana_MA マ KATAKANA LETTER MA */
+  { 0x04d0, 0x30df }, /*                     kana_MI ミ KATAKANA LETTER MI */
+  { 0x04d1, 0x30e0 }, /*                     kana_MU ム KATAKANA LETTER MU */
+  { 0x04d2, 0x30e1 }, /*                     kana_ME メ KATAKANA LETTER ME */
+  { 0x04d3, 0x30e2 }, /*                     kana_MO モ KATAKANA LETTER MO */
+  { 0x04ac, 0x30e3 }, /*                     kana_ya ャ KATAKANA LETTER SMALL YA */
+  { 0x04d4, 0x30e4 }, /*                     kana_YA ヤ KATAKANA LETTER YA */
+  { 0x04ad, 0x30e5 }, /*                     kana_yu ュ KATAKANA LETTER SMALL YU */
+  { 0x04d5, 0x30e6 }, /*                     kana_YU ユ KATAKANA LETTER YU */
+  { 0x04ae, 0x30e7 }, /*                     kana_yo ョ KATAKANA LETTER SMALL YO */
+  { 0x04d6, 0x30e8 }, /*                     kana_YO ヨ KATAKANA LETTER YO */
+  { 0x04d7, 0x30e9 }, /*                     kana_RA ラ KATAKANA LETTER RA */
+  { 0x04d8, 0x30ea }, /*                     kana_RI リ KATAKANA LETTER RI */
+  { 0x04d9, 0x30eb }, /*                     kana_RU ル KATAKANA LETTER RU */
+  { 0x04da, 0x30ec }, /*                     kana_RE レ KATAKANA LETTER RE */
+  { 0x04db, 0x30ed }, /*                     kana_RO ロ KATAKANA LETTER RO */
+  { 0x04dc, 0x30ef }, /*                     kana_WA ワ KATAKANA LETTER WA */
+  { 0x04a6, 0x30f2 }, /*                     kana_WO ヲ KATAKANA LETTER WO */
+  { 0x04dd, 0x30f3 }, /*                      kana_N ン KATAKANA LETTER N */
+  { 0x04a5, 0x30fb }, /*            kana_conjunctive ・ KATAKANA MIDDLE DOT */
+  { 0x04b0, 0x30fc }, /*              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+  { 0x0ea1, 0x3131 }, /*               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
+  { 0x0ea2, 0x3132 }, /*          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
+  { 0x0ea3, 0x3133 }, /*           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
+  { 0x0ea4, 0x3134 }, /*                Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
+  { 0x0ea5, 0x3135 }, /*           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
+  { 0x0ea6, 0x3136 }, /*           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
+  { 0x0ea7, 0x3137 }, /*               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
+  { 0x0ea8, 0x3138 }, /*          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
+  { 0x0ea9, 0x3139 }, /*                Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
+  { 0x0eaa, 0x313a }, /*          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
+  { 0x0eab, 0x313b }, /*           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
+  { 0x0eac, 0x313c }, /*           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
+  { 0x0ead, 0x313d }, /*            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
+  { 0x0eae, 0x313e }, /*           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
+  { 0x0eaf, 0x313f }, /*          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
+  { 0x0eb0, 0x3140 }, /*           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
+  { 0x0eb1, 0x3141 }, /*                Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
+  { 0x0eb2, 0x3142 }, /*                Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
+  { 0x0eb3, 0x3143 }, /*           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
+  { 0x0eb4, 0x3144 }, /*            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
+  { 0x0eb5, 0x3145 }, /*                 Hangul_Sios ㅅ HANGUL LETTER SIOS */
+  { 0x0eb6, 0x3146 }, /*            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
+  { 0x0eb7, 0x3147 }, /*                Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
+  { 0x0eb8, 0x3148 }, /*                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
+  { 0x0eb9, 0x3149 }, /*           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
+  { 0x0eba, 0x314a }, /*                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
+  { 0x0ebb, 0x314b }, /*               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
+  { 0x0ebc, 0x314c }, /*                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
+  { 0x0ebd, 0x314d }, /*               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
+  { 0x0ebe, 0x314e }, /*                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
+  { 0x0ebf, 0x314f }, /*                    Hangul_A ㅏ HANGUL LETTER A */
+  { 0x0ec0, 0x3150 }, /*                   Hangul_AE ㅐ HANGUL LETTER AE */
+  { 0x0ec1, 0x3151 }, /*                   Hangul_YA ㅑ HANGUL LETTER YA */
+  { 0x0ec2, 0x3152 }, /*                  Hangul_YAE ㅒ HANGUL LETTER YAE */
+  { 0x0ec3, 0x3153 }, /*                   Hangul_EO ㅓ HANGUL LETTER EO */
+  { 0x0ec4, 0x3154 }, /*                    Hangul_E ㅔ HANGUL LETTER E */
+  { 0x0ec5, 0x3155 }, /*                  Hangul_YEO ㅕ HANGUL LETTER YEO */
+  { 0x0ec6, 0x3156 }, /*                   Hangul_YE ㅖ HANGUL LETTER YE */
+  { 0x0ec7, 0x3157 }, /*                    Hangul_O ㅗ HANGUL LETTER O */
+  { 0x0ec8, 0x3158 }, /*                   Hangul_WA ㅘ HANGUL LETTER WA */
+  { 0x0ec9, 0x3159 }, /*                  Hangul_WAE ㅙ HANGUL LETTER WAE */
+  { 0x0eca, 0x315a }, /*                   Hangul_OE ㅚ HANGUL LETTER OE */
+  { 0x0ecb, 0x315b }, /*                   Hangul_YO ㅛ HANGUL LETTER YO */
+  { 0x0ecc, 0x315c }, /*                    Hangul_U ㅜ HANGUL LETTER U */
+  { 0x0ecd, 0x315d }, /*                  Hangul_WEO ㅝ HANGUL LETTER WEO */
+  { 0x0ece, 0x315e }, /*                   Hangul_WE ㅞ HANGUL LETTER WE */
+  { 0x0ecf, 0x315f }, /*                   Hangul_WI ㅟ HANGUL LETTER WI */
+  { 0x0ed0, 0x3160 }, /*                   Hangul_YU ㅠ HANGUL LETTER YU */
+  { 0x0ed1, 0x3161 }, /*                   Hangul_EU ㅡ HANGUL LETTER EU */
+  { 0x0ed2, 0x3162 }, /*                   Hangul_YI ㅢ HANGUL LETTER YI */
+  { 0x0ed3, 0x3163 }, /*                    Hangul_I ㅣ HANGUL LETTER I */
+  { 0x0eef, 0x316d }, /*     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
+  { 0x0ef0, 0x3171 }, /*    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
+  { 0x0ef1, 0x3178 }, /*    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
+  { 0x0ef2, 0x317f }, /*              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
+  { 0x0ef4, 0x3184 }, /*   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
+  { 0x0ef5, 0x3186 }, /*          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
+  { 0x0ef6, 0x318d }, /*                Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
+  { 0x0ef7, 0x318e }, /*               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
+};
+
+static guint
+unicode_to_keyval (wchar_t ucs)
+{
+  int min = 0;
+  int max = sizeof(u2ktab) / sizeof(u2ktab[0]) - 1;
+  int mid;
+
+  /* First check for Latin-1 characters (1:1 mapping) */
+  if ((ucs >= 0x0020 && ucs <= 0x007e) ||
+      (ucs >= 0x00a0 && ucs <= 0x00ff))
+    return ucs;
+
+  /* Binary search in table */
+  while (max >= min) {
+    mid = (min + max) / 2;
+    if (u2ktab[mid].ucs < ucs)
+      min = mid + 1;
+    else if (u2ktab[mid].ucs > ucs)
+      max = mid - 1;
+    else {
+      /* found it */
+      return u2ktab[mid].keysym;
+    }
+  }
+  
+  /*
+   * No matching keysym value found, return Unicode value plus 0x01000000
+   * (a convention introduced in the UTF-8 work on xterm).
+   */
+  return ucs | 0x01000000;
+}
+
+static void
+build_key_event_state (GdkEvent *event)
+{
+  event->key.state = 0;
+  if (GetKeyState (VK_SHIFT) < 0)
+    event->key.state |= GDK_SHIFT_MASK;
+  if (GetKeyState (VK_CAPITAL) & 0x1)
+    event->key.state |= GDK_LOCK_MASK;
+  if (!is_AltGr_key)
+    {
+      if (GetKeyState (VK_CONTROL) < 0)
+       {
+         event->key.state |= GDK_CONTROL_MASK;
+         if (event->key.keyval < ' ')
+           event->key.keyval += '@';
+       }
+      else if (event->key.keyval < ' ')
+       {
+         event->key.state |= GDK_CONTROL_MASK;
+         event->key.keyval += '@';
+       }
+      if (GetKeyState (VK_MENU) < 0)
+       event->key.state |= GDK_MOD1_MASK;
+    }
+}
+
+static void
+build_keypress_event (GdkWindowPrivate *window_private,
+                     GdkEvent         *event,
+                     MSG              *xevent)
+{
+  gint i, bytesleft, bytecount, ucount, ucleft, len;
+  guchar buf[100], *bp;
+  wchar_t wbuf[100], *wcp;
+
+  event->key.type = GDK_KEY_PRESS;
+  event->key.time = xevent->time;
+  
+  if (xevent->message == WM_CHAR)
+    {
+      bytecount = MIN ((xevent->lParam & 0xFFFF), sizeof (buf));
+      for (i = 0; i < bytecount; i++)
+       buf[i] = xevent->wParam;
+    }
+  else
+    {
+      /* WM_IME_CHAR */
+      event->key.keyval = GDK_VoidSymbol;
+      if (xevent->wParam & 0xFF00)
+       {
+         /* Contrary to the documentation,
+          * the lead byte is the msb byte.
+          */
+         buf[0] = ((xevent->wParam >> 8) & 0xFF);
+         buf[1] = (xevent->wParam & 0xFF);
+         bytecount = 2;
+       }
+      else
+       {
+         buf[0] = (xevent->wParam & 0xFF);
+         bytecount = 1;
+       }
+    }
+
+  /* Convert from the window's current code page
+   * to Unicode. Then convert to UTF-8.
+   * We don't handle the surrogate stuff. Should we?
+   */
+  ucount = MultiByteToWideChar (window_private->charset_info.ciACP,
+                               0, buf, bytecount, wbuf, 100);
+  
+  if (ucount == 0)
+    event->key.keyval = GDK_VoidSymbol;
+  else if (xevent->message == WM_CHAR)
+    if (xevent->wParam < ' ')
+      event->key.keyval = xevent->wParam + '@';
+    else
+      event->key.keyval = unicode_to_keyval (wbuf[0]);
+  else
+    event->key.keyval = GDK_VoidSymbol;
+
+  build_key_event_state (event);
+
+  ucleft = ucount;
+  len = 0;
+  wcp = wbuf;
+  while (ucleft-- > 0)
+    {
+      wchar_t c = *wcp++;
+
+      if (c < 0x80)
+       len += 1;
+      else if (c < 0x800)
+       len += 2;
+      else
+       len += 3;
+    }
+
+  event->key.string = g_malloc (len + 1);
+  event->key.length = len;
+  
+  ucleft = ucount;
+  wcp = wbuf;
+  bp = event->key.string;
+  while (ucleft-- > 0)
+    {
+      int first;
+      int i;
+      wchar_t c = *wcp++;
+
+      if (c < 0x80)
+       {
+         first = 0;
+         len = 1;
+       }
+      else if (c < 0x800)
+       {
+         first = 0xc0;
+         len = 2;
+       }
+      else
+       {
+         first = 0xe0;
+         len = 3;
+       }
+
+#if 1      
+      /* Woo-hoo! */
+      switch (len)
+       {
+       case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 1: bp[0] = c | first;
+       }
+#else
+      for (i = len - 1; i > 0; --i)
+       {
+         bp[i] = (c & 0x3f) | 0x80;
+         c >>= 6;
+       }
+      bp[0] = c | first;
+#endif
+
+      bp += len;
+    }
+  *bp = 0;
+}
+
+static void
+print_event_state (gint state)
+{
+  if (state & GDK_SHIFT_MASK)
+    g_print ("SHIFT ");
+  if (state & GDK_LOCK_MASK)
+    g_print ("LOCK ");
+  if (state & GDK_CONTROL_MASK)
+    g_print ("CONTROL ");
+  if (state & GDK_MOD1_MASK)
+    g_print ("MOD1 ");
+  if (state & GDK_BUTTON1_MASK)
+    g_print ("BUTTON1 ");
+  if (state & GDK_BUTTON2_MASK)
+    g_print ("BUTTON2 ");
+  if (state & GDK_BUTTON3_MASK)
+    g_print ("BUTTON3 ");
+}
+
+static void
+print_event (GdkEvent *event)
+{
+  gchar *escaped, *kvname;
+
+  switch (event->any.type)
+    {
+    case GDK_NOTHING: g_print ("GDK_NOTHING "); break;
+    case GDK_DELETE: g_print ("GDK_DELETE "); break;
+    case GDK_DESTROY: g_print ("GDK_DESTROY "); break;
+    case GDK_EXPOSE: g_print ("GDK_EXPOSE "); break;
+    case GDK_MOTION_NOTIFY: g_print ("GDK_MOTION_NOTIFY "); break;
+    case GDK_BUTTON_PRESS: g_print ("GDK_BUTTON_PRESS "); break;
+    case GDK_2BUTTON_PRESS: g_print ("GDK_2BUTTON_PRESS "); break;
+    case GDK_3BUTTON_PRESS: g_print ("GDK_3BUTTON_PRESS "); break;
+    case GDK_BUTTON_RELEASE: g_print ("GDK_BUTTON_RELEASE "); break;
+    case GDK_KEY_PRESS: g_print ("GDK_KEY_PRESS "); break;
+    case GDK_KEY_RELEASE: g_print ("GDK_KEY_RELEASE "); break;
+    case GDK_ENTER_NOTIFY: g_print ("GDK_ENTER_NOTIFY "); break;
+    case GDK_LEAVE_NOTIFY: g_print ("GDK_LEAVE_NOTIFY "); break;
+    case GDK_FOCUS_CHANGE: g_print ("GDK_FOCUS_CHANGE "); break;
+    case GDK_CONFIGURE: g_print ("GDK_CONFIGURE "); break;
+    case GDK_MAP: g_print ("GDK_MAP "); break;
+    case GDK_UNMAP: g_print ("GDK_UNMAP "); break;
+    case GDK_PROPERTY_NOTIFY: g_print ("GDK_PROPERTY_NOTIFY "); break;
+    case GDK_SELECTION_CLEAR: g_print ("GDK_SELECTION_CLEAR "); break;
+    case GDK_SELECTION_REQUEST: g_print ("GDK_SELECTION_REQUEST "); break;
+    case GDK_SELECTION_NOTIFY: g_print ("GDK_SELECTION_NOTIFY "); break;
+    case GDK_PROXIMITY_IN: g_print ("GDK_PROXIMITY_IN "); break;
+    case GDK_PROXIMITY_OUT: g_print ("GDK_PROXIMITY_OUT "); break;
+    case GDK_DRAG_ENTER: g_print ("GDK_DRAG_ENTER "); break;
+    case GDK_DRAG_LEAVE: g_print ("GDK_DRAG_LEAVE "); break;
+    case GDK_DRAG_MOTION: g_print ("GDK_DRAG_MOTION "); break;
+    case GDK_DRAG_STATUS: g_print ("GDK_DRAG_STATUS "); break;
+    case GDK_DROP_START: g_print ("GDK_DROP_START "); break;
+    case GDK_DROP_FINISHED: g_print ("GDK_DROP_FINISHED "); break;
+    case GDK_CLIENT_EVENT: g_print ("GDK_CLIENT_EVENT "); break;
+    case GDK_VISIBILITY_NOTIFY: g_print ("GDK_VISIBILITY_NOTIFY "); break;
+    case GDK_NO_EXPOSE: g_print ("GDK_NO_EXPOSE "); break;
+    }
+  g_print ("%#x ", GDK_DRAWABLE_XID (event->any.window));
+
+  switch (event->any.type)
+    {
+    case GDK_EXPOSE:
+      g_print ("%dx%d@+%d+%d %d",
+              event->expose.area.width,
+              event->expose.area.height,
+              event->expose.area.x,
+              event->expose.area.y,
+              event->expose.count);
+      break;
+    case GDK_MOTION_NOTIFY:
+      print_event_state (event->motion.state);
+      break;
+    case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      g_print ("%d ", event->button.button);
+      print_event_state (event->button.state);
+      break;
+    case GDK_KEY_PRESS: 
+    case GDK_KEY_RELEASE:
+      if (event->key.length == 0)
+       escaped = g_strdup ("");
+      else
+       escaped = g_strescape (event->key.string, NULL);
+      kvname = gdk_keyval_name (event->key.keyval);
+      g_print ("%s %d:\"%s\" ",
+              (kvname ? kvname : "??"),
+              event->key.length,
+              escaped);
+      g_free (escaped);
+      print_event_state (event->key.state);
+      break;
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      g_print (" %s",
+              (event->crossing.detail == GDK_NOTIFY_INFERIOR ? "INFERIOR" :
+               (event->crossing.detail == GDK_NOTIFY_ANCESTOR ? "ANCESTOR" :
+                (event->crossing.detail == GDK_NOTIFY_NONLINEAR ? "NONLINEAR" :
+                 "???"))));
+      break;
+    }  
+  g_print ("\n");
+}
+
 static void
 synthesize_crossing_events (GdkWindow *window,
                            MSG       *xevent)
 {
+  TRACKMOUSEEVENT tme;
   GdkEvent *event;
-  GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
-  GdkWindowPrivate *curWnd_private = (GdkWindowPrivate *) curWnd;
   
-  if (curWnd && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
+  /* If we are not using TrackMouseEvent, generate a leave notify
+   * event if necessary
+   */
+  if (p_TrackMouseEvent == NULL
+      && curWnd
+      && (WINDOW_PRIVATE(curWnd)->event_mask & GDK_LEAVE_NOTIFY_MASK))
     {
       GDK_NOTE (EVENTS, g_print ("synthesizing LEAVE_NOTIFY event\n"));
 
@@ -1099,15 +3073,21 @@ synthesize_crossing_events (GdkWindow *window,
       event->crossing.x_root = curXroot;
       event->crossing.y_root = curYroot;
       event->crossing.mode = GDK_CROSSING_NORMAL;
-      event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+      if (IsChild (GDK_DRAWABLE_XID (curWnd), GDK_DRAWABLE_XID (window)))
+       event->crossing.detail = GDK_NOTIFY_INFERIOR;
+      else if (IsChild (GDK_DRAWABLE_XID (window), GDK_DRAWABLE_XID (curWnd)))
+       event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+      else
+       event->crossing.detail = GDK_NOTIFY_NONLINEAR;
 
       event->crossing.focus = TRUE; /* ??? */
       event->crossing.state = 0; /* ??? */
 
       gdk_event_queue_append (event);
+      GDK_NOTE (EVENTS, print_event (event));
     }
 
-  if (window_private && (window_private->event_mask & GDK_ENTER_NOTIFY_MASK))
+  if (WINDOW_PRIVATE(window)->event_mask & GDK_ENTER_NOTIFY_MASK)
     {
       GDK_NOTE (EVENTS, g_print ("synthesizing ENTER_NOTIFY event\n"));
       
@@ -1122,35 +3102,217 @@ synthesize_crossing_events (GdkWindow *window,
       event->crossing.x_root = (gfloat) xevent->pt.x;
       event->crossing.y_root = (gfloat) xevent->pt.y;
       event->crossing.mode = GDK_CROSSING_NORMAL;
-      event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+      if (curWnd
+         && IsChild (GDK_DRAWABLE_XID (curWnd), GDK_DRAWABLE_XID (window)))
+       event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+      else if (curWnd
+              && IsChild (GDK_DRAWABLE_XID (window), GDK_DRAWABLE_XID (curWnd)))
+       event->crossing.detail = GDK_NOTIFY_INFERIOR;
+      else
+       event->crossing.detail = GDK_NOTIFY_NONLINEAR;
       
       event->crossing.focus = TRUE; /* ??? */
       event->crossing.state = 0; /* ??? */
       
       gdk_event_queue_append (event);
 
-      if (window_private->extension_events != 0
+      GDK_NOTE (EVENTS, print_event (event));
+
+      if (WINDOW_PRIVATE(window)->extension_events != 0
          && gdk_input_vtable.enter_event)
        gdk_input_vtable.enter_event (&event->crossing, window);
+
     }
   
   if (curWnd)
     gdk_window_unref (curWnd);
   curWnd = window;
   gdk_window_ref (curWnd);
+  if (p_TrackMouseEvent != NULL)
+    {
+      tme.cbSize = sizeof (TRACKMOUSEEVENT);
+      tme.dwFlags = TME_LEAVE;
+      tme.hwndTrack = GDK_DRAWABLE_XID (curWnd);
+      tme.dwHoverTime = HOVER_DEFAULT;
+      
+      (*p_TrackMouseEvent) (&tme);
+    }
+}
+
+static GdkWindow *
+key_propagate (GdkWindow *window,
+              MSG       *xevent)
+{
+  gdk_window_unref (window);
+  window = WINDOW_PRIVATE(window)->parent;
+  gdk_window_ref (window);
+  GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
+                            GDK_DRAWABLE_XID (window)));
+
+  return window;
+}  
+
+static GdkWindow *
+mouse_propagate (GdkWindow *window,
+                MSG       *xevent)
+{
+  POINT pt;
+
+  pt.x = LOWORD (xevent->lParam);
+  pt.y = HIWORD (xevent->lParam);
+  ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
+  gdk_window_unref (window);
+  window = WINDOW_PRIVATE(window)->parent;
+  gdk_window_ref (window);
+  ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
+  xevent->lParam = MAKELPARAM (pt.x, pt.y);
+  GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
+                            GDK_DRAWABLE_XID (window)));
+  return window;
+}
+
+#ifdef NEW_PROPAGATION_CODE
+
+static gboolean
+propagate (GdkWindow  **window,
+          MSG         *xevent,
+          GdkWindow   *grab_window,
+          gboolean     grab_owner_events,
+          gint         grab_mask,
+          gboolean   (*doesnt_want_it) (gint mask,
+                                        MSG *xevent),
+          GdkWindow *(*propagate) (GdkWindow *window,
+                                   MSG       *xevent))
+{
+  if (grab_window != NULL && !grab_owner_events)
+    {
+      /* Event source is grabbed with owner_events FALSE */
+      GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE, "));
+      if ((*doesnt_want_it) (grab_mask, xevent))
+       {
+         GDK_NOTE (EVENTS, g_print ("...grabber doesn't want it\n"));
+         return FALSE;
+       }
+      else
+       {
+         GDK_NOTE (EVENTS, g_print ("...sending to grabber %#x\n",
+                                    GDK_DRAWABLE_XID (grab_window)));
+         gdk_window_unref (*window);
+         *window = grab_window;
+         gdk_window_ref (*window);
+         return TRUE;
+       }
+    }
+  while (TRUE)
+    {
+     if ((*doesnt_want_it) (WINDOW_PRIVATE(*window)->event_mask, xevent))
+       {
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(*window)->parent == (GdkWindow *) gdk_root_parent)
+           {
+             /* No parent; check if grabbed */
+             if (grab_window != NULL)
+               {
+                 /* Event source is grabbed with owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 if ((*doesnt_want_it) (grab_mask, xevent))
+                   {
+                     /* Grabber doesn't want it either */
+                     GDK_NOTE (EVENTS, g_print ("...grabber doesn't want it\n"));
+                     return FALSE;
+                   }
+                 else
+                   {
+                     /* Grabbed! */
+                     GDK_NOTE (EVENTS, g_print ("...sending to grabber %#x\n",
+                                                GDK_DRAWABLE_XID (grab_window)));
+                     gdk_window_unref (*window);
+                     *window = grab_window;
+                     gdk_window_ref (*window);
+                     return TRUE;
+                   }
+               }
+             else
+               {
+                 GDK_NOTE (EVENTS, "...undelivered\n");
+                 return FALSE;
+               }
+           }
+         else
+           {
+             *window = (*propagate) (*window, xevent);
+             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
+                                        GDK_DRAWABLE_XID (*window)));
+             /* The only branch where we actually continue the loop */
+           }
+       }
+      else
+       return TRUE;
+    }
+}
+
+static gboolean
+doesnt_want_key (gint mask,
+                MSG *xevent)
+{
+  return (((xevent->message == WM_KEYUP
+           || xevent->message == WM_SYSKEYUP)
+          && !(mask & GDK_KEY_RELEASE_MASK))
+         ||
+         ((xevent->message == WM_KEYDOWN
+           || xevent->message == WM_SYSKEYDOWN)
+          && !(mask & GDK_KEY_PRESS_MASK)));
+}
+
+static gboolean
+doesnt_want_char (gint mask,
+                 MSG *xevent)
+{
+  return !(mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK));
+}
+
+static gboolean
+doesnt_want_button_press (gint mask,
+                         MSG *xevent)
+{
+  return !(mask & GDK_BUTTON_PRESS_MASK);
+}
+
+static gboolean
+doesnt_want_button_release (gint mask,
+                           MSG *xevent)
+{
+  return !(mask & GDK_BUTTON_RELEASE_MASK);
+}
+
+static gboolean
+doesnt_want_button_motion (gint mask,
+                          MSG *xevent)
+{
+  return !((mask & GDK_POINTER_MOTION_MASK)
+          || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
+              && (mask & GDK_BUTTON_MOTION_MASK))
+          || ((xevent->wParam & MK_LBUTTON)
+              && (mask & GDK_BUTTON1_MOTION_MASK))
+          || ((xevent->wParam & MK_MBUTTON)
+              && (mask & GDK_BUTTON2_MOTION_MASK))
+          || ((xevent->wParam & MK_RBUTTON)
+              && (mask & GDK_BUTTON3_MOTION_MASK)));
 }
 
-static gint
+#endif
+
+static gboolean
 gdk_event_translate (GdkEvent *event,
                     MSG      *xevent,
                     gboolean *ret_val_flagp,
                     gint     *ret_valp)
 {
-  GdkWindow *window;
-  GdkWindowPrivate *window_private;
-
+  GdkWindow *window, *orig_window;
   GdkColormapPrivate *colormap_private;
   HWND owner;
+  DWORD pidActWin;
+  DWORD pidThis;
   DWORD dwStyle;
   PAINTSTRUCT paintstruct;
   HDC hdc;
@@ -1158,7 +3320,6 @@ gdk_event_translate (GdkEvent *event,
   RECT rect;
   POINT pt;
   MINMAXINFO *lpmmi;
-  GdkWindowPrivate *curWnd_private;
   GdkEventMask mask;
   GdkDrawablePrivate *pixmap_private;
   HDC bgdc;
@@ -1166,8 +3327,8 @@ gdk_event_translate (GdkEvent *event,
   int button;
   int i, j;
   gchar buf[256];
-  gint charcount;
-  gint return_val;
+  gchar *msgname;
+  gboolean return_val;
   gboolean flag;
   
   return_val = FALSE;
@@ -1175,16 +3336,15 @@ gdk_event_translate (GdkEvent *event,
   if (ret_val_flagp)
     *ret_val_flagp = FALSE;
 
+#ifndef USE_DISPATCHMESSAGE
   if (xevent->message == gdk_ping_msg)
     {
       /* Messages we post ourselves just to wakeup WaitMessage.  */
+      GDK_NOTE (EVENTS, g_print ("gdk_ping_msg\n"));
+
       return FALSE;
     }
-
-  window = gdk_window_lookup (xevent->hwnd);
-  window_private = (GdkWindowPrivate *) window;
-  
-  if (xevent->message == g_pipe_readable_msg)
+  else if (xevent->message == g_pipe_readable_msg)
     {
       GDK_NOTE (EVENTS, g_print ("g_pipe_readable_msg: %d %d\n",
                                 xevent->wParam, xevent->lParam));
@@ -1192,7 +3352,11 @@ gdk_event_translate (GdkEvent *event,
       g_io_channel_win32_pipe_readable (xevent->wParam, xevent->lParam);
       return FALSE;
     }
+#endif
 
+  window = gdk_window_lookup (xevent->hwnd);
+  orig_window = window;
+  
   if (window != NULL)
     gdk_window_ref (window);
   else
@@ -1218,18 +3382,12 @@ gdk_event_translate (GdkEvent *event,
       return FALSE;
     }
   
-  event->any.window = window;
-
-  if (window_private && GDK_DRAWABLE_DESTROYED (window))
-    {
-    }
-  else
+  if (!GDK_DRAWABLE_DESTROYED (window))
     {
       /* Check for filters for this window */
       GdkFilterReturn result;
       result = gdk_event_apply_filters
-       (xevent, event,
-        window_private ? window_private->filters : gdk_default_filters);
+       (xevent, event, WINDOW_PRIVATE(window)->filters);
       
       if (result != GDK_FILTER_CONTINUE)
        {
@@ -1249,7 +3407,7 @@ gdk_event_translate (GdkEvent *event,
       event->selection.property = gdk_selection_property;
       event->selection.time = xevent->time;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
 
       /* Will pass through switch below without match */
     }
@@ -1266,7 +3424,7 @@ gdk_event_translate (GdkEvent *event,
       event->selection.requestor = (guint32) xevent->hwnd;
       event->selection.time = xevent->time;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
 
       /* Again, will pass through switch below without match */
     }
@@ -1280,7 +3438,7 @@ gdk_event_translate (GdkEvent *event,
       event->selection.selection = xevent->wParam;
       event->selection.time = xevent->time;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = GDK_DRAWABLE_DESTROYED (window);
 
       /* Once again, we will pass through switch below without match */
     }
@@ -1325,6 +3483,16 @@ gdk_event_translate (GdkEvent *event,
 
   switch (xevent->message)
     {
+    case WM_INPUTLANGCHANGE:
+      GDK_NOTE (EVENTS,
+               g_print ("WM_INPUTLANGCHANGE: %#x charset %d locale %x\n",
+                        xevent->hwnd, xevent->wParam, xevent->lParam));
+      WINDOW_PRIVATE(window)->input_locale = (HKL) xevent->lParam;
+      TranslateCharsetInfo ((DWORD FAR *) xevent->wParam,
+                           &WINDOW_PRIVATE(window)->charset_info,
+                           TCI_SRCCHARSET);
+      break;
+
     case WM_SYSKEYUP:
     case WM_SYSKEYDOWN:
       GDK_NOTE (EVENTS,
@@ -1367,50 +3535,57 @@ gdk_event_translate (GdkEvent *event,
 
       ignore_WM_CHAR = TRUE;
     keyup_or_down:
+
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+                     doesnt_want_key,
+                     key_propagate))
+         break;
+      event->key.window = window;
+#else
       if (k_grab_window != NULL && !k_grab_owner_events)
        {
          /* Keyboard is grabbed with owner_events FALSE */
-         GDK_NOTE (EVENTS,
-                   g_print ("...grabbed, owner_events FALSE, "
-                            "sending to %#x\n",
-                            GDK_DRAWABLE_XID (k_grab_window)));
+         GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE, "
+                                    "sending to %#x\n",
+                                    GDK_DRAWABLE_XID (k_grab_window)));
          event->key.window = k_grab_window;
+         /* Continue with switch statement below */
        }
-      else if (window_private
-              && (((xevent->message == WM_KEYUP
+      else if (((xevent->message == WM_KEYUP
                     || xevent->message == WM_SYSKEYUP)
-                   && !(window_private->event_mask & GDK_KEY_RELEASE_MASK))
+                   && !(WINDOW_PRIVATE(window)->event_mask & GDK_KEY_RELEASE_MASK))
                   || ((xevent->message == WM_KEYDOWN
                        || xevent->message == WM_SYSKEYDOWN)
-                      && !(window_private->event_mask & GDK_KEY_PRESS_MASK))))
+                      && !(WINDOW_PRIVATE(window)->event_mask & GDK_KEY_PRESS_MASK)))
        {
-         /* Owner window doesn't want it */
-         if (k_grab_window != NULL && k_grab_owner_events)
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Keyboard is grabbed with owner_events TRUE */
-             GDK_NOTE (EVENTS,
-                       g_print ("...grabbed, owner_events TRUE, doesn't want it, "
-                                "sending to %#x\n",
-                                GDK_DRAWABLE_XID (k_grab_window)));
-             event->key.window = k_grab_window;
+             /* No parent; check if grabbed */
+             if (k_grab_window != NULL)
+               {
+                 /* Keyboard is grabbed with owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 event->key.window = k_grab_window;
+                 /* Continue with switch statement below */
+               }
+             else
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               break;
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = key_propagate (window, xevent);
+             /* Jump back up */
              goto keyup_or_down;
            }
        }
-             
+      else
+       event->key.window = window;
+
+      g_assert (event->key.window == window);
+#endif       
       switch (xevent->wParam)
        {
        case VK_LBUTTON:
@@ -1505,34 +3680,22 @@ gdk_event_translate (GdkEvent *event,
        case VK_MULTIPLY:
          event->key.keyval = GDK_KP_Multiply; break;
        case VK_ADD:
-#if 0
-         event->key.keyval = GDK_KP_Add; break;
-#else
          /* Pass it on as an ASCII plus in WM_CHAR. */
          ignore_WM_CHAR = FALSE;
          break;
-#endif
        case VK_SEPARATOR:
          event->key.keyval = GDK_KP_Separator; break;
        case VK_SUBTRACT:
-#if 0
-         event->key.keyval = GDK_KP_Subtract; break;
-#else
          /* Pass it on as an ASCII minus in WM_CHAR. */
          ignore_WM_CHAR = FALSE;
          break;
-#endif
        case VK_DECIMAL:
-#if 0
-         event->key.keyval = GDK_KP_Decimal; break;
-#else
          /* The keypad decimal key should also be passed on as the decimal
           * sign ('.' or ',' depending on the Windows locale settings,
           * apparently). So wait for the WM_CHAR here, also.
           */
          ignore_WM_CHAR = FALSE;
          break;
-#endif
        case VK_DIVIDE:
          event->key.keyval = GDK_KP_Divide; break;
        case VK_F1:
@@ -1579,24 +3742,32 @@ gdk_event_translate (GdkEvent *event,
        case '9':
          if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0
                                || GetKeyState (VK_MENU) < 0))
-           /* Control- or Alt-digits won't come in as a WM_CHAR */
+           /* Control- or Alt-digits won't come in as a WM_CHAR,
+            * but beware of AltGr-digits, which are used for instance
+            * on Finnish keyboards.
+            */
            event->key.keyval = GDK_0 + (xevent->wParam - '0');
          else
-           {
-             ignore_WM_CHAR = FALSE;
-             event->key.keyval = GDK_VoidSymbol;
-           }
+           ignore_WM_CHAR = FALSE;
+         break;
+       case VK_OEM_PLUS:       /* On my Win98, the '+' key comes in
+                                * as VK_OEM_PLUS
+                                */
+         if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0
+                               || GetKeyState (VK_MENU) < 0))
+           /* Control- or Alt-plus won't come in as WM_CHAR,
+            * but beware of AltGr-plus which is backslash on
+            * Finnish keyboards
+            */
+           event->key.keyval = '+';
+         else
+           ignore_WM_CHAR = FALSE;
          break;
        default:
          if (xevent->message == WM_SYSKEYDOWN || xevent->message == WM_SYSKEYUP)
-           {
-             event->key.keyval = xevent->wParam;
-           }
+           event->key.keyval = xevent->wParam;
          else
-           {
-             ignore_WM_CHAR = FALSE;
-             event->key.keyval = GDK_VoidSymbol;
-           }
+           ignore_WM_CHAR = FALSE;
          break;
        }
 
@@ -1607,7 +3778,6 @@ gdk_event_translate (GdkEvent *event,
       event->key.type = ((xevent->message == WM_KEYDOWN
                          || xevent->message == WM_SYSKEYDOWN) ?
                         GDK_KEY_PRESS : GDK_KEY_RELEASE);
-      event->key.window = window;
       event->key.time = xevent->time;
       event->key.state = 0;
       if (GetKeyState (VK_SHIFT) < 0)
@@ -1618,17 +3788,21 @@ gdk_event_translate (GdkEvent *event,
        event->key.state |= GDK_CONTROL_MASK;
       if (xevent->wParam != VK_MENU && GetKeyState (VK_MENU) < 0)
        event->key.state |= GDK_MOD1_MASK;
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
       event->key.string = NULL;
       event->key.length = 0;
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
+    case WM_IME_CHAR:
+      GDK_NOTE (EVENTS,
+               g_print ("WM_IME_CHAR: %#x  bytes: %#.04x\n",
+                        xevent->hwnd, xevent->wParam));
+      goto wm_char;
+      
     case WM_CHAR:
       GDK_NOTE (EVENTS, 
                g_print ("WM_CHAR: %#x  char: %#x %#.08x  %s\n",
-                        xevent->hwnd,
-                        xevent->wParam,
-                        xevent->lParam,
+                        xevent->hwnd, xevent->wParam, xevent->lParam,
                         (ignore_WM_CHAR ? "ignored" : "")));
 
       if (ignore_WM_CHAR)
@@ -1638,9 +3812,17 @@ gdk_event_translate (GdkEvent *event,
        }
 
     wm_char:
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+                     doesnt_want_char,
+                     key_propagate))
+         break;
+      event->key.window = window;
+#else
       /* This doesn't handle the rather theorethical case that a window
        * wants key presses but still wants releases to be propagated,
-       * for instance.
+       * for instance. Or is that so theorethical?
        */
       if (k_grab_window != NULL && !k_grab_owner_events)
        {
@@ -1651,126 +3833,63 @@ gdk_event_translate (GdkEvent *event,
                             GDK_DRAWABLE_XID (k_grab_window)));
          event->key.window = k_grab_window;
        }
-      else if (window_private
-              && !(window_private->event_mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)))
+      else if (!(WINDOW_PRIVATE(window)->event_mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)))
        {
-         /* Owner window doesn't want it */
-         if (k_grab_window != NULL && k_grab_owner_events)
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Keyboard is grabbed with owner_events TRUE */
-             GDK_NOTE (EVENTS,
-                       g_print ("...grabbed, owner_events TRUE, doesn't want it, "
-                                "sending to %#x\n",
-                                GDK_DRAWABLE_XID (k_grab_window)));
-             event->key.window = k_grab_window;
+             /* No parent; check if grabbed */
+             if (k_grab_window != NULL)
+               {
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 event->key.window = k_grab_window;
+               }
+             else
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               g_assert_not_reached (); /* Should've been handled above */
-
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = key_propagate (window, xevent);
+             /* Jump back up */
              goto wm_char;
            }
        }
-      
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      if (return_val && (window_private->event_mask & GDK_KEY_RELEASE_MASK))
+      else
+       event->key.window = window;
+
+      g_assert (event->key.window == window);
+#endif
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
+      if (return_val && (event->key.window == k_grab_window
+                        || (WINDOW_PRIVATE(window)->event_mask & GDK_KEY_RELEASE_MASK)))
        {
-         /* Return the release event, and maybe append the press
-          * event to the queued_events list (from which it will vbe
-          * fetched before the release event).
-          */
-         event->key.type = GDK_KEY_RELEASE;
-         event->key.keyval = xevent->wParam;
-         event->key.window = window;
-         event->key.time = xevent->time;
-         event->key.state = 0;
-         if (GetKeyState (VK_SHIFT) < 0)
-           event->key.state |= GDK_SHIFT_MASK;
-         if (GetKeyState (VK_CAPITAL) & 0x1)
-           event->key.state |= GDK_LOCK_MASK;
-         if (is_AltGr_key)
-           ;
-         else if (GetKeyState (VK_CONTROL) < 0)
-           {
-             event->key.state |= GDK_CONTROL_MASK;
-             if (event->key.keyval < ' ')
-               event->key.keyval += '@';
-           }
-         else if (event->key.keyval < ' ')
+         if (window == k_grab_window
+             || (WINDOW_PRIVATE(window)->event_mask & GDK_KEY_PRESS_MASK))
            {
-             event->key.state |= GDK_CONTROL_MASK;
-             event->key.keyval += '@';
-           }
-         if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
-           event->key.state |= GDK_MOD1_MASK;
-         event->key.string = g_malloc (2);
-         event->key.length = 1;
-         event->key.string[0] = xevent->wParam; /* ??? */
-         event->key.string[1] = 0;
-
-         if (window_private->event_mask & GDK_KEY_PRESS_MASK)
-           {
-             /* Append also a GDK_KEY_PRESS event to the pushback list.  */
-             GdkEvent *event2 = gdk_event_copy (event);
-             event2->key.type = GDK_KEY_PRESS;
-             charcount = xevent->lParam & 0xFFFF;
-             if (charcount > sizeof (buf)- 1)
-               charcount = sizeof (buf) - 1;
-             g_free (event2->key.string);
-             event2->key.string = g_malloc (charcount + 1);
-             for (i = 0; i < charcount; i++)
-               event2->key.string[i] = event->key.keyval;
-             event2->key.string[charcount] = 0;
-             event2->key.length = charcount;
-
+             /* Append a GDK_KEY_PRESS event to the pushback list
+              * (from which it will be fetched before the release
+              * event).
+              */
+             GdkEvent *event2 = gdk_event_new ();
+             build_keypress_event (WINDOW_PRIVATE(window), event2, xevent);
+             event2->key.window = window;
+             gdk_window_ref (window);
              gdk_event_queue_append (event2);
+             GDK_NOTE (EVENTS, print_event (event2));
            }
+         /* Return the release event.  */
+         event->key.type = GDK_KEY_RELEASE;
+         event->key.keyval = xevent->wParam;
+         event->key.time = xevent->time;
+         build_key_event_state (event);
+         event->key.string = NULL;
+         event->key.length = 0;
        }
-      else if (return_val && (window_private->event_mask & GDK_KEY_PRESS_MASK))
+      else if (return_val
+              && (WINDOW_PRIVATE(window)->event_mask & GDK_KEY_PRESS_MASK))
        {
          /* Return just the GDK_KEY_PRESS event. */
-         event->key.type = GDK_KEY_PRESS;
-         charcount = xevent->lParam & 0xFFFF;
-         if (charcount > sizeof (buf)- 1)
-           charcount = sizeof (buf) - 1;
-         event->key.keyval = xevent->wParam;
-         event->key.window = window;
-         event->key.time = xevent->time;
-         event->key.state = 0;
-         if (GetKeyState (VK_SHIFT) < 0)
-           event->key.state |= GDK_SHIFT_MASK;
-         if (GetKeyState (VK_CAPITAL) & 0x1)
-           event->key.state |= GDK_LOCK_MASK;
-         if (is_AltGr_key)
-           ;
-         else if (GetKeyState (VK_CONTROL) < 0)
-           {
-             event->key.state |= GDK_CONTROL_MASK;
-             if (event->key.keyval < ' ')
-               event->key.keyval += '@';
-           }
-         else if (event->key.keyval < ' ')
-           {
-             event->key.state |= GDK_CONTROL_MASK;
-             event->key.keyval += '@';
-           }
-         if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
-           event->key.state |= GDK_MOD1_MASK;
-         event->key.string = g_malloc (charcount + 1);
-         for (i = 0; i < charcount; i++)
-           event->key.string[i] = event->key.keyval;
-         event->key.string[charcount] = 0;
-         event->key.length = charcount;
+         build_keypress_event (WINDOW_PRIVATE(window), event, xevent);
        }
       else
        return_val = FALSE;
@@ -1799,8 +3918,7 @@ gdk_event_translate (GdkEvent *event,
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam),
                         button));
 
-      if (window_private
-         && (window_private->extension_events != 0)
+      if (WINDOW_PRIVATE(window)->extension_events != 0
          && gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print ("...ignored\n"));
@@ -1811,18 +3929,23 @@ gdk_event_translate (GdkEvent *event,
        synthesize_crossing_events (window, xevent);
 
       event->button.type = GDK_BUTTON_PRESS;
-    buttondown:
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     p_grab_window, p_grab_owner_events, p_grab_mask,
+                     doesnt_want_button_press,
+                     mouse_propagate))
+         break;
       event->button.window = window;
-      if (window_private)
-       mask = window_private->event_mask;
-      else
-       mask = 0;               /* ??? */
+#else
+    buttondown:
+      mask = WINDOW_PRIVATE(window)->event_mask;
 
       if (p_grab_window != NULL && !p_grab_owner_events)
        {
          /* Pointer is grabbed with owner_events FALSE */
          GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
-         mask = p_grab_event_mask;
+
+         mask = p_grab_mask;
          if (!(mask & GDK_BUTTON_PRESS_MASK))
            /* Grabber doesn't want it */
            break;
@@ -1831,61 +3954,79 @@ gdk_event_translate (GdkEvent *event,
          GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
                                     GDK_DRAWABLE_XID (p_grab_window)));
        }
-      else if (window_private
-              && !(mask & GDK_BUTTON_PRESS_MASK))
+      else if (!(mask & GDK_BUTTON_PRESS_MASK))
        {
-         /* Owner window doesn't want it */
-         if (p_grab_window != NULL && p_grab_owner_events)
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Pointer is grabbed wíth owner_events TRUE */ 
-             GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
-             mask = p_grab_event_mask;
-             if (!(mask & GDK_BUTTON_PRESS_MASK))
-               /* Grabber doesn't want it either */
-               break;
+             /* No parent; check if grabbed */
+             if (p_grab_window != NULL)
+               {
+                 /* Pointer is grabbed wíth owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 mask = p_grab_mask;
+                 if (!(mask & GDK_BUTTON_PRESS_MASK))
+                   {
+                     /* Grabber doesn't want it either */
+                     GDK_NOTE (EVENTS, g_print ("...grabber uninterested\n"));
+                     break;
+                   }
+                 else
+                   event->button.window = p_grab_window;
+                 GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
+                                            GDK_DRAWABLE_XID (p_grab_window)));
+               }
              else
-               event->button.window = p_grab_window;
-             GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
-                                        GDK_DRAWABLE_XID (p_grab_window)));
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             /* Yes, this code is duplicated twice below. So shoot me. */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               break;
-             pt.x = LOWORD (xevent->lParam);
-             pt.y = HIWORD (xevent->lParam);
-             ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
-             xevent->lParam = MAKELPARAM (pt.x, pt.y);
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = mouse_propagate (window, xevent);
+             /* Jump back up */
              goto buttondown; /* What did Dijkstra say? */
            }
        }
+      else
+       event->button.window = window;
 
+      g_assert (event->button.window == window);
+#endif
       /* Emulate X11's automatic active grab */
       if (!p_grab_window)
        {
          /* No explicit active grab, let's start one automatically */
+         gint owner_events =
+           WINDOW_PRIVATE(window)->event_mask
+           & (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
+         
          GDK_NOTE (EVENTS, g_print ("...automatic grab started\n"));
-         gdk_pointer_grab (window, TRUE, window_private->event_mask,
+         gdk_pointer_grab (window,
+                           owner_events,
+                           WINDOW_PRIVATE(window)->event_mask,
                            NULL, NULL, 0);
          p_grab_automatic = TRUE;
        }
 
       event->button.time = xevent->time;
-      event->button.x = LOWORD (xevent->lParam);
-      event->button.y = HIWORD (xevent->lParam);
-      event->button.x_root = (gfloat)xevent->pt.x;
-      event->button.y_root = (gfloat)xevent->pt.y;
+      if (window == p_grab_window
+         && p_grab_window != orig_window)
+       {
+         /* Translate coordinates to grabber */
+         pt.x = LOWORD (xevent->lParam);
+         pt.y = HIWORD (xevent->lParam);
+         ClientToScreen (xevent->hwnd, &pt);
+         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
+         event->button.x = pt.x;
+         event->button.y = pt.y;
+         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
+       }
+      else
+       {
+         event->button.x = LOWORD (xevent->lParam);
+         event->button.y = HIWORD (xevent->lParam);
+       }
+      event->button.x_root = xevent->pt.x;
+      event->button.y_root = xevent->pt.y;
       event->button.pressure = 0.5;
       event->button.xtilt = 0;
       event->button.ytilt = 0;
@@ -1943,21 +4084,7 @@ gdk_event_translate (GdkEvent *event,
          button_number[1] = -1;
          button_number[0] = event->button.button;
        }
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      if (return_val
-         && p_grab_window != NULL
-         && event->any.window == p_grab_window
-         && p_grab_window != window)
-       {
-         /* Translate coordinates to grabber */
-         pt.x = event->button.x;
-         pt.y = event->button.y;
-         ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
-         event->button.x = pt.x;
-         event->button.y = pt.y;
-         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
-       }
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
     case WM_LBUTTONUP:
@@ -1977,8 +4104,7 @@ gdk_event_translate (GdkEvent *event,
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam),
                         button));
 
-      if (window_private
-         && (window_private->extension_events != 0)
+      if (WINDOW_PRIVATE(window)->extension_events != 0
          && gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print ("...ignored\n"));
@@ -1989,70 +4115,89 @@ gdk_event_translate (GdkEvent *event,
        synthesize_crossing_events (window, xevent);
 
       event->button.type = GDK_BUTTON_RELEASE;
-    buttonup:
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     p_grab_window, p_grab_owner_events, p_grab_mask,
+                     doesnt_want_button_release,
+                     mouse_propagate))
+         break;
       event->button.window = window;
-      if (window_private)
-       mask = window_private->event_mask;
-      else
-       mask = 0;
+#else
+    buttonup:
+      mask = WINDOW_PRIVATE(window)->event_mask;
 
       if (p_grab_window != NULL && !p_grab_owner_events)
        {
          /* Pointer is grabbed with owner_events FALSE */
          GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
-         mask = p_grab_event_mask;
+
+         mask = p_grab_mask;
          if (!(mask & GDK_BUTTON_RELEASE_MASK))
            /* Grabber doesn't want it */
-           break;
+           goto maybe_ungrab;
          else
            event->button.window = p_grab_window;
          GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
                                     GDK_DRAWABLE_XID (p_grab_window)));
        }
-      else if (window_private
-              && !(mask & GDK_BUTTON_RELEASE_MASK))
+      else if (!(mask & GDK_BUTTON_RELEASE_MASK))
        {
-         /* Owner window doesn't want it */
-         if (p_grab_window != NULL && p_grab_owner_events)
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Pointer is grabbed wíth owner_events TRUE */
-             GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
-             mask = p_grab_event_mask;
-             if (!(mask & GDK_BUTTON_RELEASE_MASK))
-               /* Grabber doesn't want it */
-               break;
+             /* No parent; check if grabbed */
+             if (p_grab_window != NULL)
+               {
+                 /* Pointer is grabbed wíth owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 mask = p_grab_mask;
+                 if (!(mask & GDK_BUTTON_RELEASE_MASK))
+                   {
+                     /* Grabber doesn't want it either */
+                     GDK_NOTE (EVENTS, g_print ("...grabber uninterested\n"));
+                     goto maybe_ungrab;
+                   }
+                 else
+                   event->button.window = p_grab_window;
+                 GDK_NOTE (EVENTS,
+                           g_print ("...sending to %#x\n",
+                                    GDK_DRAWABLE_XID (p_grab_window)));
+               }
              else
-               event->button.window = p_grab_window;
-             GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
-                                        GDK_DRAWABLE_XID (p_grab_window)));
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               break;
-             pt.x = LOWORD (xevent->lParam);
-             pt.y = HIWORD (xevent->lParam);
-             ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
-             xevent->lParam = MAKELPARAM (pt.x, pt.y);
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = mouse_propagate (window, xevent);
+             /* Jump back up */
              goto buttonup;
            }
        }
+      else
+       event->button.window = window;
 
+      g_assert (event->button.window == window);
+#endif
       event->button.time = xevent->time;
-      event->button.x = LOWORD (xevent->lParam);
-      event->button.y = HIWORD (xevent->lParam);
-      event->button.x_root = (gfloat)xevent->pt.x;
-      event->button.y_root = (gfloat)xevent->pt.y;
+      if (window == p_grab_window
+         && p_grab_window != orig_window)
+       {
+         /* Translate coordinates to grabber */
+         pt.x = LOWORD (xevent->lParam);
+         pt.y = HIWORD (xevent->lParam);
+         ClientToScreen (xevent->hwnd, &pt);
+         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
+         event->button.x = pt.x;
+         event->button.y = pt.y;
+         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
+       }
+      else
+       {
+         event->button.x = LOWORD (xevent->lParam);
+         event->button.y = HIWORD (xevent->lParam);
+       }
+      event->button.x_root = xevent->pt.x;
+      event->button.y_root = xevent->pt.y;
       event->button.pressure = 0.5;
       event->button.xtilt = 0;
       event->button.ytilt = 0;
@@ -2067,24 +4212,17 @@ gdk_event_translate (GdkEvent *event,
        event->button.state |= GDK_BUTTON3_MASK;
       if (xevent->wParam & MK_SHIFT)
        event->button.state |= GDK_SHIFT_MASK;
+      if (GetKeyState (VK_MENU) < 0)
+       event->button.state |= GDK_MOD1_MASK;
+      if (GetKeyState (VK_CAPITAL) & 0x1)
+       event->button.state |= GDK_LOCK_MASK;
       event->button.button = button;
       event->button.source = GDK_SOURCE_MOUSE;
       event->button.deviceid = GDK_CORE_POINTER;
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      if (return_val
-         && p_grab_window != NULL
-         && event->any.window == p_grab_window
-         && p_grab_window != window)
-       {
-         /* Translate coordinates to grabber */
-         pt.x = event->button.x;
-         pt.y = event->button.y;
-         ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
-         event->button.x = pt.x;
-         event->button.y = pt.y;
-         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
-       }
+
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
+
+    maybe_ungrab:
       if (p_grab_window != NULL
          && p_grab_automatic
          && (event->button.state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) == 0)
@@ -2097,58 +4235,41 @@ gdk_event_translate (GdkEvent *event,
                         xevent->hwnd, xevent->wParam,
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
 
-#if 0
-      /* Try hard not to generate events for windows that shouldn't
-        get any.  This is hard because we don't want pushbuttons to
-        highlight when the cursor moves over them if the window is
-        inactive. We dont want tooltips windows to be active. OTOH,
-        also menus are popup windows, but they definitely should
-        get events. Aw shit. Skip this.
-       */
-      dwStyle = GetWindowLong (xevent->hwnd, GWL_STYLE);
-      if (active == NULL ||
-         !(active == xevent->hwnd
-           || (dwStyle & WS_POPUP)
-           || IsChild (active, xevent->hwnd)))
+      /* HB: only process mouse move messages if we own the active window. */
+
+      GetWindowThreadProcessId(GetActiveWindow(), &pidActWin);
+      GetWindowThreadProcessId(xevent->hwnd, &pidThis);
+      if (pidActWin != pidThis)
        break;
-#else
-      { /* HB: only process mouse move messages
-         * if we own the active window.
-         */
-         DWORD ProcessID_ActWin;
-         DWORD ProcessID_this;
-
-         GetWindowThreadProcessId(GetActiveWindow(), &ProcessID_ActWin);
-         GetWindowThreadProcessId(xevent->hwnd, &ProcessID_this);
-         if (ProcessID_ActWin != ProcessID_this)
-          break;
-     }
-#endif
+
       if (window != curWnd)
        synthesize_crossing_events (window, xevent);
 
-      if (window_private
-         && (window_private->extension_events != 0)
+      if (WINDOW_PRIVATE(window)->extension_events != 0
          && gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print ("...ignored\n"));
          break;
        }
 
-    mousemotion:
       event->motion.type = GDK_MOTION_NOTIFY;
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     p_grab_window, p_grab_owner_events, p_grab_mask,
+                     doesnt_want_button_motion,
+                     mouse_propagate))
+         break;
       event->motion.window = window;
-      if (window_private)
-       mask = window_private->event_mask;
-      else
-       mask = 0;
+#else
+    mousemotion:
+      mask = WINDOW_PRIVATE(window)->event_mask;
 
-      if (p_grab_window && !p_grab_owner_events)
+      if (p_grab_window != NULL && !p_grab_owner_events)
        {
          /* Pointer is grabbed with owner_events FALSE */
-         GDK_NOTE (EVENTS,
-                   g_print ("...grabbed, owner_events FALSE\n"));
-         mask = p_grab_event_mask;
+         GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
+
+         mask = p_grab_mask;
          if (!((mask & GDK_POINTER_MOTION_MASK)
                || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
                    && (mask & GDK_BUTTON_MOTION_MASK))
@@ -2158,70 +4279,83 @@ gdk_event_translate (GdkEvent *event,
                    && (mask & GDK_BUTTON2_MOTION_MASK))
                || ((xevent->wParam & MK_RBUTTON)
                    && (mask & GDK_BUTTON3_MOTION_MASK))))
+           /* Grabber doesn't want it */
            break;
          else
            event->motion.window = p_grab_window;
          GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
                                     GDK_DRAWABLE_XID (p_grab_window)));
        }
-      else if (window_private
-              && !((mask & GDK_POINTER_MOTION_MASK)
-                   || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
-                       && (mask & GDK_BUTTON_MOTION_MASK))
-                   || ((xevent->wParam & MK_LBUTTON)
-                       && (mask & GDK_BUTTON1_MOTION_MASK))
-                   || ((xevent->wParam & MK_MBUTTON)
-                       && (mask & GDK_BUTTON2_MOTION_MASK))
-                   || ((xevent->wParam & MK_RBUTTON)
-                       && (mask & GDK_BUTTON3_MOTION_MASK))))
-       {
-         /* Owner window doesn't want it */
-         if (p_grab_window != NULL && p_grab_owner_events)
+      else if (!((mask & GDK_POINTER_MOTION_MASK)
+                || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
+                    && (mask & GDK_BUTTON_MOTION_MASK))
+                || ((xevent->wParam & MK_LBUTTON)
+                    && (mask & GDK_BUTTON1_MOTION_MASK))
+                || ((xevent->wParam & MK_MBUTTON)
+                    && (mask & GDK_BUTTON2_MOTION_MASK))
+                || ((xevent->wParam & MK_RBUTTON)
+                    && (mask & GDK_BUTTON3_MOTION_MASK))))
+       {
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Pointer is grabbed wíth owner_events TRUE */
-             GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
-             mask = p_grab_event_mask;
-             if (!((p_grab_event_mask & GDK_POINTER_MOTION_MASK)
-                   || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
-                       && (mask & GDK_BUTTON_MOTION_MASK))
-                   || ((xevent->wParam & MK_LBUTTON)
-                       && (mask & GDK_BUTTON1_MOTION_MASK))
-                   || ((xevent->wParam & MK_MBUTTON)
-                       && (mask & GDK_BUTTON2_MOTION_MASK))
-                   || ((xevent->wParam & MK_RBUTTON)
-                       && (mask & GDK_BUTTON3_MOTION_MASK))))
-               /* Grabber doesn't want it either */
-               break;
+             /* No parent; check if grabbed */
+             if (p_grab_window != NULL)
+               {
+                 /* Pointer is grabbed wíth owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 mask = p_grab_mask;
+                 if (!((p_grab_mask & GDK_POINTER_MOTION_MASK)
+                       || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
+                           && (mask & GDK_BUTTON_MOTION_MASK))
+                       || ((xevent->wParam & MK_LBUTTON)
+                           && (mask & GDK_BUTTON1_MOTION_MASK))
+                       || ((xevent->wParam & MK_MBUTTON)
+                           && (mask & GDK_BUTTON2_MOTION_MASK))
+                       || ((xevent->wParam & MK_RBUTTON)
+                           && (mask & GDK_BUTTON3_MOTION_MASK))))
+                   {
+                     /* Grabber doesn't want it either */
+                     GDK_NOTE (EVENTS, g_print ("...grabber uninterested\n"));
+                     break;
+                   }
+                 else
+                   event->motion.window = p_grab_window;
+                 GDK_NOTE (EVENTS,
+                           g_print ("...sending to %#x\n",
+                                    GDK_DRAWABLE_XID (p_grab_window)));
+               }
              else
-               event->motion.window = p_grab_window;
-             GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
-                                        GDK_DRAWABLE_XID (p_grab_window)));
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               break;
-             pt.x = LOWORD (xevent->lParam);
-             pt.y = HIWORD (xevent->lParam);
-             ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
-             xevent->lParam = MAKELPARAM (pt.x, pt.y);
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = mouse_propagate (window, xevent);
+             /* Jump back up */
              goto mousemotion;
            }
        }
-
+      else
+       event->motion.window = window;
+#endif
       event->motion.time = xevent->time;
-      event->motion.x = curX = LOWORD (xevent->lParam);
-      event->motion.y = curY = HIWORD (xevent->lParam);
+      if (window == p_grab_window
+         && p_grab_window != orig_window)
+       {
+         /* Translate coordinates to grabber */
+         pt.x = curX = LOWORD (xevent->lParam);
+         pt.y = curY = HIWORD (xevent->lParam);
+         ClientToScreen (xevent->hwnd, &pt);
+         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
+         event->motion.x = pt.x;
+         event->motion.y = pt.y;
+         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
+       }
+      else
+       {
+         event->motion.x = curX = LOWORD (xevent->lParam);
+         event->motion.y = curY = HIWORD (xevent->lParam);
+       }
       event->motion.x_root = xevent->pt.x;
       event->motion.y_root = xevent->pt.y;
       curXroot = event->motion.x_root;
@@ -2240,6 +4374,10 @@ gdk_event_translate (GdkEvent *event,
        event->button.state |= GDK_BUTTON3_MASK;
       if (xevent->wParam & MK_SHIFT)
        event->button.state |= GDK_SHIFT_MASK;
+      if (GetKeyState (VK_MENU) < 0)
+       event->button.state |= GDK_MOD1_MASK;
+      if (GetKeyState (VK_CAPITAL) & 0x1)
+       event->button.state |= GDK_LOCK_MASK;
       if (mask & GDK_POINTER_MOTION_HINT_MASK)
        event->motion.is_hint = NotifyHint;
       else
@@ -2247,21 +4385,7 @@ gdk_event_translate (GdkEvent *event,
       event->motion.source = GDK_SOURCE_MOUSE;
       event->motion.deviceid = GDK_CORE_POINTER;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      if (return_val
-         && p_grab_window != NULL
-         && event->any.window == p_grab_window
-         && p_grab_window != window)
-       {
-         /* Translate coordinates to grabber */
-         pt.x = event->motion.x;
-         pt.y = event->motion.y;
-         ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
-         event->motion.x = pt.x;
-         event->motion.y = pt.y;
-         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
-       }
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
     case WM_NCMOUSEMOVE:
@@ -2269,13 +4393,9 @@ gdk_event_translate (GdkEvent *event,
                g_print ("WM_NCMOUSEMOVE: %#x  x,y: %d %d\n",
                         xevent->hwnd,
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
-#if 0
-      if (active == NULL || active != xevent->hwnd)
-       break;
-#endif
-      curWnd_private = (GdkWindowPrivate *) curWnd;
-      if (curWnd != NULL
-         && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
+      if (p_TrackMouseEvent == NULL
+         && curWnd != NULL
+         && (WINDOW_PRIVATE(curWnd)->event_mask & GDK_LEAVE_NOTIFY_MASK))
        {
          GDK_NOTE (EVENTS, g_print ("...synthesizing LEAVE_NOTIFY event\n"));
 
@@ -2288,49 +4408,83 @@ gdk_event_translate (GdkEvent *event,
          event->crossing.x_root = curXroot;
          event->crossing.y_root = curYroot;
          event->crossing.mode = GDK_CROSSING_NORMAL;
-         event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+         event->crossing.detail = GDK_NOTIFY_NONLINEAR;
 
          event->crossing.focus = TRUE; /* ??? */
          event->crossing.state = 0; /* ??? */
+         return_val = TRUE;
+       }
+
+      if (curWnd)
+       {
          gdk_window_unref (curWnd);
          curWnd = NULL;
-
-         return_val = TRUE;
        }
+
       break;
 
-    case WM_SETFOCUS:
-    case WM_KILLFOCUS:
-      if (window_private
-         && !(window_private->event_mask & GDK_FOCUS_CHANGE_MASK))
+#ifdef USE_TRACKMOUSEEVENT
+    case WM_MOUSELEAVE:
+      GDK_NOTE (EVENTS, g_print ("WM_MOUSELEAVE: %#x\n", xevent->hwnd));
+
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
        break;
 
+      event->crossing.type = GDK_LEAVE_NOTIFY;
+      event->crossing.window = window;
+      event->crossing.subwindow = NULL;
+      event->crossing.time = xevent->time;
+      event->crossing.x = curX;
+      event->crossing.y = curY;
+      event->crossing.x_root = curXroot;
+      event->crossing.y_root = curYroot;
+      event->crossing.mode = GDK_CROSSING_NORMAL;
+      if (curWnd
+         && IsChild (GDK_DRAWABLE_XID (curWnd), GDK_DRAWABLE_XID (window)))
+       event->crossing.detail = GDK_NOTIFY_INFERIOR;
+      else if (curWnd
+              && IsChild (GDK_DRAWABLE_XID (window), GDK_DRAWABLE_XID (curWnd)))
+       event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+      else
+       event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+
+      event->crossing.focus = TRUE; /* ??? */
+      event->crossing.state = 0; /* ??? */
+
+      if (curWnd)
+       {
+         gdk_window_unref (curWnd);
+         curWnd = NULL;
+       }
+
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
+      break;
+#endif
+       
+    case WM_SETFOCUS:
+    case WM_KILLFOCUS:
       GDK_NOTE (EVENTS, g_print ("WM_%sFOCUS: %#x\n",
-                                (xevent->message == WM_SETFOCUS ? "SET" : "KILL"),
+                                (xevent->message == WM_SETFOCUS ?
+                                 "SET" : "KILL"),
                                 xevent->hwnd));
       
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_FOCUS_CHANGE_MASK))
+       break;
+
       event->focus_change.type = GDK_FOCUS_CHANGE;
       event->focus_change.window = window;
       event->focus_change.in = (xevent->message == WM_SETFOCUS);
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      break;
-#if 0
-    case WM_ACTIVATE:
-      GDK_NOTE (EVENTS, g_print ("WM_ACTIVATE: %#x  %d\n",
-                                xevent->hwnd, LOWORD (xevent->wParam)));
-      if (LOWORD (xevent->wParam) == WA_INACTIVE)
-       active = (HWND) xevent->lParam;
-      else
-       active = xevent->hwnd;
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
-#endif
+
     case WM_ERASEBKGND:
       GDK_NOTE (EVENTS, g_print ("WM_ERASEBKGND: %#x  dc %#x\n",
                                 xevent->hwnd, xevent->wParam));
       
-      if (!window_private || GDK_DRAWABLE_DESTROYED (window))
+      if (GDK_DRAWABLE_DESTROYED (window))
        break;
-      colormap_private = (GdkColormapPrivate *) window_private->drawable.colormap;
+
+      colormap_private = (GdkColormapPrivate *) WINDOW_PRIVATE(window)->drawable.colormap;
       hdc = (HDC) xevent->wParam;
       if (colormap_private
          && colormap_private->xcolormap->rc_palette)
@@ -2350,32 +4504,38 @@ gdk_event_translate (GdkEvent *event,
       *ret_val_flagp = TRUE;
       *ret_valp = 1;
 
-      if (window_private->bg_type == GDK_WIN32_BG_TRANSPARENT)
+      if (WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_TRANSPARENT)
        break;
 
-      if (window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
+      if (WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
        {
          /* If this window should have the same background as the
           * parent, fetch the parent. (And if the same goes for
           * the parent, fetch the grandparent, etc.)
           */
-         while (window_private
-                && window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
-           window_private = (GdkWindowPrivate *) window_private->parent;
+         while (window
+                && WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
+           {
+             gdk_window_unref (window);
+             window = WINDOW_PRIVATE(window)->parent;
+             gdk_window_ref (window);
+           }
        }
 
-      if (window_private->bg_type == GDK_WIN32_BG_PIXEL)
+      if (WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_PIXEL)
        {
          COLORREF bg;
          GetClipBox (hdc, &rect);
-         GDK_NOTE (EVENTS, g_print ("...%dx%d@+%d+%d BG_PIXEL %s\n",
-                                    rect.right - rect.left,
-                                    rect.bottom - rect.top,
-                                    rect.left, rect.top,
-                                    gdk_color_to_string (&window_private->bg_pixel)));
-         bg = GetNearestColor (hdc, RGB (window_private->bg_pixel.red >> 8,
-                                         window_private->bg_pixel.green >> 8,
-                                         window_private->bg_pixel.blue >> 8));
+         GDK_NOTE (EVENTS,
+                   g_print ("...%dx%d@+%d+%d BG_PIXEL %s\n",
+                            rect.right - rect.left,
+                            rect.bottom - rect.top,
+                            rect.left, rect.top,
+                            gdk_color_to_string (&WINDOW_PRIVATE(window)->bg_pixel)));
+         bg = GetNearestColor
+           (hdc, RGB (WINDOW_PRIVATE(window)->bg_pixel.red >> 8,
+                      WINDOW_PRIVATE(window)->bg_pixel.green >> 8,
+                      WINDOW_PRIVATE(window)->bg_pixel.blue >> 8));
          hbr = CreateSolidBrush (bg);
 #if 0
          g_print ("...CreateSolidBrush (%.08x) = %.08x\n", bg, hbr);
@@ -2384,9 +4544,10 @@ gdk_event_translate (GdkEvent *event,
            g_warning ("WM_ERASEBKGND: FillRect failed");
          DeleteObject (hbr);
        }
-      else if (window_private->bg_type == GDK_WIN32_BG_PIXMAP)
+      else if (WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_PIXMAP)
        {
-         pixmap_private = (GdkDrawablePrivate*) window_private->bg_pixmap;
+         pixmap_private =
+           (GdkDrawablePrivate*) WINDOW_PRIVATE(window)->bg_pixmap;
          GetClipBox (hdc, &rect);
 
          if (pixmap_private->width <= 8
@@ -2470,8 +4631,7 @@ gdk_event_translate (GdkEvent *event,
 
       EndPaint (xevent->hwnd, &paintstruct);
 
-      if (window_private
-         && !(window_private->event_mask & GDK_EXPOSURE_MASK))
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_EXPOSURE_MASK))
        break;
 
       event->expose.type = GDK_EXPOSE;
@@ -2482,7 +4642,7 @@ gdk_event_translate (GdkEvent *event,
       event->expose.area.height = paintstruct.rcPaint.bottom - paintstruct.rcPaint.top;
       event->expose.count = 0;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       if (return_val)
        {
          GList *list = queued_events;
@@ -2503,7 +4663,6 @@ gdk_event_translate (GdkEvent *event,
                                 xevent->hwnd,
                                 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
 
-      return_val = FALSE;
       if (LOWORD (xevent->lParam) != HTCLIENT)
        break;
       if (p_grab_window != NULL && p_grab_cursor != NULL)
@@ -2511,44 +4670,27 @@ gdk_event_translate (GdkEvent *event,
          GDK_NOTE (EVENTS, g_print ("...SetCursor(%#x)\n", p_grab_cursor));
          SetCursor (p_grab_cursor);
        }
-      else if (window_private
-              && !GDK_DRAWABLE_DESTROYED (window)
-              && window_private->xcursor)
+      else if (!GDK_DRAWABLE_DESTROYED (window)
+              && WINDOW_PRIVATE(window)->xcursor)
        {
          GDK_NOTE (EVENTS, g_print ("...SetCursor(%#x)\n",
-                                    window_private->xcursor));
-         SetCursor (window_private->xcursor);
+                                    WINDOW_PRIVATE(window)->xcursor));
+         SetCursor (WINDOW_PRIVATE(window)->xcursor);
        }
-      *ret_val_flagp = TRUE;
-      *ret_valp = FALSE;
-      break;
 
-#if 0
-    case WM_QUERYOPEN:
-      GDK_NOTE (EVENTS, g_print ("WM_QUERYOPEN: %#x\n",
-                                xevent->hwnd));
-      *ret_val_flagp = TRUE;
-      *ret_valp = TRUE;
-
-      if (window_private
-         && !(window_private->event_mask & GDK_STRUCTURE_MASK))
-       break;
-
-      event->any.type = GDK_MAP;
-      event->any.window = window;
+      if (window != curWnd)
+       synthesize_crossing_events (window, xevent);
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      *ret_val_flagp = TRUE;
+      *ret_valp = FALSE;
       break;
-#endif
 
-#if 1
     case WM_SHOWWINDOW:
       GDK_NOTE (EVENTS, g_print ("WM_SHOWWINDOW: %#x  %d\n",
                                 xevent->hwnd,
                                 xevent->wParam));
 
-      if (window_private
-         && !(window_private->event_mask & GDK_STRUCTURE_MASK))
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_STRUCTURE_MASK))
        break;
 
       event->any.type = (xevent->wParam ? GDK_MAP : GDK_UNMAP);
@@ -2562,9 +4704,9 @@ gdk_event_translate (GdkEvent *event,
          && k_grab_window == window)
        gdk_keyboard_ungrab (xevent->time);
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
-#endif
+
     case WM_SIZE:
       GDK_NOTE (EVENTS,
                g_print ("WM_SIZE: %#x  %s %dx%d\n",
@@ -2576,13 +4718,11 @@ gdk_event_translate (GdkEvent *event,
                             (xevent->wParam == SIZE_RESTORED ? "RESTORED" : "?"))))),
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
 
-      if (window_private
-         && !(window_private->event_mask & GDK_STRUCTURE_MASK))
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_STRUCTURE_MASK))
        break;
-      if (window_private != NULL
-         && xevent->wParam == SIZE_MINIMIZED)
+
+      if (xevent->wParam == SIZE_MINIMIZED)
        {
-#if 1
          event->any.type = GDK_UNMAP;
          event->any.window = window;
 
@@ -2593,11 +4733,9 @@ gdk_event_translate (GdkEvent *event,
            gdk_keyboard_ungrab (xevent->time);
 
          return_val = !GDK_DRAWABLE_DESTROYED (window);
-#endif
        }
-      else if (window_private != NULL
-              && (xevent->wParam == SIZE_RESTORED
-                  || xevent->wParam == SIZE_MAXIMIZED)
+      else if ((xevent->wParam == SIZE_RESTORED
+               || xevent->wParam == SIZE_MAXIMIZED)
 #if 1
               && GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_CHILD
 #endif
@@ -2615,121 +4753,49 @@ gdk_event_translate (GdkEvent *event,
          event->configure.y = pt.y;
          event->configure.width = LOWORD (xevent->lParam);
          event->configure.height = HIWORD (xevent->lParam);
-         window_private->x = event->configure.x;
-         window_private->y = event->configure.y;
-         window_private->drawable.width = event->configure.width;
-         window_private->drawable.height = event->configure.height;
-         if (window_private->resize_count > 1)
-           window_private->resize_count -= 1;
+         WINDOW_PRIVATE(window)->x = event->configure.x;
+         WINDOW_PRIVATE(window)->y = event->configure.y;
+         WINDOW_PRIVATE(window)->drawable.width = event->configure.width;
+         WINDOW_PRIVATE(window)->drawable.height = event->configure.height;
+         if (WINDOW_PRIVATE(window)->resize_count > 1)
+           WINDOW_PRIVATE(window)->resize_count -= 1;
          
          return_val = !GDK_DRAWABLE_DESTROYED (window);
          if (return_val
-             && window_private->extension_events != 0
+             && WINDOW_PRIVATE(window)->extension_events != 0
              && gdk_input_vtable.configure_event)
            gdk_input_vtable.configure_event (&event->configure, window);
        }
       break;
-#if 0 /* Bernd Herd suggests responding to WM_GETMINMAXINFO instead,
-       * which indeed is much easier.
-       */
-    case WM_SIZING:
-      GDK_NOTE (EVENTS, g_print ("WM_SIZING: %#x\n", xevent->hwnd));
-      if (ret_val_flagp == NULL)
-         g_warning ("ret_val_flagp is NULL but we got a WM_SIZING?");
-      else if (window_private != NULL
-              && window_private->hint_flags &
-              (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE))
-       {
-         LPRECT lprc = (LPRECT) xevent->lParam;
 
-         if (window_private->hint_flags & GDK_HINT_MIN_SIZE)
-           {
-             gint w = lprc->right - lprc->left;
-             gint h = lprc->bottom - lprc->top;
-
-             if (w < window_private->hint_min_width)
-               {
-                 if (xevent->wParam == WMSZ_BOTTOMLEFT
-                     || xevent->wParam == WMSZ_LEFT
-                     || xevent->wParam == WMSZ_TOPLEFT)
-                   lprc->left = lprc->right - window_private->hint_min_width;
-                 else
-                   lprc->right = lprc->left + window_private->hint_min_width;
-                 *ret_val_flagp = TRUE;
-                 *ret_valp = TRUE;
-               }
-             if (h < window_private->hint_min_height)
-               {
-                 if (xevent->wParam == WMSZ_BOTTOMLEFT
-                     || xevent->wParam == WMSZ_BOTTOM
-                     || xevent->wParam == WMSZ_BOTTOMRIGHT)
-                   lprc->bottom = lprc->top + window_private->hint_min_height;
-                 else
-                   lprc->top = lprc->bottom - window_private->hint_min_height;
-                 *ret_val_flagp = TRUE;
-                 *ret_valp = TRUE;
-               }
-           }
-         if (window_private->hint_flags & GDK_HINT_MAX_SIZE)
-           {
-             gint w = lprc->right - lprc->left;
-             gint h = lprc->bottom - lprc->top;
-
-             if (w > window_private->hint_max_width)
-               {
-                 if (xevent->wParam == WMSZ_BOTTOMLEFT
-                     || xevent->wParam == WMSZ_LEFT
-                     || xevent->wParam == WMSZ_TOPLEFT)
-                   lprc->left = lprc->right - window_private->hint_max_width;
-                 else
-                   lprc->right = lprc->left + window_private->hint_max_width;
-                 *ret_val_flagp = TRUE;
-                 *ret_valp = TRUE;
-               }
-             if (h > window_private->hint_max_height)
-               {
-                 if (xevent->wParam == WMSZ_BOTTOMLEFT
-                     || xevent->wParam == WMSZ_BOTTOM
-                     || xevent->wParam == WMSZ_BOTTOMRIGHT)
-                   lprc->bottom = lprc->top + window_private->hint_max_height;
-                 else
-                   lprc->top = lprc->bottom - window_private->hint_max_height;
-                 *ret_val_flagp = TRUE;
-                 *ret_valp = TRUE;
-               }
-           }
-       }
-      break;
-#else
     case WM_GETMINMAXINFO:
       GDK_NOTE (EVENTS, g_print ("WM_GETMINMAXINFO: %#x\n", xevent->hwnd));
+
       lpmmi = (MINMAXINFO*) xevent->lParam;
-      if (window_private->hint_flags & GDK_HINT_MIN_SIZE)
+      if (WINDOW_PRIVATE(window)->hint_flags & GDK_HINT_MIN_SIZE)
        {
-         lpmmi->ptMinTrackSize.x = window_private->hint_min_width;
-         lpmmi->ptMinTrackSize.y = window_private->hint_min_height;
+         lpmmi->ptMinTrackSize.x = WINDOW_PRIVATE(window)->hint_min_width;
+         lpmmi->ptMinTrackSize.y = WINDOW_PRIVATE(window)->hint_min_height;
        }
-      if (window_private->hint_flags & GDK_HINT_MAX_SIZE)
+      if (WINDOW_PRIVATE(window)->hint_flags & GDK_HINT_MAX_SIZE)
        {
-         lpmmi->ptMaxTrackSize.x = window_private->hint_max_width;
-         lpmmi->ptMaxTrackSize.y = window_private->hint_max_height;
+         lpmmi->ptMaxTrackSize.x = WINDOW_PRIVATE(window)->hint_max_width;
+         lpmmi->ptMaxTrackSize.y = WINDOW_PRIVATE(window)->hint_max_height;
            
-         lpmmi->ptMaxSize.x = window_private->hint_max_width;
-         lpmmi->ptMaxSize.y = window_private->hint_max_height;
+         lpmmi->ptMaxSize.x = WINDOW_PRIVATE(window)->hint_max_width;
+         lpmmi->ptMaxSize.y = WINDOW_PRIVATE(window)->hint_max_height;
        }
       break;
-#endif
 
     case WM_MOVE:
       GDK_NOTE (EVENTS, g_print ("WM_MOVE: %#x  +%d+%d\n",
                                 xevent->hwnd,
                                 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
 
-      if (window_private
-         && !(window_private->event_mask & GDK_STRUCTURE_MASK))
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_STRUCTURE_MASK))
        break;
-      if (window_private != NULL
-         && GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_CHILD)
+
+      if (GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_CHILD)
        {
          event->configure.type = GDK_CONFIGURE;
          event->configure.window = window;
@@ -2738,10 +4804,10 @@ gdk_event_translate (GdkEvent *event,
          GetClientRect (xevent->hwnd, &rect);
          event->configure.width = rect.right;
          event->configure.height = rect.bottom;
-         window_private->x = event->configure.x;
-         window_private->y = event->configure.y;
-         window_private->drawable.width = event->configure.width;
-         window_private->drawable.height = event->configure.height;
+         WINDOW_PRIVATE(window)->x = event->configure.x;
+         WINDOW_PRIVATE(window)->y = event->configure.y;
+         WINDOW_PRIVATE(window)->drawable.width = event->configure.width;
+         WINDOW_PRIVATE(window)->drawable.height = event->configure.height;
          
          return_val = !GDK_DRAWABLE_DESTROYED (window);
        }
@@ -2749,10 +4815,11 @@ gdk_event_translate (GdkEvent *event,
 
     case WM_CLOSE:
       GDK_NOTE (EVENTS, g_print ("WM_CLOSE: %#x\n", xevent->hwnd));
+
       event->any.type = GDK_DELETE;
       event->any.window = window;
       
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
 #if 0
@@ -2795,7 +4862,7 @@ gdk_event_translate (GdkEvent *event,
       event->selection.property = gdk_selection_property;
       event->selection.requestor = (guint32) xevent->hwnd;
       event->selection.time = xevent->time;
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
 #else
       /* Test code, to see if SetClipboardData works when called from
        * the window procedure.
@@ -2817,6 +4884,7 @@ gdk_event_translate (GdkEvent *event,
 
     case WM_DESTROY:
       GDK_NOTE (EVENTS, g_print ("WM_DESTROY: %#x\n", xevent->hwnd));
+
       event->any.type = GDK_DESTROY;
       event->any.window = window;
       if (window != NULL && window == curWnd)
@@ -2831,7 +4899,7 @@ gdk_event_translate (GdkEvent *event,
       if (k_grab_window == window)
        gdk_keyboard_ungrab (xevent->time);
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
 #ifdef HAVE_WINTAB
@@ -2871,6 +4939,8 @@ bypass_switch:
           (event->any.type == GDK_LEAVE_NOTIFY)) &&
          (event->crossing.subwindow != NULL))
        gdk_window_ref (event->crossing.subwindow);
+
+      GDK_NOTE (EVENTS, print_event (event));
     }
   else
     {
@@ -2891,17 +4961,31 @@ gdk_events_queue (void)
   GList *node;
   GdkEvent *event;
   MSG msg;
-
-  GDK_NOTE (EVENTS, g_print ("gdk_events_queue: %s\n",
-                            (queued_events ? "yes" : "none")));
+  LRESULT lres;
 
   while (!gdk_event_queue_find_first()
         && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
     {
-      GDK_NOTE (EVENTS, g_print ("gdk_events_queue:  PeekMessage: %#x\n",
-                                msg.message));
-      TranslateMessage (&msg);
+      GDK_NOTE (EVENTS, g_print ("PeekMessage: %#x %#x\n",
+                                msg.hwnd, msg.message));
 
+      if (paimmmpo == NULL
+         || (paimmmpo->lpVtbl->OnTranslateMessage) (paimmmpo, &msg) != S_OK)
+       TranslateMessage (&msg);
+
+#ifdef USE_DISPATCHMESSAGE
+      if (msg.message == g_pipe_readable_msg)
+       {
+         GDK_NOTE (EVENTS, g_print ("g_pipe_readable_msg: %d %d\n",
+                                    msg.wParam, msg.lParam));
+
+         g_io_channel_win32_pipe_readable (msg.wParam, msg.lParam);
+
+         continue;
+       }
+      
+      DispatchMessage (&msg);
+#else
       event = gdk_event_new ();
       
       event->any.type = GDK_NOTHING;
@@ -2914,14 +4998,20 @@ gdk_events_queue (void)
       node = queued_tail;
 
       if (gdk_event_translate (event, &msg, NULL, NULL))
-         ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+       ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
       else
        {
-         DefWindowProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
+         if (paimmapp == NULL
+             || (paimmapp->lpVtbl->OnDefWindowProc) (paimmapp, msg.hwnd,
+                                                     msg.message,
+                                                     msg.wParam, msg.lParam,
+                                                     &lres) == S_FALSE)
+           DefWindowProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
          gdk_event_queue_remove_link (node);
          g_list_free_1 (node);
          gdk_event_free (event);
        }
+#endif
     }
 }
 
@@ -2937,8 +5027,6 @@ gdk_event_prepare (gpointer  source_data,
 
   *timeout = -1;
 
-  GDK_NOTE (EVENTS, g_print ("gdk_event_prepare\n"));
-
   retval = (gdk_event_queue_find_first () != NULL)
              || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
 
@@ -2954,8 +5042,6 @@ gdk_event_check (gpointer  source_data,
   MSG msg;
   gboolean retval;
   
-  GDK_NOTE (EVENTS, g_print ("gdk_event_check\n"));
-
   GDK_THREADS_ENTER ();
 
   if (event_poll_fd.revents & G_IO_IN)
@@ -2994,8 +5080,6 @@ gdk_event_dispatch (gpointer  source_data,
 {
   GdkEvent *event;
  
-  GDK_NOTE (EVENTS, g_print ("gdk_event_dispatch\n"));
-
   GDK_THREADS_ENTER ();
 
   gdk_events_queue();
index 53097d20b741efe05fb6f4b06489106ceb04ebb6..7ac8169786d662eb6477c8151c63e029fa89d17f 100644 (file)
 
 #include "config.h"
 
+#define NEW_PROPAGATION_CODE
+
+#define USE_DISPATCHMESSAGE
+
+/* Cannot use TrackMouseEvent, as the stupid WM_MOUSELEAVE message
+ * doesn't tell us where the mouse has gone. Thus we cannot use it to
+ * generate a correct GdkNotifyType. Pity, as using TrackMouseEvent
+ * otherwise would make it possible to reliably generate
+ * GDK_LEAVE_NOTIFY events, which would help get rid of those pesky
+ * tooltips sometimes popping up in the wrong place.
+ */
+/* define USE_TRACKMOUSEEVENT */
+
 #include <stdio.h>
 
+#include <windows.h>
+
+#ifdef HAVE_WINTAB
+#include <wintab.h>
+#endif
+
+#include <objbase.h>
+#include <imm.h>
+
+#ifdef HAVE_DIMM_H
+#include <dimm.h>
+#else
+#include "surrogate-dimm.h"
+#endif
+
 #include "gdk.h"
-#include "gdkprivate.h"
 #include "gdkx.h"
 
 #include "gdkkeysyms.h"
 
-#ifdef HAVE_WINTAB
-#include <wintab.h>
-#endif
 #include "gdkinputprivate.h"
 
 #define PING() printf("%s: %d\n",__FILE__,__LINE__),fflush(stdout)
 
+#define WINDOW_PRIVATE(wp) ((GdkWindowPrivate *) (wp))
+
 typedef struct _GdkIOClosure GdkIOClosure;
 typedef struct _GdkEventPrivate GdkEventPrivate;
 
@@ -80,10 +106,10 @@ struct _GdkEventPrivate
 
 static GdkEvent *gdk_event_new         (void);
 static GdkFilterReturn
-               gdk_event_apply_filters (MSG      *xevent,
+                gdk_event_apply_filters(MSG      *xevent,
                                         GdkEvent *event,
                                         GList    *filters);
-static gint     gdk_event_translate    (GdkEvent *event, 
+static gboolean  gdk_event_translate   (GdkEvent *event, 
                                         MSG      *xevent,
                                         gboolean *ret_val_flagp,
                                         gint     *ret_valp);
@@ -125,7 +151,7 @@ static GdkWindow *k_grab_window = NULL; /* Window the holds the
 static GList *client_filters;  /* Filters for client messages */
 
 static gboolean p_grab_automatic;
-static GdkEventMask p_grab_event_mask;
+static GdkEventMask p_grab_mask;
 static gboolean p_grab_owner_events, k_grab_owner_events;
 static HCURSOR p_grab_cursor;
 
@@ -158,22 +184,26 @@ static UINT gdk_ping_msg;
 static gboolean ignore_WM_CHAR = FALSE;
 static gboolean is_AltGr_key = FALSE;
 
+static IActiveIMMApp *paimmapp = NULL;
+static IActiveIMMMessagePumpOwner *paimmmpo = NULL;
+
 LRESULT CALLBACK 
-gdk_WindowProc(HWND hwnd,
-              UINT message,
-              WPARAM wParam,
-              LPARAM lParam)
+gdk_WindowProc (HWND hWnd,
+               UINT message,
+               WPARAM wParam,
+               LPARAM lParam)
 {
   GdkEvent event;
   GdkEvent *eventp;
   MSG msg;
   DWORD pos;
+  LRESULT lres;
   gint ret_val;
   gboolean ret_val_flag;
 
-  GDK_NOTE (EVENTS, g_print ("gdk_WindowProc: %#x\n", message));
+  GDK_NOTE (EVENTS, g_print ("gdk_WindowProc: %#x %#.03x\n", hWnd, message));
 
-  msg.hwnd = hwnd;
+  msg.hwnd = hWnd;
   msg.message = message;
   msg.wParam = wParam;
   msg.lParam = lParam;
@@ -182,12 +212,14 @@ gdk_WindowProc(HWND hwnd,
   msg.pt.x = LOWORD (pos);
   msg.pt.y = HIWORD (pos);
 
+  ((GdkEventPrivate *)&event)->flags |= GDK_EVENT_PENDING;
   if (gdk_event_translate (&event, &msg, &ret_val_flag, &ret_val))
     {
+      ((GdkEventPrivate *)&event)->flags &= ~GDK_EVENT_PENDING;
 #if 1
-      /* Compress configure events */
       if (event.any.type == GDK_CONFIGURE)
        {
+         /* Compress configure events */
          GList *list = queued_events;
 
          while (list != NULL
@@ -203,6 +235,29 @@ gdk_WindowProc(HWND hwnd,
              return FALSE;
            }
        }
+      else if (event.any.type == GDK_EXPOSE)
+       {
+         /* Compress expose events */
+         GList *list = queued_events;
+
+         while (list != NULL
+                && (((GdkEvent *)list->data)->any.type != GDK_EXPOSE
+                    || ((GdkEvent *)list->data)->any.window != event.any.window))
+           list = list->next;
+         if (list != NULL)
+           {
+             GdkRectangle u;
+
+             gdk_rectangle_union (&event.expose.area,
+                                  &((GdkEvent *)list->data)->expose.area,
+                                  &u);
+             ((GdkEvent *)list->data)->expose.area = u;
+             gdk_window_unref (event.any.window);
+             /* Wake up WaitMessage */
+             PostMessage (NULL, gdk_ping_msg, 0, 0);
+             return FALSE;
+           }
+       }
 #endif
       eventp = gdk_event_new ();
       *eventp = event;
@@ -240,7 +295,13 @@ gdk_WindowProc(HWND hwnd,
   if (ret_val_flag)
     return ret_val;
   else
-    return DefWindowProc (hwnd, message, wParam, lParam);
+    {
+      if (paimmapp == NULL
+         || (*paimmapp->lpVtbl->OnDefWindowProc) (paimmapp, hWnd, message, wParam, lParam, &lres) == S_FALSE)
+       return DefWindowProc (hWnd, message, wParam, lParam);
+      else
+       return lres;
+    }
 }
 
 /*********************************************
@@ -319,8 +380,18 @@ gdk_event_queue_append (GdkEvent *event)
 void 
 gdk_events_init (void)
 {
+  HRESULT hres;
+  HMODULE user32;
+  HINSTANCE commctrl32;
+
   if (g_pipe_readable_msg == 0)
     g_pipe_readable_msg = RegisterWindowMessage ("g-pipe-readable");
+  GDK_NOTE (EVENTS, g_print ("g-pipe-readable = %#.03x\n",
+                            g_pipe_readable_msg));
+
+  gdk_ping_msg = RegisterWindowMessage ("gdk-ping");
+  GDK_NOTE (EVENTS, g_print ("gdk-ping = %#.03x\n",
+                            gdk_ping_msg));
 
   g_source_add (GDK_PRIORITY_EVENTS, TRUE, &event_funcs, NULL, NULL, NULL);
 
@@ -336,7 +407,34 @@ gdk_events_init (void)
   button_number[0] = -1;
   button_number[1] = -1;
 
-  gdk_ping_msg = RegisterWindowMessage ("gdk-ping");
+  hres = CoCreateInstance (&CLSID_CActiveIMM,
+                          NULL,
+                          CLSCTX_ALL,
+                          &IID_IActiveIMMApp,
+                          (LPVOID *) &paimmapp);
+  
+  if (hres == S_OK)
+    {
+      GDK_NOTE (EVENTS, g_print ("IActiveIMMApp created %#x\n",
+                                paimmapp));
+      (*paimmapp->lpVtbl->Activate) (paimmapp, TRUE);
+      
+      hres = (*paimmapp->lpVtbl->QueryInterface) (paimmapp, &IID_IActiveIMMMessagePumpOwner, &paimmmpo);
+      GDK_NOTE (EVENTS, g_print ("IActiveIMMMessagePumpOwner created %#x\n",
+                                paimmmpo));
+      (paimmmpo->lpVtbl->Start) (paimmmpo);
+    }
+
+#ifdef USE_TRACKMOUSEEVENT
+  user32 = GetModuleHandle ("user32.dll");
+  if ((p_TrackMouseEvent = GetProcAddress (user32, "TrackMouseEvent")) == NULL)
+    {
+      if ((commctrl32 = LoadLibrary ("commctrl32.dll")) != NULL)
+       p_TrackMouseEvent = GetProcAddress (commctrl32, "_TrackMouseEvent");
+    }
+  if (p_TrackMouseEvent != NULL)
+    GDK_NOTE (EVENTS, g_print ("Using TrackMouseEvent to detect leave events\n"));
+#endif
 }
 
 /*
@@ -809,12 +907,16 @@ gdk_pointer_grab (GdkWindow *       window,
     {
       if (!GDK_DRAWABLE_DESTROYED (window))
       {
-       GDK_NOTE (EVENTS, g_print ("gdk_pointer_grab: %#x %s %#x\n",
+       GDK_NOTE (EVENTS, g_print ("gdk_pointer_grab: %#x %s %#x%s%s\n",
                                   xwindow,
                                   (owner_events ? "TRUE" : "FALSE"),
-                                  xcursor));
-       p_grab_event_mask = event_mask;
-       p_grab_owner_events = owner_events != 0;
+                                  xcursor,
+                                  (event_mask & GDK_BUTTON_PRESS_MASK) ?
+                                  " PRESS" : "",
+                                  (event_mask & GDK_BUTTON_RELEASE_MASK) ?
+                                  " RELEASE" : ""));
+       p_grab_mask = event_mask;
+       p_grab_owner_events = (owner_events != 0);
        p_grab_automatic = FALSE;
 
 #if 0 /* Menus don't work if we use mouse capture. Pity, because many other
@@ -1076,15 +1178,1887 @@ gdk_add_client_message_filter (GdkAtom       message_type,
   client_filters = g_list_prepend (client_filters, filter);
 }
 
+/* Thanks to Markus G. Kuhn <mkuhn@acm.org> for the ksysym<->Unicode
+ * mapping functions, from the xterm sources.
+ */
+
+struct k2u {
+  unsigned short keysym;
+  unsigned short ucs;
+} k2utab[] = {
+  { 0x01a1, 0x0104 }, /*                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
+  { 0x01a2, 0x02d8 }, /*                       breve ˘ BREVE */
+  { 0x01a3, 0x0141 }, /*                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
+  { 0x01a5, 0x013d }, /*                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
+  { 0x01a6, 0x015a }, /*                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
+  { 0x01a9, 0x0160 }, /*                      Scaron Š LATIN CAPITAL LETTER S WITH CARON */
+  { 0x01aa, 0x015e }, /*                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
+  { 0x01ab, 0x0164 }, /*                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
+  { 0x01ac, 0x0179 }, /*                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
+  { 0x01ae, 0x017d }, /*                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
+  { 0x01af, 0x017b }, /*                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+  { 0x01b1, 0x0105 }, /*                     aogonek ą LATIN SMALL LETTER A WITH OGONEK */
+  { 0x01b2, 0x02db }, /*                      ogonek ˛ OGONEK */
+  { 0x01b3, 0x0142 }, /*                     lstroke ł LATIN SMALL LETTER L WITH STROKE */
+  { 0x01b5, 0x013e }, /*                      lcaron ľ LATIN SMALL LETTER L WITH CARON */
+  { 0x01b6, 0x015b }, /*                      sacute ś LATIN SMALL LETTER S WITH ACUTE */
+  { 0x01b7, 0x02c7 }, /*                       caron ˇ CARON */
+  { 0x01b9, 0x0161 }, /*                      scaron š LATIN SMALL LETTER S WITH CARON */
+  { 0x01ba, 0x015f }, /*                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
+  { 0x01bb, 0x0165 }, /*                      tcaron ť LATIN SMALL LETTER T WITH CARON */
+  { 0x01bc, 0x017a }, /*                      zacute ź LATIN SMALL LETTER Z WITH ACUTE */
+  { 0x01bd, 0x02dd }, /*                 doubleacute ˝ DOUBLE ACUTE ACCENT */
+  { 0x01be, 0x017e }, /*                      zcaron ž LATIN SMALL LETTER Z WITH CARON */
+  { 0x01bf, 0x017c }, /*                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
+  { 0x01c0, 0x0154 }, /*                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
+  { 0x01c3, 0x0102 }, /*                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
+  { 0x01c5, 0x0139 }, /*                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
+  { 0x01c6, 0x0106 }, /*                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
+  { 0x01c8, 0x010c }, /*                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
+  { 0x01ca, 0x0118 }, /*                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
+  { 0x01cc, 0x011a }, /*                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
+  { 0x01cf, 0x010e }, /*                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
+  { 0x01d0, 0x0110 }, /*                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
+  { 0x01d1, 0x0143 }, /*                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
+  { 0x01d2, 0x0147 }, /*                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
+  { 0x01d5, 0x0150 }, /*                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+  { 0x01d8, 0x0158 }, /*                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
+  { 0x01d9, 0x016e }, /*                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
+  { 0x01db, 0x0170 }, /*                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+  { 0x01de, 0x0162 }, /*                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
+  { 0x01e0, 0x0155 }, /*                      racute ŕ LATIN SMALL LETTER R WITH ACUTE */
+  { 0x01e3, 0x0103 }, /*                      abreve ă LATIN SMALL LETTER A WITH BREVE */
+  { 0x01e5, 0x013a }, /*                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
+  { 0x01e6, 0x0107 }, /*                      cacute ć LATIN SMALL LETTER C WITH ACUTE */
+  { 0x01e8, 0x010d }, /*                      ccaron č LATIN SMALL LETTER C WITH CARON */
+  { 0x01ea, 0x0119 }, /*                     eogonek ę LATIN SMALL LETTER E WITH OGONEK */
+  { 0x01ec, 0x011b }, /*                      ecaron ě LATIN SMALL LETTER E WITH CARON */
+  { 0x01ef, 0x010f }, /*                      dcaron ď LATIN SMALL LETTER D WITH CARON */
+  { 0x01f0, 0x0111 }, /*                     dstroke đ LATIN SMALL LETTER D WITH STROKE */
+  { 0x01f1, 0x0144 }, /*                      nacute ń LATIN SMALL LETTER N WITH ACUTE */
+  { 0x01f2, 0x0148 }, /*                      ncaron ň LATIN SMALL LETTER N WITH CARON */
+  { 0x01f5, 0x0151 }, /*                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+  { 0x01f8, 0x0159 }, /*                      rcaron ř LATIN SMALL LETTER R WITH CARON */
+  { 0x01f9, 0x016f }, /*                       uring ů LATIN SMALL LETTER U WITH RING ABOVE */
+  { 0x01fb, 0x0171 }, /*                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+  { 0x01fe, 0x0163 }, /*                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
+  { 0x01ff, 0x02d9 }, /*                    abovedot ˙ DOT ABOVE */
+  { 0x02a1, 0x0126 }, /*                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
+  { 0x02a6, 0x0124 }, /*                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+  { 0x02a9, 0x0130 }, /*                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
+  { 0x02ab, 0x011e }, /*                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
+  { 0x02ac, 0x0134 }, /*                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+  { 0x02b1, 0x0127 }, /*                     hstroke ħ LATIN SMALL LETTER H WITH STROKE */
+  { 0x02b6, 0x0125 }, /*                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
+  { 0x02b9, 0x0131 }, /*                    idotless ı LATIN SMALL LETTER DOTLESS I */
+  { 0x02bb, 0x011f }, /*                      gbreve ğ LATIN SMALL LETTER G WITH BREVE */
+  { 0x02bc, 0x0135 }, /*                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
+  { 0x02c5, 0x010a }, /*                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
+  { 0x02c6, 0x0108 }, /*                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+  { 0x02d5, 0x0120 }, /*                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
+  { 0x02d8, 0x011c }, /*                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+  { 0x02dd, 0x016c }, /*                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
+  { 0x02de, 0x015c }, /*                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+  { 0x02e5, 0x010b }, /*                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
+  { 0x02e6, 0x0109 }, /*                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
+  { 0x02f5, 0x0121 }, /*                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
+  { 0x02f8, 0x011d }, /*                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
+  { 0x02fd, 0x016d }, /*                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
+  { 0x02fe, 0x015d }, /*                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
+  { 0x03a2, 0x0138 }, /*                         kra ĸ LATIN SMALL LETTER KRA */
+  { 0x03a3, 0x0156 }, /*                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
+  { 0x03a5, 0x0128 }, /*                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
+  { 0x03a6, 0x013b }, /*                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
+  { 0x03aa, 0x0112 }, /*                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
+  { 0x03ab, 0x0122 }, /*                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
+  { 0x03ac, 0x0166 }, /*                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
+  { 0x03b3, 0x0157 }, /*                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
+  { 0x03b5, 0x0129 }, /*                      itilde ĩ LATIN SMALL LETTER I WITH TILDE */
+  { 0x03b6, 0x013c }, /*                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
+  { 0x03ba, 0x0113 }, /*                     emacron ē LATIN SMALL LETTER E WITH MACRON */
+  { 0x03bb, 0x0123 }, /*                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
+  { 0x03bc, 0x0167 }, /*                      tslash ŧ LATIN SMALL LETTER T WITH STROKE */
+  { 0x03bd, 0x014a }, /*                         ENG Ŋ LATIN CAPITAL LETTER ENG */
+  { 0x03bf, 0x014b }, /*                         eng ŋ LATIN SMALL LETTER ENG */
+  { 0x03c0, 0x0100 }, /*                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
+  { 0x03c7, 0x012e }, /*                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
+  { 0x03cc, 0x0116 }, /*                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
+  { 0x03cf, 0x012a }, /*                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
+  { 0x03d1, 0x0145 }, /*                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
+  { 0x03d2, 0x014c }, /*                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
+  { 0x03d3, 0x0136 }, /*                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
+  { 0x03d9, 0x0172 }, /*                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
+  { 0x03dd, 0x0168 }, /*                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
+  { 0x03de, 0x016a }, /*                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
+  { 0x03e0, 0x0101 }, /*                     amacron ā LATIN SMALL LETTER A WITH MACRON */
+  { 0x03e7, 0x012f }, /*                     iogonek į LATIN SMALL LETTER I WITH OGONEK */
+  { 0x03ec, 0x0117 }, /*                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
+  { 0x03ef, 0x012b }, /*                     imacron ī LATIN SMALL LETTER I WITH MACRON */
+  { 0x03f1, 0x0146 }, /*                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
+  { 0x03f2, 0x014d }, /*                     omacron ō LATIN SMALL LETTER O WITH MACRON */
+  { 0x03f3, 0x0137 }, /*                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
+  { 0x03f9, 0x0173 }, /*                     uogonek ų LATIN SMALL LETTER U WITH OGONEK */
+  { 0x03fd, 0x0169 }, /*                      utilde ũ LATIN SMALL LETTER U WITH TILDE */
+  { 0x03fe, 0x016b }, /*                     umacron ū LATIN SMALL LETTER U WITH MACRON */
+  { 0x047e, 0x203e }, /*                    overline ‾ OVERLINE */
+  { 0x04a1, 0x3002 }, /*               kana_fullstop 。 IDEOGRAPHIC FULL STOP */
+  { 0x04a2, 0x300c }, /*         kana_openingbracket 「 LEFT CORNER BRACKET */
+  { 0x04a3, 0x300d }, /*         kana_closingbracket 」 RIGHT CORNER BRACKET */
+  { 0x04a4, 0x3001 }, /*                  kana_comma 、 IDEOGRAPHIC COMMA */
+  { 0x04a5, 0x30fb }, /*            kana_conjunctive ・ KATAKANA MIDDLE DOT */
+  { 0x04a6, 0x30f2 }, /*                     kana_WO ヲ KATAKANA LETTER WO */
+  { 0x04a7, 0x30a1 }, /*                      kana_a ァ KATAKANA LETTER SMALL A */
+  { 0x04a8, 0x30a3 }, /*                      kana_i ィ KATAKANA LETTER SMALL I */
+  { 0x04a9, 0x30a5 }, /*                      kana_u ゥ KATAKANA LETTER SMALL U */
+  { 0x04aa, 0x30a7 }, /*                      kana_e ェ KATAKANA LETTER SMALL E */
+  { 0x04ab, 0x30a9 }, /*                      kana_o ォ KATAKANA LETTER SMALL O */
+  { 0x04ac, 0x30e3 }, /*                     kana_ya ャ KATAKANA LETTER SMALL YA */
+  { 0x04ad, 0x30e5 }, /*                     kana_yu ュ KATAKANA LETTER SMALL YU */
+  { 0x04ae, 0x30e7 }, /*                     kana_yo ョ KATAKANA LETTER SMALL YO */
+  { 0x04af, 0x30c3 }, /*                    kana_tsu ッ KATAKANA LETTER SMALL TU */
+  { 0x04b0, 0x30fc }, /*              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+  { 0x04b1, 0x30a2 }, /*                      kana_A ア KATAKANA LETTER A */
+  { 0x04b2, 0x30a4 }, /*                      kana_I イ KATAKANA LETTER I */
+  { 0x04b3, 0x30a6 }, /*                      kana_U ウ KATAKANA LETTER U */
+  { 0x04b4, 0x30a8 }, /*                      kana_E エ KATAKANA LETTER E */
+  { 0x04b5, 0x30aa }, /*                      kana_O オ KATAKANA LETTER O */
+  { 0x04b6, 0x30ab }, /*                     kana_KA カ KATAKANA LETTER KA */
+  { 0x04b7, 0x30ad }, /*                     kana_KI キ KATAKANA LETTER KI */
+  { 0x04b8, 0x30af }, /*                     kana_KU ク KATAKANA LETTER KU */
+  { 0x04b9, 0x30b1 }, /*                     kana_KE ケ KATAKANA LETTER KE */
+  { 0x04ba, 0x30b3 }, /*                     kana_KO コ KATAKANA LETTER KO */
+  { 0x04bb, 0x30b5 }, /*                     kana_SA サ KATAKANA LETTER SA */
+  { 0x04bc, 0x30b7 }, /*                    kana_SHI シ KATAKANA LETTER SI */
+  { 0x04bd, 0x30b9 }, /*                     kana_SU ス KATAKANA LETTER SU */
+  { 0x04be, 0x30bb }, /*                     kana_SE セ KATAKANA LETTER SE */
+  { 0x04bf, 0x30bd }, /*                     kana_SO ソ KATAKANA LETTER SO */
+  { 0x04c0, 0x30bf }, /*                     kana_TA タ KATAKANA LETTER TA */
+  { 0x04c1, 0x30c1 }, /*                    kana_CHI チ KATAKANA LETTER TI */
+  { 0x04c2, 0x30c4 }, /*                    kana_TSU ツ KATAKANA LETTER TU */
+  { 0x04c3, 0x30c6 }, /*                     kana_TE テ KATAKANA LETTER TE */
+  { 0x04c4, 0x30c8 }, /*                     kana_TO ト KATAKANA LETTER TO */
+  { 0x04c5, 0x30ca }, /*                     kana_NA ナ KATAKANA LETTER NA */
+  { 0x04c6, 0x30cb }, /*                     kana_NI ニ KATAKANA LETTER NI */
+  { 0x04c7, 0x30cc }, /*                     kana_NU ヌ KATAKANA LETTER NU */
+  { 0x04c8, 0x30cd }, /*                     kana_NE ネ KATAKANA LETTER NE */
+  { 0x04c9, 0x30ce }, /*                     kana_NO ノ KATAKANA LETTER NO */
+  { 0x04ca, 0x30cf }, /*                     kana_HA ハ KATAKANA LETTER HA */
+  { 0x04cb, 0x30d2 }, /*                     kana_HI ヒ KATAKANA LETTER HI */
+  { 0x04cc, 0x30d5 }, /*                     kana_FU フ KATAKANA LETTER HU */
+  { 0x04cd, 0x30d8 }, /*                     kana_HE ヘ KATAKANA LETTER HE */
+  { 0x04ce, 0x30db }, /*                     kana_HO ホ KATAKANA LETTER HO */
+  { 0x04cf, 0x30de }, /*                     kana_MA マ KATAKANA LETTER MA */
+  { 0x04d0, 0x30df }, /*                     kana_MI ミ KATAKANA LETTER MI */
+  { 0x04d1, 0x30e0 }, /*                     kana_MU ム KATAKANA LETTER MU */
+  { 0x04d2, 0x30e1 }, /*                     kana_ME メ KATAKANA LETTER ME */
+  { 0x04d3, 0x30e2 }, /*                     kana_MO モ KATAKANA LETTER MO */
+  { 0x04d4, 0x30e4 }, /*                     kana_YA ヤ KATAKANA LETTER YA */
+  { 0x04d5, 0x30e6 }, /*                     kana_YU ユ KATAKANA LETTER YU */
+  { 0x04d6, 0x30e8 }, /*                     kana_YO ヨ KATAKANA LETTER YO */
+  { 0x04d7, 0x30e9 }, /*                     kana_RA ラ KATAKANA LETTER RA */
+  { 0x04d8, 0x30ea }, /*                     kana_RI リ KATAKANA LETTER RI */
+  { 0x04d9, 0x30eb }, /*                     kana_RU ル KATAKANA LETTER RU */
+  { 0x04da, 0x30ec }, /*                     kana_RE レ KATAKANA LETTER RE */
+  { 0x04db, 0x30ed }, /*                     kana_RO ロ KATAKANA LETTER RO */
+  { 0x04dc, 0x30ef }, /*                     kana_WA ワ KATAKANA LETTER WA */
+  { 0x04dd, 0x30f3 }, /*                      kana_N ン KATAKANA LETTER N */
+  { 0x04de, 0x309b }, /*                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
+  { 0x04df, 0x309c }, /*             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+  { 0x05ac, 0x060c }, /*                Arabic_comma ، ARABIC COMMA */
+  { 0x05bb, 0x061b }, /*            Arabic_semicolon ؛ ARABIC SEMICOLON */
+  { 0x05bf, 0x061f }, /*        Arabic_question_mark ؟ ARABIC QUESTION MARK */
+  { 0x05c1, 0x0621 }, /*                Arabic_hamza ء ARABIC LETTER HAMZA */
+  { 0x05c2, 0x0622 }, /*          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
+  { 0x05c3, 0x0623 }, /*          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
+  { 0x05c4, 0x0624 }, /*           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
+  { 0x05c5, 0x0625 }, /*       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
+  { 0x05c6, 0x0626 }, /*           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
+  { 0x05c7, 0x0627 }, /*                 Arabic_alef ا ARABIC LETTER ALEF */
+  { 0x05c8, 0x0628 }, /*                  Arabic_beh ب ARABIC LETTER BEH */
+  { 0x05c9, 0x0629 }, /*           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
+  { 0x05ca, 0x062a }, /*                  Arabic_teh ت ARABIC LETTER TEH */
+  { 0x05cb, 0x062b }, /*                 Arabic_theh ث ARABIC LETTER THEH */
+  { 0x05cc, 0x062c }, /*                 Arabic_jeem ج ARABIC LETTER JEEM */
+  { 0x05cd, 0x062d }, /*                  Arabic_hah ح ARABIC LETTER HAH */
+  { 0x05ce, 0x062e }, /*                 Arabic_khah خ ARABIC LETTER KHAH */
+  { 0x05cf, 0x062f }, /*                  Arabic_dal د ARABIC LETTER DAL */
+  { 0x05d0, 0x0630 }, /*                 Arabic_thal ذ ARABIC LETTER THAL */
+  { 0x05d1, 0x0631 }, /*                   Arabic_ra ر ARABIC LETTER REH */
+  { 0x05d2, 0x0632 }, /*                 Arabic_zain ز ARABIC LETTER ZAIN */
+  { 0x05d3, 0x0633 }, /*                 Arabic_seen س ARABIC LETTER SEEN */
+  { 0x05d4, 0x0634 }, /*                Arabic_sheen ش ARABIC LETTER SHEEN */
+  { 0x05d5, 0x0635 }, /*                  Arabic_sad ص ARABIC LETTER SAD */
+  { 0x05d6, 0x0636 }, /*                  Arabic_dad ض ARABIC LETTER DAD */
+  { 0x05d7, 0x0637 }, /*                  Arabic_tah ط ARABIC LETTER TAH */
+  { 0x05d8, 0x0638 }, /*                  Arabic_zah ظ ARABIC LETTER ZAH */
+  { 0x05d9, 0x0639 }, /*                  Arabic_ain ع ARABIC LETTER AIN */
+  { 0x05da, 0x063a }, /*                Arabic_ghain غ ARABIC LETTER GHAIN */
+  { 0x05e0, 0x0640 }, /*              Arabic_tatweel ـ ARABIC TATWEEL */
+  { 0x05e1, 0x0641 }, /*                  Arabic_feh ف ARABIC LETTER FEH */
+  { 0x05e2, 0x0642 }, /*                  Arabic_qaf ق ARABIC LETTER QAF */
+  { 0x05e3, 0x0643 }, /*                  Arabic_kaf ك ARABIC LETTER KAF */
+  { 0x05e4, 0x0644 }, /*                  Arabic_lam ل ARABIC LETTER LAM */
+  { 0x05e5, 0x0645 }, /*                 Arabic_meem م ARABIC LETTER MEEM */
+  { 0x05e6, 0x0646 }, /*                 Arabic_noon ن ARABIC LETTER NOON */
+  { 0x05e7, 0x0647 }, /*                   Arabic_ha ه ARABIC LETTER HEH */
+  { 0x05e8, 0x0648 }, /*                  Arabic_waw و ARABIC LETTER WAW */
+  { 0x05e9, 0x0649 }, /*          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
+  { 0x05ea, 0x064a }, /*                  Arabic_yeh ي ARABIC LETTER YEH */
+  { 0x05eb, 0x064b }, /*             Arabic_fathatan ً ARABIC FATHATAN */
+  { 0x05ec, 0x064c }, /*             Arabic_dammatan ٌ ARABIC DAMMATAN */
+  { 0x05ed, 0x064d }, /*             Arabic_kasratan ٍ ARABIC KASRATAN */
+  { 0x05ee, 0x064e }, /*                Arabic_fatha َ ARABIC FATHA */
+  { 0x05ef, 0x064f }, /*                Arabic_damma ُ ARABIC DAMMA */
+  { 0x05f0, 0x0650 }, /*                Arabic_kasra ِ ARABIC KASRA */
+  { 0x05f1, 0x0651 }, /*               Arabic_shadda ّ ARABIC SHADDA */
+  { 0x05f2, 0x0652 }, /*                Arabic_sukun ْ ARABIC SUKUN */
+  { 0x06a1, 0x0452 }, /*                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
+  { 0x06a2, 0x0453 }, /*               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
+  { 0x06a3, 0x0451 }, /*                 Cyrillic_io ё CYRILLIC SMALL LETTER IO */
+  { 0x06a4, 0x0454 }, /*                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
+  { 0x06a5, 0x0455 }, /*               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
+  { 0x06a6, 0x0456 }, /*                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06a7, 0x0457 }, /*                Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
+  { 0x06a8, 0x0458 }, /*                 Cyrillic_je ј CYRILLIC SMALL LETTER JE */
+  { 0x06a9, 0x0459 }, /*                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
+  { 0x06aa, 0x045a }, /*                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
+  { 0x06ab, 0x045b }, /*                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
+  { 0x06ac, 0x045c }, /*               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
+  { 0x06ae, 0x045e }, /*         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
+  { 0x06af, 0x045f }, /*               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
+  { 0x06b0, 0x2116 }, /*                  numerosign № NUMERO SIGN */
+  { 0x06b1, 0x0402 }, /*                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
+  { 0x06b2, 0x0403 }, /*               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
+  { 0x06b3, 0x0401 }, /*                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
+  { 0x06b4, 0x0404 }, /*                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+  { 0x06b5, 0x0405 }, /*               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
+  { 0x06b6, 0x0406 }, /*                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06b7, 0x0407 }, /*                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
+  { 0x06b8, 0x0408 }, /*                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
+  { 0x06b9, 0x0409 }, /*                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
+  { 0x06ba, 0x040a }, /*                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
+  { 0x06bb, 0x040b }, /*                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
+  { 0x06bc, 0x040c }, /*               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
+  { 0x06be, 0x040e }, /*         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
+  { 0x06bf, 0x040f }, /*               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
+  { 0x06c0, 0x044e }, /*                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
+  { 0x06c1, 0x0430 }, /*                  Cyrillic_a а CYRILLIC SMALL LETTER A */
+  { 0x06c2, 0x0431 }, /*                 Cyrillic_be б CYRILLIC SMALL LETTER BE */
+  { 0x06c3, 0x0446 }, /*                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
+  { 0x06c4, 0x0434 }, /*                 Cyrillic_de д CYRILLIC SMALL LETTER DE */
+  { 0x06c5, 0x0435 }, /*                 Cyrillic_ie е CYRILLIC SMALL LETTER IE */
+  { 0x06c6, 0x0444 }, /*                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
+  { 0x06c7, 0x0433 }, /*                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
+  { 0x06c8, 0x0445 }, /*                 Cyrillic_ha х CYRILLIC SMALL LETTER HA */
+  { 0x06c9, 0x0438 }, /*                  Cyrillic_i и CYRILLIC SMALL LETTER I */
+  { 0x06ca, 0x0439 }, /*             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
+  { 0x06cb, 0x043a }, /*                 Cyrillic_ka к CYRILLIC SMALL LETTER KA */
+  { 0x06cc, 0x043b }, /*                 Cyrillic_el л CYRILLIC SMALL LETTER EL */
+  { 0x06cd, 0x043c }, /*                 Cyrillic_em м CYRILLIC SMALL LETTER EM */
+  { 0x06ce, 0x043d }, /*                 Cyrillic_en н CYRILLIC SMALL LETTER EN */
+  { 0x06cf, 0x043e }, /*                  Cyrillic_o о CYRILLIC SMALL LETTER O */
+  { 0x06d0, 0x043f }, /*                 Cyrillic_pe п CYRILLIC SMALL LETTER PE */
+  { 0x06d1, 0x044f }, /*                 Cyrillic_ya я CYRILLIC SMALL LETTER YA */
+  { 0x06d2, 0x0440 }, /*                 Cyrillic_er р CYRILLIC SMALL LETTER ER */
+  { 0x06d3, 0x0441 }, /*                 Cyrillic_es с CYRILLIC SMALL LETTER ES */
+  { 0x06d4, 0x0442 }, /*                 Cyrillic_te т CYRILLIC SMALL LETTER TE */
+  { 0x06d5, 0x0443 }, /*                  Cyrillic_u у CYRILLIC SMALL LETTER U */
+  { 0x06d6, 0x0436 }, /*                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
+  { 0x06d7, 0x0432 }, /*                 Cyrillic_ve в CYRILLIC SMALL LETTER VE */
+  { 0x06d8, 0x044c }, /*           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
+  { 0x06d9, 0x044b }, /*               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
+  { 0x06da, 0x0437 }, /*                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
+  { 0x06db, 0x0448 }, /*                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
+  { 0x06dc, 0x044d }, /*                  Cyrillic_e э CYRILLIC SMALL LETTER E */
+  { 0x06dd, 0x0449 }, /*              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
+  { 0x06de, 0x0447 }, /*                Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
+  { 0x06df, 0x044a }, /*           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
+  { 0x06e0, 0x042e }, /*                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
+  { 0x06e1, 0x0410 }, /*                  Cyrillic_A А CYRILLIC CAPITAL LETTER A */
+  { 0x06e2, 0x0411 }, /*                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
+  { 0x06e3, 0x0426 }, /*                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
+  { 0x06e4, 0x0414 }, /*                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
+  { 0x06e5, 0x0415 }, /*                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
+  { 0x06e6, 0x0424 }, /*                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
+  { 0x06e7, 0x0413 }, /*                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
+  { 0x06e8, 0x0425 }, /*                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
+  { 0x06e9, 0x0418 }, /*                  Cyrillic_I И CYRILLIC CAPITAL LETTER I */
+  { 0x06ea, 0x0419 }, /*             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
+  { 0x06eb, 0x041a }, /*                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
+  { 0x06ec, 0x041b }, /*                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
+  { 0x06ed, 0x041c }, /*                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
+  { 0x06ee, 0x041d }, /*                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
+  { 0x06ef, 0x041e }, /*                  Cyrillic_O О CYRILLIC CAPITAL LETTER O */
+  { 0x06f0, 0x041f }, /*                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
+  { 0x06f1, 0x042f }, /*                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
+  { 0x06f2, 0x0420 }, /*                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
+  { 0x06f3, 0x0421 }, /*                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
+  { 0x06f4, 0x0422 }, /*                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
+  { 0x06f5, 0x0423 }, /*                  Cyrillic_U У CYRILLIC CAPITAL LETTER U */
+  { 0x06f6, 0x0416 }, /*                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
+  { 0x06f7, 0x0412 }, /*                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
+  { 0x06f8, 0x042c }, /*           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
+  { 0x06f9, 0x042b }, /*               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
+  { 0x06fa, 0x0417 }, /*                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
+  { 0x06fb, 0x0428 }, /*                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
+  { 0x06fc, 0x042d }, /*                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
+  { 0x06fd, 0x0429 }, /*              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
+  { 0x06fe, 0x0427 }, /*                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
+  { 0x06ff, 0x042a }, /*           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
+  { 0x07a1, 0x0386 }, /*           Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
+  { 0x07a2, 0x0388 }, /*         Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
+  { 0x07a3, 0x0389 }, /*             Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
+  { 0x07a4, 0x038a }, /*            Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
+  { 0x07a5, 0x03aa }, /*         Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+  { 0x07a7, 0x038c }, /*         Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
+  { 0x07a8, 0x038e }, /*         Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
+  { 0x07a9, 0x03ab }, /*       Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07ab, 0x038f }, /*           Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
+  { 0x07ae, 0x0385 }, /*        Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
+  { 0x07af, 0x2015 }, /*              Greek_horizbar ― HORIZONTAL BAR */
+  { 0x07b1, 0x03ac }, /*           Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
+  { 0x07b2, 0x03ad }, /*         Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
+  { 0x07b3, 0x03ae }, /*             Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
+  { 0x07b4, 0x03af }, /*            Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
+  { 0x07b5, 0x03ca }, /*          Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+  { 0x07b6, 0x0390 }, /*    Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+  { 0x07b7, 0x03cc }, /*         Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
+  { 0x07b8, 0x03cd }, /*         Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
+  { 0x07b9, 0x03cb }, /*       Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+  { 0x07bb, 0x03ce }, /*           Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
+  { 0x07c1, 0x0391 }, /*                 Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
+  { 0x07c2, 0x0392 }, /*                  Greek_BETA Β GREEK CAPITAL LETTER BETA */
+  { 0x07c3, 0x0393 }, /*                 Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
+  { 0x07c4, 0x0394 }, /*                 Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
+  { 0x07c5, 0x0395 }, /*               Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
+  { 0x07c6, 0x0396 }, /*                  Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
+  { 0x07c7, 0x0397 }, /*                   Greek_ETA Η GREEK CAPITAL LETTER ETA */
+  { 0x07c8, 0x0398 }, /*                 Greek_THETA Θ GREEK CAPITAL LETTER THETA */
+  { 0x07c9, 0x0399 }, /*                  Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
+  { 0x07ca, 0x039a }, /*                 Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
+  { 0x07cb, 0x039b }, /*                Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
+  { 0x07cc, 0x039c }, /*                    Greek_MU Μ GREEK CAPITAL LETTER MU */
+  { 0x07cd, 0x039d }, /*                    Greek_NU Ν GREEK CAPITAL LETTER NU */
+  { 0x07ce, 0x039e }, /*                    Greek_XI Ξ GREEK CAPITAL LETTER XI */
+  { 0x07cf, 0x039f }, /*               Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
+  { 0x07d0, 0x03a0 }, /*                    Greek_PI Π GREEK CAPITAL LETTER PI */
+  { 0x07d1, 0x03a1 }, /*                   Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
+  { 0x07d2, 0x03a3 }, /*                 Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
+  { 0x07d4, 0x03a4 }, /*                   Greek_TAU Τ GREEK CAPITAL LETTER TAU */
+  { 0x07d5, 0x03a5 }, /*               Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
+  { 0x07d6, 0x03a6 }, /*                   Greek_PHI Φ GREEK CAPITAL LETTER PHI */
+  { 0x07d7, 0x03a7 }, /*                   Greek_CHI Χ GREEK CAPITAL LETTER CHI */
+  { 0x07d8, 0x03a8 }, /*                   Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
+  { 0x07d9, 0x03a9 }, /*                 Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
+  { 0x07e1, 0x03b1 }, /*                 Greek_alpha α GREEK SMALL LETTER ALPHA */
+  { 0x07e2, 0x03b2 }, /*                  Greek_beta β GREEK SMALL LETTER BETA */
+  { 0x07e3, 0x03b3 }, /*                 Greek_gamma γ GREEK SMALL LETTER GAMMA */
+  { 0x07e4, 0x03b4 }, /*                 Greek_delta δ GREEK SMALL LETTER DELTA */
+  { 0x07e5, 0x03b5 }, /*               Greek_epsilon ε GREEK SMALL LETTER EPSILON */
+  { 0x07e6, 0x03b6 }, /*                  Greek_zeta ζ GREEK SMALL LETTER ZETA */
+  { 0x07e7, 0x03b7 }, /*                   Greek_eta η GREEK SMALL LETTER ETA */
+  { 0x07e8, 0x03b8 }, /*                 Greek_theta θ GREEK SMALL LETTER THETA */
+  { 0x07e9, 0x03b9 }, /*                  Greek_iota ι GREEK SMALL LETTER IOTA */
+  { 0x07ea, 0x03ba }, /*                 Greek_kappa κ GREEK SMALL LETTER KAPPA */
+  { 0x07eb, 0x03bb }, /*                Greek_lambda λ GREEK SMALL LETTER LAMDA */
+  { 0x07ec, 0x03bc }, /*                    Greek_mu μ GREEK SMALL LETTER MU */
+  { 0x07ed, 0x03bd }, /*                    Greek_nu ν GREEK SMALL LETTER NU */
+  { 0x07ee, 0x03be }, /*                    Greek_xi ξ GREEK SMALL LETTER XI */
+  { 0x07ef, 0x03bf }, /*               Greek_omicron ο GREEK SMALL LETTER OMICRON */
+  { 0x07f0, 0x03c0 }, /*                    Greek_pi π GREEK SMALL LETTER PI */
+  { 0x07f1, 0x03c1 }, /*                   Greek_rho ρ GREEK SMALL LETTER RHO */
+  { 0x07f2, 0x03c3 }, /*                 Greek_sigma σ GREEK SMALL LETTER SIGMA */
+  { 0x07f3, 0x03c2 }, /*       Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
+  { 0x07f4, 0x03c4 }, /*                   Greek_tau τ GREEK SMALL LETTER TAU */
+  { 0x07f5, 0x03c5 }, /*               Greek_upsilon υ GREEK SMALL LETTER UPSILON */
+  { 0x07f6, 0x03c6 }, /*                   Greek_phi φ GREEK SMALL LETTER PHI */
+  { 0x07f7, 0x03c7 }, /*                   Greek_chi χ GREEK SMALL LETTER CHI */
+  { 0x07f8, 0x03c8 }, /*                   Greek_psi ψ GREEK SMALL LETTER PSI */
+  { 0x07f9, 0x03c9 }, /*                 Greek_omega ω GREEK SMALL LETTER OMEGA */
+/*  0x08a1                               leftradical ? ??? */
+/*  0x08a2                            topleftradical ? ??? */
+/*  0x08a3                            horizconnector ? ??? */
+  { 0x08a4, 0x2320 }, /*                 topintegral ⌠ TOP HALF INTEGRAL */
+  { 0x08a5, 0x2321 }, /*                 botintegral ⌡ BOTTOM HALF INTEGRAL */
+  { 0x08a6, 0x2502 }, /*               vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
+/*  0x08a7                          topleftsqbracket ? ??? */
+/*  0x08a8                          botleftsqbracket ? ??? */
+/*  0x08a9                         toprightsqbracket ? ??? */
+/*  0x08aa                         botrightsqbracket ? ??? */
+/*  0x08ab                             topleftparens ? ??? */
+/*  0x08ac                             botleftparens ? ??? */
+/*  0x08ad                            toprightparens ? ??? */
+/*  0x08ae                            botrightparens ? ??? */
+/*  0x08af                      leftmiddlecurlybrace ? ??? */
+/*  0x08b0                     rightmiddlecurlybrace ? ??? */
+/*  0x08b1                          topleftsummation ? ??? */
+/*  0x08b2                          botleftsummation ? ??? */
+/*  0x08b3                 topvertsummationconnector ? ??? */
+/*  0x08b4                 botvertsummationconnector ? ??? */
+/*  0x08b5                         toprightsummation ? ??? */
+/*  0x08b6                         botrightsummation ? ??? */
+/*  0x08b7                      rightmiddlesummation ? ??? */
+  { 0x08bc, 0x2264 }, /*               lessthanequal ≤ LESS-THAN OR EQUAL TO */
+  { 0x08bd, 0x2260 }, /*                    notequal ≠ NOT EQUAL TO */
+  { 0x08be, 0x2265 }, /*            greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
+  { 0x08bf, 0x222b }, /*                    integral ∫ INTEGRAL */
+  { 0x08c0, 0x2234 }, /*                   therefore ∴ THEREFORE */
+  { 0x08c1, 0x221d }, /*                   variation ∝ PROPORTIONAL TO */
+  { 0x08c2, 0x221e }, /*                    infinity ∞ INFINITY */
+  { 0x08c5, 0x2207 }, /*                       nabla ∇ NABLA */
+  { 0x08c8, 0x2245 }, /*                 approximate ≅ APPROXIMATELY EQUAL TO */
+/*  0x08c9                              similarequal ? ??? */
+  { 0x08cd, 0x21d4 }, /*                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
+  { 0x08ce, 0x21d2 }, /*                     implies ⇒ RIGHTWARDS DOUBLE ARROW */
+  { 0x08cf, 0x2261 }, /*                   identical ≡ IDENTICAL TO */
+  { 0x08d6, 0x221a }, /*                     radical √ SQUARE ROOT */
+  { 0x08da, 0x2282 }, /*                  includedin ⊂ SUBSET OF */
+  { 0x08db, 0x2283 }, /*                    includes ⊃ SUPERSET OF */
+  { 0x08dc, 0x2229 }, /*                intersection ∩ INTERSECTION */
+  { 0x08dd, 0x222a }, /*                       union ∪ UNION */
+  { 0x08de, 0x2227 }, /*                  logicaland ∧ LOGICAL AND */
+  { 0x08df, 0x2228 }, /*                   logicalor ∨ LOGICAL OR */
+  { 0x08ef, 0x2202 }, /*           partialderivative ∂ PARTIAL DIFFERENTIAL */
+  { 0x08f6, 0x0192 }, /*                    function ƒ LATIN SMALL LETTER F WITH HOOK */
+  { 0x08fb, 0x2190 }, /*                   leftarrow ← LEFTWARDS ARROW */
+  { 0x08fc, 0x2191 }, /*                     uparrow ↑ UPWARDS ARROW */
+  { 0x08fd, 0x2192 }, /*                  rightarrow → RIGHTWARDS ARROW */
+  { 0x08fe, 0x2193 }, /*                   downarrow ↓ DOWNWARDS ARROW */
+  { 0x09df, 0x2422 }, /*                       blank ␢ BLANK SYMBOL */
+  { 0x09e0, 0x25c6 }, /*                soliddiamond ◆ BLACK DIAMOND */
+  { 0x09e1, 0x2592 }, /*                checkerboard ▒ MEDIUM SHADE */
+  { 0x09e2, 0x2409 }, /*                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
+  { 0x09e3, 0x240c }, /*                          ff ␌ SYMBOL FOR FORM FEED */
+  { 0x09e4, 0x240d }, /*                          cr ␍ SYMBOL FOR CARRIAGE RETURN */
+  { 0x09e5, 0x240a }, /*                          lf ␊ SYMBOL FOR LINE FEED */
+  { 0x09e8, 0x2424 }, /*                          nl ␤ SYMBOL FOR NEWLINE */
+  { 0x09e9, 0x240b }, /*                          vt ␋ SYMBOL FOR VERTICAL TABULATION */
+  { 0x09ea, 0x2518 }, /*              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
+  { 0x09eb, 0x2510 }, /*               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
+  { 0x09ec, 0x250c }, /*                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+  { 0x09ed, 0x2514 }, /*               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
+  { 0x09ee, 0x253c }, /*               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+/*  0x09ef                            horizlinescan1 ? ??? */
+/*  0x09f0                            horizlinescan3 ? ??? */
+  { 0x09f1, 0x2500 }, /*              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
+/*  0x09f2                            horizlinescan7 ? ??? */
+/*  0x09f3                            horizlinescan9 ? ??? */
+  { 0x09f4, 0x251c }, /*                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+  { 0x09f5, 0x2524 }, /*                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+  { 0x09f6, 0x2534 }, /*                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+  { 0x09f7, 0x252c }, /*                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+  { 0x09f8, 0x2502 }, /*                     vertbar │ BOX DRAWINGS LIGHT VERTICAL */
+  { 0x0aa1, 0x2003 }, /*                     emspace   EM SPACE */
+  { 0x0aa2, 0x2002 }, /*                     enspace   EN SPACE */
+  { 0x0aa3, 0x2004 }, /*                    em3space   THREE-PER-EM SPACE */
+  { 0x0aa4, 0x2005 }, /*                    em4space   FOUR-PER-EM SPACE */
+  { 0x0aa5, 0x2007 }, /*                  digitspace   FIGURE SPACE */
+  { 0x0aa6, 0x2008 }, /*                  punctspace   PUNCTUATION SPACE */
+  { 0x0aa7, 0x2009 }, /*                   thinspace   THIN SPACE */
+  { 0x0aa8, 0x200a }, /*                   hairspace   HAIR SPACE */
+  { 0x0aa9, 0x2014 }, /*                      emdash — EM DASH */
+  { 0x0aaa, 0x2013 }, /*                      endash – EN DASH */
+/*  0x0aac                               signifblank ? ??? */
+  { 0x0aae, 0x2026 }, /*                    ellipsis … HORIZONTAL ELLIPSIS */
+/*  0x0aaf                           doubbaselinedot ? ??? */
+  { 0x0ab0, 0x2153 }, /*                    onethird ⅓ VULGAR FRACTION ONE THIRD */
+  { 0x0ab1, 0x2154 }, /*                   twothirds ⅔ VULGAR FRACTION TWO THIRDS */
+  { 0x0ab2, 0x2155 }, /*                    onefifth ⅕ VULGAR FRACTION ONE FIFTH */
+  { 0x0ab3, 0x2156 }, /*                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
+  { 0x0ab4, 0x2157 }, /*                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
+  { 0x0ab5, 0x2158 }, /*                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
+  { 0x0ab6, 0x2159 }, /*                    onesixth ⅙ VULGAR FRACTION ONE SIXTH */
+  { 0x0ab7, 0x215a }, /*                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
+  { 0x0ab8, 0x2105 }, /*                      careof ℅ CARE OF */
+  { 0x0abb, 0x2012 }, /*                     figdash ‒ FIGURE DASH */
+  { 0x0abc, 0x2329 }, /*            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
+  { 0x0abd, 0x002e }, /*                decimalpoint . FULL STOP */
+  { 0x0abe, 0x232a }, /*           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
+/*  0x0abf                                    marker ? ??? */
+  { 0x0ac3, 0x215b }, /*                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
+  { 0x0ac4, 0x215c }, /*                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
+  { 0x0ac5, 0x215d }, /*                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
+  { 0x0ac6, 0x215e }, /*                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
+  { 0x0ac9, 0x2122 }, /*                   trademark ™ TRADE MARK SIGN */
+  { 0x0aca, 0x2613 }, /*               signaturemark ☓ SALTIRE */
+/*  0x0acb                         trademarkincircle ? ??? */
+  { 0x0acc, 0x25c1 }, /*            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
+  { 0x0acd, 0x25b7 }, /*           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
+  { 0x0ace, 0x25cb }, /*                emopencircle ○ WHITE CIRCLE */
+  { 0x0acf, 0x25a1 }, /*             emopenrectangle □ WHITE SQUARE */
+  { 0x0ad0, 0x2018 }, /*         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
+  { 0x0ad1, 0x2019 }, /*        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
+  { 0x0ad2, 0x201c }, /*         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
+  { 0x0ad3, 0x201d }, /*        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
+  { 0x0ad4, 0x211e }, /*                prescription ℞ PRESCRIPTION TAKE */
+  { 0x0ad6, 0x2032 }, /*                     minutes ′ PRIME */
+  { 0x0ad7, 0x2033 }, /*                     seconds ″ DOUBLE PRIME */
+  { 0x0ad9, 0x271d }, /*                  latincross ✝ LATIN CROSS */
+/*  0x0ada                                  hexagram ? ??? */
+  { 0x0adb, 0x25ac }, /*            filledrectbullet ▬ BLACK RECTANGLE */
+  { 0x0adc, 0x25c0 }, /*         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
+  { 0x0add, 0x25b6 }, /*        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
+  { 0x0ade, 0x25cf }, /*              emfilledcircle ● BLACK CIRCLE */
+  { 0x0adf, 0x25a0 }, /*                emfilledrect ■ BLACK SQUARE */
+  { 0x0ae0, 0x25e6 }, /*            enopencircbullet ◦ WHITE BULLET */
+  { 0x0ae1, 0x25ab }, /*          enopensquarebullet ▫ WHITE SMALL SQUARE */
+  { 0x0ae2, 0x25ad }, /*              openrectbullet ▭ WHITE RECTANGLE */
+  { 0x0ae3, 0x25b3 }, /*             opentribulletup △ WHITE UP-POINTING TRIANGLE */
+  { 0x0ae4, 0x25bd }, /*           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
+  { 0x0ae5, 0x2606 }, /*                    openstar ☆ WHITE STAR */
+  { 0x0ae6, 0x2022 }, /*          enfilledcircbullet • BULLET */
+  { 0x0ae7, 0x25aa }, /*            enfilledsqbullet ▪ BLACK SMALL SQUARE */
+  { 0x0ae8, 0x25b2 }, /*           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
+  { 0x0ae9, 0x25bc }, /*         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
+  { 0x0aea, 0x261c }, /*                 leftpointer ☜ WHITE LEFT POINTING INDEX */
+  { 0x0aeb, 0x261e }, /*                rightpointer ☞ WHITE RIGHT POINTING INDEX */
+  { 0x0aec, 0x2663 }, /*                        club ♣ BLACK CLUB SUIT */
+  { 0x0aed, 0x2666 }, /*                     diamond ♦ BLACK DIAMOND SUIT */
+  { 0x0aee, 0x2665 }, /*                       heart ♥ BLACK HEART SUIT */
+  { 0x0af0, 0x2720 }, /*                maltesecross ✠ MALTESE CROSS */
+  { 0x0af1, 0x2020 }, /*                      dagger † DAGGER */
+  { 0x0af2, 0x2021 }, /*                doubledagger ‡ DOUBLE DAGGER */
+  { 0x0af3, 0x2713 }, /*                   checkmark ✓ CHECK MARK */
+  { 0x0af4, 0x2717 }, /*                 ballotcross ✗ BALLOT X */
+  { 0x0af5, 0x266f }, /*                musicalsharp ♯ MUSIC SHARP SIGN */
+  { 0x0af6, 0x266d }, /*                 musicalflat ♭ MUSIC FLAT SIGN */
+  { 0x0af7, 0x2642 }, /*                  malesymbol ♂ MALE SIGN */
+  { 0x0af8, 0x2640 }, /*                femalesymbol ♀ FEMALE SIGN */
+  { 0x0af9, 0x260e }, /*                   telephone ☎ BLACK TELEPHONE */
+  { 0x0afa, 0x2315 }, /*           telephonerecorder ⌕ TELEPHONE RECORDER */
+  { 0x0afb, 0x2117 }, /*         phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
+  { 0x0afc, 0x2038 }, /*                       caret ‸ CARET */
+  { 0x0afd, 0x201a }, /*          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
+  { 0x0afe, 0x201e }, /*          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
+/*  0x0aff                                    cursor ? ??? */
+  { 0x0ba3, 0x003c }, /*                   leftcaret < LESS-THAN SIGN */
+  { 0x0ba6, 0x003e }, /*                  rightcaret > GREATER-THAN SIGN */
+  { 0x0ba8, 0x2228 }, /*                   downcaret ∨ LOGICAL OR */
+  { 0x0ba9, 0x2227 }, /*                     upcaret ∧ LOGICAL AND */
+  { 0x0bc0, 0x00af }, /*                     overbar ¯ MACRON */
+  { 0x0bc2, 0x22a4 }, /*                    downtack ⊤ DOWN TACK */
+  { 0x0bc3, 0x2229 }, /*                      upshoe ∩ INTERSECTION */
+  { 0x0bc4, 0x230a }, /*                   downstile ⌊ LEFT FLOOR */
+  { 0x0bc6, 0x005f }, /*                    underbar _ LOW LINE */
+  { 0x0bca, 0x2218 }, /*                         jot ∘ RING OPERATOR */
+  { 0x0bcc, 0x2395 }, /*                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */
+  { 0x0bce, 0x22a5 }, /*                      uptack ⊥ UP TACK */
+  { 0x0bcf, 0x25cb }, /*                      circle ○ WHITE CIRCLE */
+  { 0x0bd3, 0x2308 }, /*                     upstile ⌈ LEFT CEILING */
+  { 0x0bd6, 0x222a }, /*                    downshoe ∪ UNION */
+  { 0x0bd8, 0x2283 }, /*                   rightshoe ⊃ SUPERSET OF */
+  { 0x0bda, 0x2282 }, /*                    leftshoe ⊂ SUBSET OF */
+  { 0x0bdc, 0x22a3 }, /*                    lefttack ⊣ LEFT TACK */
+  { 0x0bfc, 0x22a2 }, /*                   righttack ⊢ RIGHT TACK */
+  { 0x0cdf, 0x2017 }, /*        hebrew_doublelowline ‗ DOUBLE LOW LINE */
+  { 0x0ce0, 0x05d0 }, /*                hebrew_aleph א HEBREW LETTER ALEF */
+  { 0x0ce1, 0x05d1 }, /*                  hebrew_bet ב HEBREW LETTER BET */
+  { 0x0ce2, 0x05d2 }, /*                hebrew_gimel ג HEBREW LETTER GIMEL */
+  { 0x0ce3, 0x05d3 }, /*                hebrew_dalet ד HEBREW LETTER DALET */
+  { 0x0ce4, 0x05d4 }, /*                   hebrew_he ה HEBREW LETTER HE */
+  { 0x0ce5, 0x05d5 }, /*                  hebrew_waw ו HEBREW LETTER VAV */
+  { 0x0ce6, 0x05d6 }, /*                 hebrew_zain ז HEBREW LETTER ZAYIN */
+  { 0x0ce7, 0x05d7 }, /*                 hebrew_chet ח HEBREW LETTER HET */
+  { 0x0ce8, 0x05d8 }, /*                  hebrew_tet ט HEBREW LETTER TET */
+  { 0x0ce9, 0x05d9 }, /*                  hebrew_yod י HEBREW LETTER YOD */
+  { 0x0cea, 0x05da }, /*            hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
+  { 0x0ceb, 0x05db }, /*                 hebrew_kaph כ HEBREW LETTER KAF */
+  { 0x0cec, 0x05dc }, /*                hebrew_lamed ל HEBREW LETTER LAMED */
+  { 0x0ced, 0x05dd }, /*             hebrew_finalmem ם HEBREW LETTER FINAL MEM */
+  { 0x0cee, 0x05de }, /*                  hebrew_mem מ HEBREW LETTER MEM */
+  { 0x0cef, 0x05df }, /*             hebrew_finalnun ן HEBREW LETTER FINAL NUN */
+  { 0x0cf0, 0x05e0 }, /*                  hebrew_nun נ HEBREW LETTER NUN */
+  { 0x0cf1, 0x05e1 }, /*               hebrew_samech ס HEBREW LETTER SAMEKH */
+  { 0x0cf2, 0x05e2 }, /*                 hebrew_ayin ע HEBREW LETTER AYIN */
+  { 0x0cf3, 0x05e3 }, /*              hebrew_finalpe ף HEBREW LETTER FINAL PE */
+  { 0x0cf4, 0x05e4 }, /*                   hebrew_pe פ HEBREW LETTER PE */
+  { 0x0cf5, 0x05e5 }, /*            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
+  { 0x0cf6, 0x05e6 }, /*                 hebrew_zade צ HEBREW LETTER TSADI */
+  { 0x0cf7, 0x05e7 }, /*                 hebrew_qoph ק HEBREW LETTER QOF */
+  { 0x0cf8, 0x05e8 }, /*                 hebrew_resh ר HEBREW LETTER RESH */
+  { 0x0cf9, 0x05e9 }, /*                 hebrew_shin ש HEBREW LETTER SHIN */
+  { 0x0cfa, 0x05ea }, /*                  hebrew_taw ת HEBREW LETTER TAV */
+  { 0x0da1, 0x0e01 }, /*                  Thai_kokai ก THAI CHARACTER KO KAI */
+  { 0x0da2, 0x0e02 }, /*                Thai_khokhai ข THAI CHARACTER KHO KHAI */
+  { 0x0da3, 0x0e03 }, /*               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
+  { 0x0da4, 0x0e04 }, /*               Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
+  { 0x0da5, 0x0e05 }, /*                Thai_khokhon ฅ THAI CHARACTER KHO KHON */
+  { 0x0da6, 0x0e06 }, /*             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
+  { 0x0da7, 0x0e07 }, /*                 Thai_ngongu ง THAI CHARACTER NGO NGU */
+  { 0x0da8, 0x0e08 }, /*                Thai_chochan จ THAI CHARACTER CHO CHAN */
+  { 0x0da9, 0x0e09 }, /*               Thai_choching ฉ THAI CHARACTER CHO CHING */
+  { 0x0daa, 0x0e0a }, /*               Thai_chochang ช THAI CHARACTER CHO CHANG */
+  { 0x0dab, 0x0e0b }, /*                   Thai_soso ซ THAI CHARACTER SO SO */
+  { 0x0dac, 0x0e0c }, /*                Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
+  { 0x0dad, 0x0e0d }, /*                 Thai_yoying ญ THAI CHARACTER YO YING */
+  { 0x0dae, 0x0e0e }, /*                Thai_dochada ฎ THAI CHARACTER DO CHADA */
+  { 0x0daf, 0x0e0f }, /*                Thai_topatak ฏ THAI CHARACTER TO PATAK */
+  { 0x0db0, 0x0e10 }, /*                Thai_thothan ฐ THAI CHARACTER THO THAN */
+  { 0x0db1, 0x0e11 }, /*          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
+  { 0x0db2, 0x0e12 }, /*             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
+  { 0x0db3, 0x0e13 }, /*                  Thai_nonen ณ THAI CHARACTER NO NEN */
+  { 0x0db4, 0x0e14 }, /*                  Thai_dodek ด THAI CHARACTER DO DEK */
+  { 0x0db5, 0x0e15 }, /*                  Thai_totao ต THAI CHARACTER TO TAO */
+  { 0x0db6, 0x0e16 }, /*               Thai_thothung ถ THAI CHARACTER THO THUNG */
+  { 0x0db7, 0x0e17 }, /*              Thai_thothahan ท THAI CHARACTER THO THAHAN */
+  { 0x0db8, 0x0e18 }, /*               Thai_thothong ธ THAI CHARACTER THO THONG */
+  { 0x0db9, 0x0e19 }, /*                   Thai_nonu น THAI CHARACTER NO NU */
+  { 0x0dba, 0x0e1a }, /*               Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
+  { 0x0dbb, 0x0e1b }, /*                  Thai_popla ป THAI CHARACTER PO PLA */
+  { 0x0dbc, 0x0e1c }, /*               Thai_phophung ผ THAI CHARACTER PHO PHUNG */
+  { 0x0dbd, 0x0e1d }, /*                   Thai_fofa ฝ THAI CHARACTER FO FA */
+  { 0x0dbe, 0x0e1e }, /*                Thai_phophan พ THAI CHARACTER PHO PHAN */
+  { 0x0dbf, 0x0e1f }, /*                  Thai_fofan ฟ THAI CHARACTER FO FAN */
+  { 0x0dc0, 0x0e20 }, /*             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
+  { 0x0dc1, 0x0e21 }, /*                   Thai_moma ม THAI CHARACTER MO MA */
+  { 0x0dc2, 0x0e22 }, /*                  Thai_yoyak ย THAI CHARACTER YO YAK */
+  { 0x0dc3, 0x0e23 }, /*                  Thai_rorua ร THAI CHARACTER RO RUA */
+  { 0x0dc4, 0x0e24 }, /*                     Thai_ru ฤ THAI CHARACTER RU */
+  { 0x0dc5, 0x0e25 }, /*                 Thai_loling ล THAI CHARACTER LO LING */
+  { 0x0dc6, 0x0e26 }, /*                     Thai_lu ฦ THAI CHARACTER LU */
+  { 0x0dc7, 0x0e27 }, /*                 Thai_wowaen ว THAI CHARACTER WO WAEN */
+  { 0x0dc8, 0x0e28 }, /*                 Thai_sosala ศ THAI CHARACTER SO SALA */
+  { 0x0dc9, 0x0e29 }, /*                 Thai_sorusi ษ THAI CHARACTER SO RUSI */
+  { 0x0dca, 0x0e2a }, /*                  Thai_sosua ส THAI CHARACTER SO SUA */
+  { 0x0dcb, 0x0e2b }, /*                  Thai_hohip ห THAI CHARACTER HO HIP */
+  { 0x0dcc, 0x0e2c }, /*                Thai_lochula ฬ THAI CHARACTER LO CHULA */
+  { 0x0dcd, 0x0e2d }, /*                   Thai_oang อ THAI CHARACTER O ANG */
+  { 0x0dce, 0x0e2e }, /*               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
+  { 0x0dcf, 0x0e2f }, /*              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
+  { 0x0dd0, 0x0e30 }, /*                  Thai_saraa ะ THAI CHARACTER SARA A */
+  { 0x0dd1, 0x0e31 }, /*             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
+  { 0x0dd2, 0x0e32 }, /*                 Thai_saraaa า THAI CHARACTER SARA AA */
+  { 0x0dd3, 0x0e33 }, /*                 Thai_saraam ำ THAI CHARACTER SARA AM */
+  { 0x0dd4, 0x0e34 }, /*                  Thai_sarai ิ THAI CHARACTER SARA I */
+  { 0x0dd5, 0x0e35 }, /*                 Thai_saraii ี THAI CHARACTER SARA II */
+  { 0x0dd6, 0x0e36 }, /*                 Thai_saraue ึ THAI CHARACTER SARA UE */
+  { 0x0dd7, 0x0e37 }, /*                Thai_sarauee ื THAI CHARACTER SARA UEE */
+  { 0x0dd8, 0x0e38 }, /*                  Thai_sarau ุ THAI CHARACTER SARA U */
+  { 0x0dd9, 0x0e39 }, /*                 Thai_sarauu ู THAI CHARACTER SARA UU */
+  { 0x0dda, 0x0e3a }, /*                Thai_phinthu ฺ THAI CHARACTER PHINTHU */
+  { 0x0dde, 0x0e3e }, /*      Thai_maihanakat_maitho ฾ ??? */
+  { 0x0ddf, 0x0e3f }, /*                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
+  { 0x0de0, 0x0e40 }, /*                  Thai_sarae เ THAI CHARACTER SARA E */
+  { 0x0de1, 0x0e41 }, /*                 Thai_saraae แ THAI CHARACTER SARA AE */
+  { 0x0de2, 0x0e42 }, /*                  Thai_sarao โ THAI CHARACTER SARA O */
+  { 0x0de3, 0x0e43 }, /*          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
+  { 0x0de4, 0x0e44 }, /*         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
+  { 0x0de5, 0x0e45 }, /*            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
+  { 0x0de6, 0x0e46 }, /*               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
+  { 0x0de7, 0x0e47 }, /*              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
+  { 0x0de8, 0x0e48 }, /*                  Thai_maiek ่ THAI CHARACTER MAI EK */
+  { 0x0de9, 0x0e49 }, /*                 Thai_maitho ้ THAI CHARACTER MAI THO */
+  { 0x0dea, 0x0e4a }, /*                 Thai_maitri ๊ THAI CHARACTER MAI TRI */
+  { 0x0deb, 0x0e4b }, /*            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
+  { 0x0dec, 0x0e4c }, /*            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
+  { 0x0ded, 0x0e4d }, /*               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
+  { 0x0df0, 0x0e50 }, /*                 Thai_leksun ๐ THAI DIGIT ZERO */
+  { 0x0df1, 0x0e51 }, /*                Thai_leknung ๑ THAI DIGIT ONE */
+  { 0x0df2, 0x0e52 }, /*                Thai_leksong ๒ THAI DIGIT TWO */
+  { 0x0df3, 0x0e53 }, /*                 Thai_leksam ๓ THAI DIGIT THREE */
+  { 0x0df4, 0x0e54 }, /*                  Thai_leksi ๔ THAI DIGIT FOUR */
+  { 0x0df5, 0x0e55 }, /*                  Thai_lekha ๕ THAI DIGIT FIVE */
+  { 0x0df6, 0x0e56 }, /*                 Thai_lekhok ๖ THAI DIGIT SIX */
+  { 0x0df7, 0x0e57 }, /*                Thai_lekchet ๗ THAI DIGIT SEVEN */
+  { 0x0df8, 0x0e58 }, /*                Thai_lekpaet ๘ THAI DIGIT EIGHT */
+  { 0x0df9, 0x0e59 }, /*                 Thai_lekkao ๙ THAI DIGIT NINE */
+  { 0x0ea1, 0x3131 }, /*               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
+  { 0x0ea2, 0x3132 }, /*          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
+  { 0x0ea3, 0x3133 }, /*           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
+  { 0x0ea4, 0x3134 }, /*                Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
+  { 0x0ea5, 0x3135 }, /*           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
+  { 0x0ea6, 0x3136 }, /*           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
+  { 0x0ea7, 0x3137 }, /*               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
+  { 0x0ea8, 0x3138 }, /*          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
+  { 0x0ea9, 0x3139 }, /*                Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
+  { 0x0eaa, 0x313a }, /*          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
+  { 0x0eab, 0x313b }, /*           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
+  { 0x0eac, 0x313c }, /*           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
+  { 0x0ead, 0x313d }, /*            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
+  { 0x0eae, 0x313e }, /*           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
+  { 0x0eaf, 0x313f }, /*          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
+  { 0x0eb0, 0x3140 }, /*           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
+  { 0x0eb1, 0x3141 }, /*                Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
+  { 0x0eb2, 0x3142 }, /*                Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
+  { 0x0eb3, 0x3143 }, /*           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
+  { 0x0eb4, 0x3144 }, /*            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
+  { 0x0eb5, 0x3145 }, /*                 Hangul_Sios ㅅ HANGUL LETTER SIOS */
+  { 0x0eb6, 0x3146 }, /*            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
+  { 0x0eb7, 0x3147 }, /*                Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
+  { 0x0eb8, 0x3148 }, /*                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
+  { 0x0eb9, 0x3149 }, /*           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
+  { 0x0eba, 0x314a }, /*                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
+  { 0x0ebb, 0x314b }, /*               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
+  { 0x0ebc, 0x314c }, /*                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
+  { 0x0ebd, 0x314d }, /*               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
+  { 0x0ebe, 0x314e }, /*                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
+  { 0x0ebf, 0x314f }, /*                    Hangul_A ㅏ HANGUL LETTER A */
+  { 0x0ec0, 0x3150 }, /*                   Hangul_AE ㅐ HANGUL LETTER AE */
+  { 0x0ec1, 0x3151 }, /*                   Hangul_YA ㅑ HANGUL LETTER YA */
+  { 0x0ec2, 0x3152 }, /*                  Hangul_YAE ㅒ HANGUL LETTER YAE */
+  { 0x0ec3, 0x3153 }, /*                   Hangul_EO ㅓ HANGUL LETTER EO */
+  { 0x0ec4, 0x3154 }, /*                    Hangul_E ㅔ HANGUL LETTER E */
+  { 0x0ec5, 0x3155 }, /*                  Hangul_YEO ㅕ HANGUL LETTER YEO */
+  { 0x0ec6, 0x3156 }, /*                   Hangul_YE ㅖ HANGUL LETTER YE */
+  { 0x0ec7, 0x3157 }, /*                    Hangul_O ㅗ HANGUL LETTER O */
+  { 0x0ec8, 0x3158 }, /*                   Hangul_WA ㅘ HANGUL LETTER WA */
+  { 0x0ec9, 0x3159 }, /*                  Hangul_WAE ㅙ HANGUL LETTER WAE */
+  { 0x0eca, 0x315a }, /*                   Hangul_OE ㅚ HANGUL LETTER OE */
+  { 0x0ecb, 0x315b }, /*                   Hangul_YO ㅛ HANGUL LETTER YO */
+  { 0x0ecc, 0x315c }, /*                    Hangul_U ㅜ HANGUL LETTER U */
+  { 0x0ecd, 0x315d }, /*                  Hangul_WEO ㅝ HANGUL LETTER WEO */
+  { 0x0ece, 0x315e }, /*                   Hangul_WE ㅞ HANGUL LETTER WE */
+  { 0x0ecf, 0x315f }, /*                   Hangul_WI ㅟ HANGUL LETTER WI */
+  { 0x0ed0, 0x3160 }, /*                   Hangul_YU ㅠ HANGUL LETTER YU */
+  { 0x0ed1, 0x3161 }, /*                   Hangul_EU ㅡ HANGUL LETTER EU */
+  { 0x0ed2, 0x3162 }, /*                   Hangul_YI ㅢ HANGUL LETTER YI */
+  { 0x0ed3, 0x3163 }, /*                    Hangul_I ㅣ HANGUL LETTER I */
+  { 0x0ed4, 0x11a8 }, /*             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
+  { 0x0ed5, 0x11a9 }, /*        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
+  { 0x0ed6, 0x11aa }, /*         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
+  { 0x0ed7, 0x11ab }, /*              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
+  { 0x0ed8, 0x11ac }, /*         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
+  { 0x0ed9, 0x11ad }, /*         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
+  { 0x0eda, 0x11ae }, /*             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
+  { 0x0edb, 0x11af }, /*              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
+  { 0x0edc, 0x11b0 }, /*        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
+  { 0x0edd, 0x11b1 }, /*         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
+  { 0x0ede, 0x11b2 }, /*         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
+  { 0x0edf, 0x11b3 }, /*          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
+  { 0x0ee0, 0x11b4 }, /*         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
+  { 0x0ee1, 0x11b5 }, /*        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
+  { 0x0ee2, 0x11b6 }, /*         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
+  { 0x0ee3, 0x11b7 }, /*              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
+  { 0x0ee4, 0x11b8 }, /*              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
+  { 0x0ee5, 0x11b9 }, /*          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
+  { 0x0ee6, 0x11ba }, /*               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
+  { 0x0ee7, 0x11bb }, /*          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
+  { 0x0ee8, 0x11bc }, /*              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
+  { 0x0ee9, 0x11bd }, /*              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
+  { 0x0eea, 0x11be }, /*              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
+  { 0x0eeb, 0x11bf }, /*             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
+  { 0x0eec, 0x11c0 }, /*              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
+  { 0x0eed, 0x11c1 }, /*             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
+  { 0x0eee, 0x11c2 }, /*              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
+  { 0x0eef, 0x316d }, /*     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
+  { 0x0ef0, 0x3171 }, /*    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
+  { 0x0ef1, 0x3178 }, /*    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
+  { 0x0ef2, 0x317f }, /*              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
+/*  0x0ef3                  Hangul_KkogjiDalrinIeung ? ??? */
+  { 0x0ef4, 0x3184 }, /*   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
+  { 0x0ef5, 0x3186 }, /*          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
+  { 0x0ef6, 0x318d }, /*                Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
+  { 0x0ef7, 0x318e }, /*               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
+  { 0x0ef8, 0x11eb }, /*            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
+/*  0x0ef9                Hangul_J_KkogjiDalrinIeung ? ??? */
+  { 0x0efa, 0x11f9 }, /*        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
+  { 0x0eff, 0x20a9 }, /*                  Korean_Won ₩ WON SIGN */
+  { 0x13bc, 0x0152 }, /*                          OE Œ LATIN CAPITAL LIGATURE OE */
+  { 0x13bd, 0x0153 }, /*                          oe œ LATIN SMALL LIGATURE OE */
+  { 0x13be, 0x0178 }, /*                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
+  { 0x20a0, 0x20a0 }, /*                     EcuSign ₠ EURO-CURRENCY SIGN */
+  { 0x20a1, 0x20a1 }, /*                   ColonSign ₡ COLON SIGN */
+  { 0x20a2, 0x20a2 }, /*                CruzeiroSign ₢ CRUZEIRO SIGN */
+  { 0x20a3, 0x20a3 }, /*                  FFrancSign ₣ FRENCH FRANC SIGN */
+  { 0x20a4, 0x20a4 }, /*                    LiraSign ₤ LIRA SIGN */
+  { 0x20a5, 0x20a5 }, /*                    MillSign ₥ MILL SIGN */
+  { 0x20a6, 0x20a6 }, /*                   NairaSign ₦ NAIRA SIGN */
+  { 0x20a7, 0x20a7 }, /*                  PesetaSign ₧ PESETA SIGN */
+  { 0x20a8, 0x20a8 }, /*                   RupeeSign ₨ RUPEE SIGN */
+  { 0x20a9, 0x20a9 }, /*                     WonSign ₩ WON SIGN */
+  { 0x20aa, 0x20aa }, /*               NewSheqelSign ₪ NEW SHEQEL SIGN */
+  { 0x20ab, 0x20ab }, /*                    DongSign ₫ DONG SIGN */
+  { 0x20ac, 0x20ac }, /*                    EuroSign € EURO SIGN */
+};
+
+static guint
+keyval_to_unicode (guint keysym)
+{
+  int min = 0;
+  int max = sizeof(k2utab) / sizeof(k2utab[0]) - 1;
+  int mid;
+
+  /* First check for Latin-1 characters (1:1 mapping) */
+  if ((keysym >= 0x0020 && keysym <= 0x007e) ||
+      (keysym >= 0x00a0 && keysym <= 0x00ff))
+    return keysym;
+
+  /* Also check for directly encoded 24-bit UCS characters */
+  if ((keysym & 0xff000000) == 0x01000000)
+    return keysym & 0x00ffffff;
+
+  /* binary search in table */
+  while (max >= min) {
+    mid = (min + max) / 2;
+    if (k2utab[mid].keysym < keysym)
+      min = mid + 1;
+    else if (k2utab[mid].keysym > keysym)
+      max = mid - 1;
+    else {
+      /* found it */
+      return k2utab[mid].ucs;
+    }
+  }
+  
+  /* No matching Unicode value found */
+  return -1;
+}
+
+struct u2k {
+  unsigned short keysym;
+  unsigned short ucs;
+} u2ktab[] = {
+  { 0x0abd, 0x002e }, /*                decimalpoint . FULL STOP */
+  { 0x0ba3, 0x003c }, /*                   leftcaret < LESS-THAN SIGN */
+  { 0x0ba6, 0x003e }, /*                  rightcaret > GREATER-THAN SIGN */
+  { 0x0bc6, 0x005f }, /*                    underbar _ LOW LINE */
+  { 0x0bc0, 0x00af }, /*                     overbar ¯ MACRON */
+  { 0x03c0, 0x0100 }, /*                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
+  { 0x03e0, 0x0101 }, /*                     amacron ā LATIN SMALL LETTER A WITH MACRON */
+  { 0x01c3, 0x0102 }, /*                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
+  { 0x01e3, 0x0103 }, /*                      abreve ă LATIN SMALL LETTER A WITH BREVE */
+  { 0x01a1, 0x0104 }, /*                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
+  { 0x01b1, 0x0105 }, /*                     aogonek ą LATIN SMALL LETTER A WITH OGONEK */
+  { 0x01c6, 0x0106 }, /*                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
+  { 0x01e6, 0x0107 }, /*                      cacute ć LATIN SMALL LETTER C WITH ACUTE */
+  { 0x02c6, 0x0108 }, /*                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
+  { 0x02e6, 0x0109 }, /*                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
+  { 0x02c5, 0x010a }, /*                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
+  { 0x02e5, 0x010b }, /*                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
+  { 0x01c8, 0x010c }, /*                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
+  { 0x01e8, 0x010d }, /*                      ccaron č LATIN SMALL LETTER C WITH CARON */
+  { 0x01cf, 0x010e }, /*                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
+  { 0x01ef, 0x010f }, /*                      dcaron ď LATIN SMALL LETTER D WITH CARON */
+  { 0x01d0, 0x0110 }, /*                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
+  { 0x01f0, 0x0111 }, /*                     dstroke đ LATIN SMALL LETTER D WITH STROKE */
+  { 0x03aa, 0x0112 }, /*                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
+  { 0x03ba, 0x0113 }, /*                     emacron ē LATIN SMALL LETTER E WITH MACRON */
+  { 0x03cc, 0x0116 }, /*                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
+  { 0x03ec, 0x0117 }, /*                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
+  { 0x01ca, 0x0118 }, /*                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
+  { 0x01ea, 0x0119 }, /*                     eogonek ę LATIN SMALL LETTER E WITH OGONEK */
+  { 0x01cc, 0x011a }, /*                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
+  { 0x01ec, 0x011b }, /*                      ecaron ě LATIN SMALL LETTER E WITH CARON */
+  { 0x02d8, 0x011c }, /*                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
+  { 0x02f8, 0x011d }, /*                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
+  { 0x02ab, 0x011e }, /*                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
+  { 0x02bb, 0x011f }, /*                      gbreve ğ LATIN SMALL LETTER G WITH BREVE */
+  { 0x02d5, 0x0120 }, /*                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
+  { 0x02f5, 0x0121 }, /*                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
+  { 0x03ab, 0x0122 }, /*                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
+  { 0x03bb, 0x0123 }, /*                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
+  { 0x02a6, 0x0124 }, /*                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
+  { 0x02b6, 0x0125 }, /*                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
+  { 0x02a1, 0x0126 }, /*                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
+  { 0x02b1, 0x0127 }, /*                     hstroke ħ LATIN SMALL LETTER H WITH STROKE */
+  { 0x03a5, 0x0128 }, /*                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
+  { 0x03b5, 0x0129 }, /*                      itilde ĩ LATIN SMALL LETTER I WITH TILDE */
+  { 0x03cf, 0x012a }, /*                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
+  { 0x03ef, 0x012b }, /*                     imacron ī LATIN SMALL LETTER I WITH MACRON */
+  { 0x03c7, 0x012e }, /*                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
+  { 0x03e7, 0x012f }, /*                     iogonek į LATIN SMALL LETTER I WITH OGONEK */
+  { 0x02a9, 0x0130 }, /*                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
+  { 0x02b9, 0x0131 }, /*                    idotless ı LATIN SMALL LETTER DOTLESS I */
+  { 0x02ac, 0x0134 }, /*                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
+  { 0x02bc, 0x0135 }, /*                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
+  { 0x03d3, 0x0136 }, /*                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
+  { 0x03f3, 0x0137 }, /*                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
+  { 0x03a2, 0x0138 }, /*                         kra ĸ LATIN SMALL LETTER KRA */
+  { 0x01c5, 0x0139 }, /*                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
+  { 0x01e5, 0x013a }, /*                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
+  { 0x03a6, 0x013b }, /*                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
+  { 0x03b6, 0x013c }, /*                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
+  { 0x01a5, 0x013d }, /*                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
+  { 0x01b5, 0x013e }, /*                      lcaron ľ LATIN SMALL LETTER L WITH CARON */
+  { 0x01a3, 0x0141 }, /*                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
+  { 0x01b3, 0x0142 }, /*                     lstroke ł LATIN SMALL LETTER L WITH STROKE */
+  { 0x01d1, 0x0143 }, /*                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
+  { 0x01f1, 0x0144 }, /*                      nacute ń LATIN SMALL LETTER N WITH ACUTE */
+  { 0x03d1, 0x0145 }, /*                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
+  { 0x03f1, 0x0146 }, /*                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
+  { 0x01d2, 0x0147 }, /*                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
+  { 0x01f2, 0x0148 }, /*                      ncaron ň LATIN SMALL LETTER N WITH CARON */
+  { 0x03bd, 0x014a }, /*                         ENG Ŋ LATIN CAPITAL LETTER ENG */
+  { 0x03bf, 0x014b }, /*                         eng ŋ LATIN SMALL LETTER ENG */
+  { 0x03d2, 0x014c }, /*                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
+  { 0x03f2, 0x014d }, /*                     omacron ō LATIN SMALL LETTER O WITH MACRON */
+  { 0x01d5, 0x0150 }, /*                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
+  { 0x01f5, 0x0151 }, /*                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
+  { 0x13bc, 0x0152 }, /*                          OE Œ LATIN CAPITAL LIGATURE OE */
+  { 0x13bd, 0x0153 }, /*                          oe œ LATIN SMALL LIGATURE OE */
+  { 0x01c0, 0x0154 }, /*                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
+  { 0x01e0, 0x0155 }, /*                      racute ŕ LATIN SMALL LETTER R WITH ACUTE */
+  { 0x03a3, 0x0156 }, /*                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
+  { 0x03b3, 0x0157 }, /*                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
+  { 0x01d8, 0x0158 }, /*                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
+  { 0x01f8, 0x0159 }, /*                      rcaron ř LATIN SMALL LETTER R WITH CARON */
+  { 0x01a6, 0x015a }, /*                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
+  { 0x01b6, 0x015b }, /*                      sacute ś LATIN SMALL LETTER S WITH ACUTE */
+  { 0x02de, 0x015c }, /*                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
+  { 0x02fe, 0x015d }, /*                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
+  { 0x01aa, 0x015e }, /*                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
+  { 0x01ba, 0x015f }, /*                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
+  { 0x01a9, 0x0160 }, /*                      Scaron Š LATIN CAPITAL LETTER S WITH CARON */
+  { 0x01b9, 0x0161 }, /*                      scaron š LATIN SMALL LETTER S WITH CARON */
+  { 0x01de, 0x0162 }, /*                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
+  { 0x01fe, 0x0163 }, /*                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
+  { 0x01ab, 0x0164 }, /*                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
+  { 0x01bb, 0x0165 }, /*                      tcaron ť LATIN SMALL LETTER T WITH CARON */
+  { 0x03ac, 0x0166 }, /*                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
+  { 0x03bc, 0x0167 }, /*                      tslash ŧ LATIN SMALL LETTER T WITH STROKE */
+  { 0x03dd, 0x0168 }, /*                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
+  { 0x03fd, 0x0169 }, /*                      utilde ũ LATIN SMALL LETTER U WITH TILDE */
+  { 0x03de, 0x016a }, /*                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
+  { 0x03fe, 0x016b }, /*                     umacron ū LATIN SMALL LETTER U WITH MACRON */
+  { 0x02dd, 0x016c }, /*                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
+  { 0x02fd, 0x016d }, /*                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
+  { 0x01d9, 0x016e }, /*                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
+  { 0x01f9, 0x016f }, /*                       uring ů LATIN SMALL LETTER U WITH RING ABOVE */
+  { 0x01db, 0x0170 }, /*                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
+  { 0x01fb, 0x0171 }, /*                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
+  { 0x03d9, 0x0172 }, /*                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
+  { 0x03f9, 0x0173 }, /*                     uogonek ų LATIN SMALL LETTER U WITH OGONEK */
+  { 0x13be, 0x0178 }, /*                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
+  { 0x01ac, 0x0179 }, /*                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
+  { 0x01bc, 0x017a }, /*                      zacute ź LATIN SMALL LETTER Z WITH ACUTE */
+  { 0x01af, 0x017b }, /*                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
+  { 0x01bf, 0x017c }, /*                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
+  { 0x01ae, 0x017d }, /*                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
+  { 0x01be, 0x017e }, /*                      zcaron ž LATIN SMALL LETTER Z WITH CARON */
+  { 0x08f6, 0x0192 }, /*                    function ƒ LATIN SMALL LETTER F WITH HOOK */
+  { 0x01b7, 0x02c7 }, /*                       caron ˇ CARON */
+  { 0x01a2, 0x02d8 }, /*                       breve ˘ BREVE */
+  { 0x01ff, 0x02d9 }, /*                    abovedot ˙ DOT ABOVE */
+  { 0x01b2, 0x02db }, /*                      ogonek ˛ OGONEK */
+  { 0x01bd, 0x02dd }, /*                 doubleacute ˝ DOUBLE ACUTE ACCENT */
+  { 0x07ae, 0x0385 }, /*        Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
+  { 0x07a1, 0x0386 }, /*           Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
+  { 0x07a2, 0x0388 }, /*         Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
+  { 0x07a3, 0x0389 }, /*             Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
+  { 0x07a4, 0x038a }, /*            Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
+  { 0x07a7, 0x038c }, /*         Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
+  { 0x07a8, 0x038e }, /*         Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
+  { 0x07ab, 0x038f }, /*           Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
+  { 0x07b6, 0x0390 }, /*    Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
+  { 0x07c1, 0x0391 }, /*                 Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
+  { 0x07c2, 0x0392 }, /*                  Greek_BETA Β GREEK CAPITAL LETTER BETA */
+  { 0x07c3, 0x0393 }, /*                 Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
+  { 0x07c4, 0x0394 }, /*                 Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
+  { 0x07c5, 0x0395 }, /*               Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
+  { 0x07c6, 0x0396 }, /*                  Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
+  { 0x07c7, 0x0397 }, /*                   Greek_ETA Η GREEK CAPITAL LETTER ETA */
+  { 0x07c8, 0x0398 }, /*                 Greek_THETA Θ GREEK CAPITAL LETTER THETA */
+  { 0x07c9, 0x0399 }, /*                  Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
+  { 0x07ca, 0x039a }, /*                 Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
+  { 0x07cb, 0x039b }, /*                Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
+  { 0x07cc, 0x039c }, /*                    Greek_MU Μ GREEK CAPITAL LETTER MU */
+  { 0x07cd, 0x039d }, /*                    Greek_NU Ν GREEK CAPITAL LETTER NU */
+  { 0x07ce, 0x039e }, /*                    Greek_XI Ξ GREEK CAPITAL LETTER XI */
+  { 0x07cf, 0x039f }, /*               Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
+  { 0x07d0, 0x03a0 }, /*                    Greek_PI Π GREEK CAPITAL LETTER PI */
+  { 0x07d1, 0x03a1 }, /*                   Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
+  { 0x07d2, 0x03a3 }, /*                 Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
+  { 0x07d4, 0x03a4 }, /*                   Greek_TAU Τ GREEK CAPITAL LETTER TAU */
+  { 0x07d5, 0x03a5 }, /*               Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
+  { 0x07d6, 0x03a6 }, /*                   Greek_PHI Φ GREEK CAPITAL LETTER PHI */
+  { 0x07d7, 0x03a7 }, /*                   Greek_CHI Χ GREEK CAPITAL LETTER CHI */
+  { 0x07d8, 0x03a8 }, /*                   Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
+  { 0x07d9, 0x03a9 }, /*                 Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
+  { 0x07a5, 0x03aa }, /*         Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
+  { 0x07a9, 0x03ab }, /*       Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07b1, 0x03ac }, /*           Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
+  { 0x07b2, 0x03ad }, /*         Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
+  { 0x07b3, 0x03ae }, /*             Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
+  { 0x07b4, 0x03af }, /*            Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
+  { 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
+  { 0x07e1, 0x03b1 }, /*                 Greek_alpha α GREEK SMALL LETTER ALPHA */
+  { 0x07e2, 0x03b2 }, /*                  Greek_beta β GREEK SMALL LETTER BETA */
+  { 0x07e3, 0x03b3 }, /*                 Greek_gamma γ GREEK SMALL LETTER GAMMA */
+  { 0x07e4, 0x03b4 }, /*                 Greek_delta δ GREEK SMALL LETTER DELTA */
+  { 0x07e5, 0x03b5 }, /*               Greek_epsilon ε GREEK SMALL LETTER EPSILON */
+  { 0x07e6, 0x03b6 }, /*                  Greek_zeta ζ GREEK SMALL LETTER ZETA */
+  { 0x07e7, 0x03b7 }, /*                   Greek_eta η GREEK SMALL LETTER ETA */
+  { 0x07e8, 0x03b8 }, /*                 Greek_theta θ GREEK SMALL LETTER THETA */
+  { 0x07e9, 0x03b9 }, /*                  Greek_iota ι GREEK SMALL LETTER IOTA */
+  { 0x07ea, 0x03ba }, /*                 Greek_kappa κ GREEK SMALL LETTER KAPPA */
+  { 0x07eb, 0x03bb }, /*                Greek_lambda λ GREEK SMALL LETTER LAMDA */
+  { 0x07ec, 0x03bc }, /*                    Greek_mu μ GREEK SMALL LETTER MU */
+  { 0x07ed, 0x03bd }, /*                    Greek_nu ν GREEK SMALL LETTER NU */
+  { 0x07ee, 0x03be }, /*                    Greek_xi ξ GREEK SMALL LETTER XI */
+  { 0x07ef, 0x03bf }, /*               Greek_omicron ο GREEK SMALL LETTER OMICRON */
+  { 0x07f0, 0x03c0 }, /*                    Greek_pi π GREEK SMALL LETTER PI */
+  { 0x07f1, 0x03c1 }, /*                   Greek_rho ρ GREEK SMALL LETTER RHO */
+  { 0x07f3, 0x03c2 }, /*       Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
+  { 0x07f2, 0x03c3 }, /*                 Greek_sigma σ GREEK SMALL LETTER SIGMA */
+  { 0x07f4, 0x03c4 }, /*                   Greek_tau τ GREEK SMALL LETTER TAU */
+  { 0x07f5, 0x03c5 }, /*               Greek_upsilon υ GREEK SMALL LETTER UPSILON */
+  { 0x07f6, 0x03c6 }, /*                   Greek_phi φ GREEK SMALL LETTER PHI */
+  { 0x07f7, 0x03c7 }, /*                   Greek_chi χ GREEK SMALL LETTER CHI */
+  { 0x07f8, 0x03c8 }, /*                   Greek_psi ψ GREEK SMALL LETTER PSI */
+  { 0x07f9, 0x03c9 }, /*                 Greek_omega ω GREEK SMALL LETTER OMEGA */
+  { 0x07b5, 0x03ca }, /*          Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
+  { 0x07b9, 0x03cb }, /*       Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
+  { 0x07b7, 0x03cc }, /*         Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
+  { 0x07b8, 0x03cd }, /*         Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
+  { 0x07bb, 0x03ce }, /*           Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
+  { 0x06b3, 0x0401 }, /*                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
+  { 0x06b1, 0x0402 }, /*                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
+  { 0x06b2, 0x0403 }, /*               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
+  { 0x06b4, 0x0404 }, /*                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
+  { 0x06b5, 0x0405 }, /*               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
+  { 0x06b6, 0x0406 }, /*                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06b7, 0x0407 }, /*                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
+  { 0x06b8, 0x0408 }, /*                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
+  { 0x06b9, 0x0409 }, /*                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
+  { 0x06ba, 0x040a }, /*                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
+  { 0x06bb, 0x040b }, /*                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
+  { 0x06bc, 0x040c }, /*               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
+  { 0x06be, 0x040e }, /*         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
+  { 0x06bf, 0x040f }, /*               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
+  { 0x06e1, 0x0410 }, /*                  Cyrillic_A А CYRILLIC CAPITAL LETTER A */
+  { 0x06e2, 0x0411 }, /*                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
+  { 0x06f7, 0x0412 }, /*                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
+  { 0x06e7, 0x0413 }, /*                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
+  { 0x06e4, 0x0414 }, /*                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
+  { 0x06e5, 0x0415 }, /*                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
+  { 0x06f6, 0x0416 }, /*                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
+  { 0x06fa, 0x0417 }, /*                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
+  { 0x06e9, 0x0418 }, /*                  Cyrillic_I И CYRILLIC CAPITAL LETTER I */
+  { 0x06ea, 0x0419 }, /*             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
+  { 0x06eb, 0x041a }, /*                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
+  { 0x06ec, 0x041b }, /*                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
+  { 0x06ed, 0x041c }, /*                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
+  { 0x06ee, 0x041d }, /*                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
+  { 0x06ef, 0x041e }, /*                  Cyrillic_O О CYRILLIC CAPITAL LETTER O */
+  { 0x06f0, 0x041f }, /*                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
+  { 0x06f2, 0x0420 }, /*                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
+  { 0x06f3, 0x0421 }, /*                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
+  { 0x06f4, 0x0422 }, /*                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
+  { 0x06f5, 0x0423 }, /*                  Cyrillic_U У CYRILLIC CAPITAL LETTER U */
+  { 0x06e6, 0x0424 }, /*                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
+  { 0x06e8, 0x0425 }, /*                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
+  { 0x06e3, 0x0426 }, /*                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
+  { 0x06fe, 0x0427 }, /*                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
+  { 0x06fb, 0x0428 }, /*                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
+  { 0x06fd, 0x0429 }, /*              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
+  { 0x06ff, 0x042a }, /*           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
+  { 0x06f9, 0x042b }, /*               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
+  { 0x06f8, 0x042c }, /*           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
+  { 0x06fc, 0x042d }, /*                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
+  { 0x06e0, 0x042e }, /*                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
+  { 0x06f1, 0x042f }, /*                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
+  { 0x06c1, 0x0430 }, /*                  Cyrillic_a а CYRILLIC SMALL LETTER A */
+  { 0x06c2, 0x0431 }, /*                 Cyrillic_be б CYRILLIC SMALL LETTER BE */
+  { 0x06d7, 0x0432 }, /*                 Cyrillic_ve в CYRILLIC SMALL LETTER VE */
+  { 0x06c7, 0x0433 }, /*                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
+  { 0x06c4, 0x0434 }, /*                 Cyrillic_de д CYRILLIC SMALL LETTER DE */
+  { 0x06c5, 0x0435 }, /*                 Cyrillic_ie е CYRILLIC SMALL LETTER IE */
+  { 0x06d6, 0x0436 }, /*                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
+  { 0x06da, 0x0437 }, /*                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
+  { 0x06c9, 0x0438 }, /*                  Cyrillic_i и CYRILLIC SMALL LETTER I */
+  { 0x06ca, 0x0439 }, /*             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
+  { 0x06cb, 0x043a }, /*                 Cyrillic_ka к CYRILLIC SMALL LETTER KA */
+  { 0x06cc, 0x043b }, /*                 Cyrillic_el л CYRILLIC SMALL LETTER EL */
+  { 0x06cd, 0x043c }, /*                 Cyrillic_em м CYRILLIC SMALL LETTER EM */
+  { 0x06ce, 0x043d }, /*                 Cyrillic_en н CYRILLIC SMALL LETTER EN */
+  { 0x06cf, 0x043e }, /*                  Cyrillic_o о CYRILLIC SMALL LETTER O */
+  { 0x06d0, 0x043f }, /*                 Cyrillic_pe п CYRILLIC SMALL LETTER PE */
+  { 0x06d2, 0x0440 }, /*                 Cyrillic_er р CYRILLIC SMALL LETTER ER */
+  { 0x06d3, 0x0441 }, /*                 Cyrillic_es с CYRILLIC SMALL LETTER ES */
+  { 0x06d4, 0x0442 }, /*                 Cyrillic_te т CYRILLIC SMALL LETTER TE */
+  { 0x06d5, 0x0443 }, /*                  Cyrillic_u у CYRILLIC SMALL LETTER U */
+  { 0x06c6, 0x0444 }, /*                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
+  { 0x06c8, 0x0445 }, /*                 Cyrillic_ha х CYRILLIC SMALL LETTER HA */
+  { 0x06c3, 0x0446 }, /*                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
+  { 0x06de, 0x0447 }, /*                Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
+  { 0x06db, 0x0448 }, /*                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
+  { 0x06dd, 0x0449 }, /*              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
+  { 0x06df, 0x044a }, /*           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
+  { 0x06d9, 0x044b }, /*               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
+  { 0x06d8, 0x044c }, /*           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
+  { 0x06dc, 0x044d }, /*                  Cyrillic_e э CYRILLIC SMALL LETTER E */
+  { 0x06c0, 0x044e }, /*                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
+  { 0x06d1, 0x044f }, /*                 Cyrillic_ya я CYRILLIC SMALL LETTER YA */
+  { 0x06a3, 0x0451 }, /*                 Cyrillic_io ё CYRILLIC SMALL LETTER IO */
+  { 0x06a1, 0x0452 }, /*                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
+  { 0x06a2, 0x0453 }, /*               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
+  { 0x06a4, 0x0454 }, /*                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
+  { 0x06a5, 0x0455 }, /*               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
+  { 0x06a6, 0x0456 }, /*                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
+  { 0x06a7, 0x0457 }, /*                Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
+  { 0x06a8, 0x0458 }, /*                 Cyrillic_je ј CYRILLIC SMALL LETTER JE */
+  { 0x06a9, 0x0459 }, /*                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
+  { 0x06aa, 0x045a }, /*                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
+  { 0x06ab, 0x045b }, /*                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
+  { 0x06ac, 0x045c }, /*               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
+  { 0x06ae, 0x045e }, /*         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
+  { 0x06af, 0x045f }, /*               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
+  { 0x0ce0, 0x05d0 }, /*                hebrew_aleph א HEBREW LETTER ALEF */
+  { 0x0ce1, 0x05d1 }, /*                  hebrew_bet ב HEBREW LETTER BET */
+  { 0x0ce2, 0x05d2 }, /*                hebrew_gimel ג HEBREW LETTER GIMEL */
+  { 0x0ce3, 0x05d3 }, /*                hebrew_dalet ד HEBREW LETTER DALET */
+  { 0x0ce4, 0x05d4 }, /*                   hebrew_he ה HEBREW LETTER HE */
+  { 0x0ce5, 0x05d5 }, /*                  hebrew_waw ו HEBREW LETTER VAV */
+  { 0x0ce6, 0x05d6 }, /*                 hebrew_zain ז HEBREW LETTER ZAYIN */
+  { 0x0ce7, 0x05d7 }, /*                 hebrew_chet ח HEBREW LETTER HET */
+  { 0x0ce8, 0x05d8 }, /*                  hebrew_tet ט HEBREW LETTER TET */
+  { 0x0ce9, 0x05d9 }, /*                  hebrew_yod י HEBREW LETTER YOD */
+  { 0x0cea, 0x05da }, /*            hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
+  { 0x0ceb, 0x05db }, /*                 hebrew_kaph כ HEBREW LETTER KAF */
+  { 0x0cec, 0x05dc }, /*                hebrew_lamed ל HEBREW LETTER LAMED */
+  { 0x0ced, 0x05dd }, /*             hebrew_finalmem ם HEBREW LETTER FINAL MEM */
+  { 0x0cee, 0x05de }, /*                  hebrew_mem מ HEBREW LETTER MEM */
+  { 0x0cef, 0x05df }, /*             hebrew_finalnun ן HEBREW LETTER FINAL NUN */
+  { 0x0cf0, 0x05e0 }, /*                  hebrew_nun נ HEBREW LETTER NUN */
+  { 0x0cf1, 0x05e1 }, /*               hebrew_samech ס HEBREW LETTER SAMEKH */
+  { 0x0cf2, 0x05e2 }, /*                 hebrew_ayin ע HEBREW LETTER AYIN */
+  { 0x0cf3, 0x05e3 }, /*              hebrew_finalpe ף HEBREW LETTER FINAL PE */
+  { 0x0cf4, 0x05e4 }, /*                   hebrew_pe פ HEBREW LETTER PE */
+  { 0x0cf5, 0x05e5 }, /*            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
+  { 0x0cf6, 0x05e6 }, /*                 hebrew_zade צ HEBREW LETTER TSADI */
+  { 0x0cf7, 0x05e7 }, /*                 hebrew_qoph ק HEBREW LETTER QOF */
+  { 0x0cf8, 0x05e8 }, /*                 hebrew_resh ר HEBREW LETTER RESH */
+  { 0x0cf9, 0x05e9 }, /*                 hebrew_shin ש HEBREW LETTER SHIN */
+  { 0x0cfa, 0x05ea }, /*                  hebrew_taw ת HEBREW LETTER TAV */
+  { 0x05ac, 0x060c }, /*                Arabic_comma ، ARABIC COMMA */
+  { 0x05bb, 0x061b }, /*            Arabic_semicolon ؛ ARABIC SEMICOLON */
+  { 0x05bf, 0x061f }, /*        Arabic_question_mark ؟ ARABIC QUESTION MARK */
+  { 0x05c1, 0x0621 }, /*                Arabic_hamza ء ARABIC LETTER HAMZA */
+  { 0x05c2, 0x0622 }, /*          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
+  { 0x05c3, 0x0623 }, /*          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
+  { 0x05c4, 0x0624 }, /*           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
+  { 0x05c5, 0x0625 }, /*       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
+  { 0x05c6, 0x0626 }, /*           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
+  { 0x05c7, 0x0627 }, /*                 Arabic_alef ا ARABIC LETTER ALEF */
+  { 0x05c8, 0x0628 }, /*                  Arabic_beh ب ARABIC LETTER BEH */
+  { 0x05c9, 0x0629 }, /*           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
+  { 0x05ca, 0x062a }, /*                  Arabic_teh ت ARABIC LETTER TEH */
+  { 0x05cb, 0x062b }, /*                 Arabic_theh ث ARABIC LETTER THEH */
+  { 0x05cc, 0x062c }, /*                 Arabic_jeem ج ARABIC LETTER JEEM */
+  { 0x05cd, 0x062d }, /*                  Arabic_hah ح ARABIC LETTER HAH */
+  { 0x05ce, 0x062e }, /*                 Arabic_khah خ ARABIC LETTER KHAH */
+  { 0x05cf, 0x062f }, /*                  Arabic_dal د ARABIC LETTER DAL */
+  { 0x05d0, 0x0630 }, /*                 Arabic_thal ذ ARABIC LETTER THAL */
+  { 0x05d1, 0x0631 }, /*                   Arabic_ra ر ARABIC LETTER REH */
+  { 0x05d2, 0x0632 }, /*                 Arabic_zain ز ARABIC LETTER ZAIN */
+  { 0x05d3, 0x0633 }, /*                 Arabic_seen س ARABIC LETTER SEEN */
+  { 0x05d4, 0x0634 }, /*                Arabic_sheen ش ARABIC LETTER SHEEN */
+  { 0x05d5, 0x0635 }, /*                  Arabic_sad ص ARABIC LETTER SAD */
+  { 0x05d6, 0x0636 }, /*                  Arabic_dad ض ARABIC LETTER DAD */
+  { 0x05d7, 0x0637 }, /*                  Arabic_tah ط ARABIC LETTER TAH */
+  { 0x05d8, 0x0638 }, /*                  Arabic_zah ظ ARABIC LETTER ZAH */
+  { 0x05d9, 0x0639 }, /*                  Arabic_ain ع ARABIC LETTER AIN */
+  { 0x05da, 0x063a }, /*                Arabic_ghain غ ARABIC LETTER GHAIN */
+  { 0x05e0, 0x0640 }, /*              Arabic_tatweel ـ ARABIC TATWEEL */
+  { 0x05e1, 0x0641 }, /*                  Arabic_feh ف ARABIC LETTER FEH */
+  { 0x05e2, 0x0642 }, /*                  Arabic_qaf ق ARABIC LETTER QAF */
+  { 0x05e3, 0x0643 }, /*                  Arabic_kaf ك ARABIC LETTER KAF */
+  { 0x05e4, 0x0644 }, /*                  Arabic_lam ل ARABIC LETTER LAM */
+  { 0x05e5, 0x0645 }, /*                 Arabic_meem م ARABIC LETTER MEEM */
+  { 0x05e6, 0x0646 }, /*                 Arabic_noon ن ARABIC LETTER NOON */
+  { 0x05e7, 0x0647 }, /*                   Arabic_ha ه ARABIC LETTER HEH */
+  { 0x05e8, 0x0648 }, /*                  Arabic_waw و ARABIC LETTER WAW */
+  { 0x05e9, 0x0649 }, /*          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
+  { 0x05ea, 0x064a }, /*                  Arabic_yeh ي ARABIC LETTER YEH */
+  { 0x05eb, 0x064b }, /*             Arabic_fathatan ً ARABIC FATHATAN */
+  { 0x05ec, 0x064c }, /*             Arabic_dammatan ٌ ARABIC DAMMATAN */
+  { 0x05ed, 0x064d }, /*             Arabic_kasratan ٍ ARABIC KASRATAN */
+  { 0x05ee, 0x064e }, /*                Arabic_fatha َ ARABIC FATHA */
+  { 0x05ef, 0x064f }, /*                Arabic_damma ُ ARABIC DAMMA */
+  { 0x05f0, 0x0650 }, /*                Arabic_kasra ِ ARABIC KASRA */
+  { 0x05f1, 0x0651 }, /*               Arabic_shadda ّ ARABIC SHADDA */
+  { 0x05f2, 0x0652 }, /*                Arabic_sukun ْ ARABIC SUKUN */
+  { 0x0da1, 0x0e01 }, /*                  Thai_kokai ก THAI CHARACTER KO KAI */
+  { 0x0da2, 0x0e02 }, /*                Thai_khokhai ข THAI CHARACTER KHO KHAI */
+  { 0x0da3, 0x0e03 }, /*               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
+  { 0x0da4, 0x0e04 }, /*               Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
+  { 0x0da5, 0x0e05 }, /*                Thai_khokhon ฅ THAI CHARACTER KHO KHON */
+  { 0x0da6, 0x0e06 }, /*             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
+  { 0x0da7, 0x0e07 }, /*                 Thai_ngongu ง THAI CHARACTER NGO NGU */
+  { 0x0da8, 0x0e08 }, /*                Thai_chochan จ THAI CHARACTER CHO CHAN */
+  { 0x0da9, 0x0e09 }, /*               Thai_choching ฉ THAI CHARACTER CHO CHING */
+  { 0x0daa, 0x0e0a }, /*               Thai_chochang ช THAI CHARACTER CHO CHANG */
+  { 0x0dab, 0x0e0b }, /*                   Thai_soso ซ THAI CHARACTER SO SO */
+  { 0x0dac, 0x0e0c }, /*                Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
+  { 0x0dad, 0x0e0d }, /*                 Thai_yoying ญ THAI CHARACTER YO YING */
+  { 0x0dae, 0x0e0e }, /*                Thai_dochada ฎ THAI CHARACTER DO CHADA */
+  { 0x0daf, 0x0e0f }, /*                Thai_topatak ฏ THAI CHARACTER TO PATAK */
+  { 0x0db0, 0x0e10 }, /*                Thai_thothan ฐ THAI CHARACTER THO THAN */
+  { 0x0db1, 0x0e11 }, /*          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
+  { 0x0db2, 0x0e12 }, /*             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
+  { 0x0db3, 0x0e13 }, /*                  Thai_nonen ณ THAI CHARACTER NO NEN */
+  { 0x0db4, 0x0e14 }, /*                  Thai_dodek ด THAI CHARACTER DO DEK */
+  { 0x0db5, 0x0e15 }, /*                  Thai_totao ต THAI CHARACTER TO TAO */
+  { 0x0db6, 0x0e16 }, /*               Thai_thothung ถ THAI CHARACTER THO THUNG */
+  { 0x0db7, 0x0e17 }, /*              Thai_thothahan ท THAI CHARACTER THO THAHAN */
+  { 0x0db8, 0x0e18 }, /*               Thai_thothong ธ THAI CHARACTER THO THONG */
+  { 0x0db9, 0x0e19 }, /*                   Thai_nonu น THAI CHARACTER NO NU */
+  { 0x0dba, 0x0e1a }, /*               Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
+  { 0x0dbb, 0x0e1b }, /*                  Thai_popla ป THAI CHARACTER PO PLA */
+  { 0x0dbc, 0x0e1c }, /*               Thai_phophung ผ THAI CHARACTER PHO PHUNG */
+  { 0x0dbd, 0x0e1d }, /*                   Thai_fofa ฝ THAI CHARACTER FO FA */
+  { 0x0dbe, 0x0e1e }, /*                Thai_phophan พ THAI CHARACTER PHO PHAN */
+  { 0x0dbf, 0x0e1f }, /*                  Thai_fofan ฟ THAI CHARACTER FO FAN */
+  { 0x0dc0, 0x0e20 }, /*             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
+  { 0x0dc1, 0x0e21 }, /*                   Thai_moma ม THAI CHARACTER MO MA */
+  { 0x0dc2, 0x0e22 }, /*                  Thai_yoyak ย THAI CHARACTER YO YAK */
+  { 0x0dc3, 0x0e23 }, /*                  Thai_rorua ร THAI CHARACTER RO RUA */
+  { 0x0dc4, 0x0e24 }, /*                     Thai_ru ฤ THAI CHARACTER RU */
+  { 0x0dc5, 0x0e25 }, /*                 Thai_loling ล THAI CHARACTER LO LING */
+  { 0x0dc6, 0x0e26 }, /*                     Thai_lu ฦ THAI CHARACTER LU */
+  { 0x0dc7, 0x0e27 }, /*                 Thai_wowaen ว THAI CHARACTER WO WAEN */
+  { 0x0dc8, 0x0e28 }, /*                 Thai_sosala ศ THAI CHARACTER SO SALA */
+  { 0x0dc9, 0x0e29 }, /*                 Thai_sorusi ษ THAI CHARACTER SO RUSI */
+  { 0x0dca, 0x0e2a }, /*                  Thai_sosua ส THAI CHARACTER SO SUA */
+  { 0x0dcb, 0x0e2b }, /*                  Thai_hohip ห THAI CHARACTER HO HIP */
+  { 0x0dcc, 0x0e2c }, /*                Thai_lochula ฬ THAI CHARACTER LO CHULA */
+  { 0x0dcd, 0x0e2d }, /*                   Thai_oang อ THAI CHARACTER O ANG */
+  { 0x0dce, 0x0e2e }, /*               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
+  { 0x0dcf, 0x0e2f }, /*              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
+  { 0x0dd0, 0x0e30 }, /*                  Thai_saraa ะ THAI CHARACTER SARA A */
+  { 0x0dd1, 0x0e31 }, /*             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
+  { 0x0dd2, 0x0e32 }, /*                 Thai_saraaa า THAI CHARACTER SARA AA */
+  { 0x0dd3, 0x0e33 }, /*                 Thai_saraam ำ THAI CHARACTER SARA AM */
+  { 0x0dd4, 0x0e34 }, /*                  Thai_sarai ิ THAI CHARACTER SARA I */
+  { 0x0dd5, 0x0e35 }, /*                 Thai_saraii ี THAI CHARACTER SARA II */
+  { 0x0dd6, 0x0e36 }, /*                 Thai_saraue ึ THAI CHARACTER SARA UE */
+  { 0x0dd7, 0x0e37 }, /*                Thai_sarauee ื THAI CHARACTER SARA UEE */
+  { 0x0dd8, 0x0e38 }, /*                  Thai_sarau ุ THAI CHARACTER SARA U */
+  { 0x0dd9, 0x0e39 }, /*                 Thai_sarauu ู THAI CHARACTER SARA UU */
+  { 0x0dda, 0x0e3a }, /*                Thai_phinthu ฺ THAI CHARACTER PHINTHU */
+  { 0x0ddf, 0x0e3f }, /*                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
+  { 0x0de0, 0x0e40 }, /*                  Thai_sarae เ THAI CHARACTER SARA E */
+  { 0x0de1, 0x0e41 }, /*                 Thai_saraae แ THAI CHARACTER SARA AE */
+  { 0x0de2, 0x0e42 }, /*                  Thai_sarao โ THAI CHARACTER SARA O */
+  { 0x0de3, 0x0e43 }, /*          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
+  { 0x0de4, 0x0e44 }, /*         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
+  { 0x0de5, 0x0e45 }, /*            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
+  { 0x0de6, 0x0e46 }, /*               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
+  { 0x0de7, 0x0e47 }, /*              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
+  { 0x0de8, 0x0e48 }, /*                  Thai_maiek ่ THAI CHARACTER MAI EK */
+  { 0x0de9, 0x0e49 }, /*                 Thai_maitho ้ THAI CHARACTER MAI THO */
+  { 0x0dea, 0x0e4a }, /*                 Thai_maitri ๊ THAI CHARACTER MAI TRI */
+  { 0x0deb, 0x0e4b }, /*            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
+  { 0x0dec, 0x0e4c }, /*            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
+  { 0x0ded, 0x0e4d }, /*               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
+  { 0x0df0, 0x0e50 }, /*                 Thai_leksun ๐ THAI DIGIT ZERO */
+  { 0x0df1, 0x0e51 }, /*                Thai_leknung ๑ THAI DIGIT ONE */
+  { 0x0df2, 0x0e52 }, /*                Thai_leksong ๒ THAI DIGIT TWO */
+  { 0x0df3, 0x0e53 }, /*                 Thai_leksam ๓ THAI DIGIT THREE */
+  { 0x0df4, 0x0e54 }, /*                  Thai_leksi ๔ THAI DIGIT FOUR */
+  { 0x0df5, 0x0e55 }, /*                  Thai_lekha ๕ THAI DIGIT FIVE */
+  { 0x0df6, 0x0e56 }, /*                 Thai_lekhok ๖ THAI DIGIT SIX */
+  { 0x0df7, 0x0e57 }, /*                Thai_lekchet ๗ THAI DIGIT SEVEN */
+  { 0x0df8, 0x0e58 }, /*                Thai_lekpaet ๘ THAI DIGIT EIGHT */
+  { 0x0df9, 0x0e59 }, /*                 Thai_lekkao ๙ THAI DIGIT NINE */
+  { 0x0ed4, 0x11a8 }, /*             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
+  { 0x0ed5, 0x11a9 }, /*        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
+  { 0x0ed6, 0x11aa }, /*         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
+  { 0x0ed7, 0x11ab }, /*              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
+  { 0x0ed8, 0x11ac }, /*         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
+  { 0x0ed9, 0x11ad }, /*         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
+  { 0x0eda, 0x11ae }, /*             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
+  { 0x0edb, 0x11af }, /*              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
+  { 0x0edc, 0x11b0 }, /*        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
+  { 0x0edd, 0x11b1 }, /*         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
+  { 0x0ede, 0x11b2 }, /*         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
+  { 0x0edf, 0x11b3 }, /*          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
+  { 0x0ee0, 0x11b4 }, /*         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
+  { 0x0ee1, 0x11b5 }, /*        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
+  { 0x0ee2, 0x11b6 }, /*         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
+  { 0x0ee3, 0x11b7 }, /*              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
+  { 0x0ee4, 0x11b8 }, /*              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
+  { 0x0ee5, 0x11b9 }, /*          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
+  { 0x0ee6, 0x11ba }, /*               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
+  { 0x0ee7, 0x11bb }, /*          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
+  { 0x0ee8, 0x11bc }, /*              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
+  { 0x0ee9, 0x11bd }, /*              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
+  { 0x0eea, 0x11be }, /*              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
+  { 0x0eeb, 0x11bf }, /*             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
+  { 0x0eec, 0x11c0 }, /*              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
+  { 0x0eed, 0x11c1 }, /*             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
+  { 0x0eee, 0x11c2 }, /*              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
+  { 0x0ef8, 0x11eb }, /*            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
+  { 0x0efa, 0x11f9 }, /*        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
+  { 0x0aa2, 0x2002 }, /*                     enspace   EN SPACE */
+  { 0x0aa1, 0x2003 }, /*                     emspace   EM SPACE */
+  { 0x0aa3, 0x2004 }, /*                    em3space   THREE-PER-EM SPACE */
+  { 0x0aa4, 0x2005 }, /*                    em4space   FOUR-PER-EM SPACE */
+  { 0x0aa5, 0x2007 }, /*                  digitspace   FIGURE SPACE */
+  { 0x0aa6, 0x2008 }, /*                  punctspace   PUNCTUATION SPACE */
+  { 0x0aa7, 0x2009 }, /*                   thinspace   THIN SPACE */
+  { 0x0aa8, 0x200a }, /*                   hairspace   HAIR SPACE */
+  { 0x0abb, 0x2012 }, /*                     figdash ‒ FIGURE DASH */
+  { 0x0aaa, 0x2013 }, /*                      endash – EN DASH */
+  { 0x0aa9, 0x2014 }, /*                      emdash — EM DASH */
+  { 0x07af, 0x2015 }, /*              Greek_horizbar ― HORIZONTAL BAR */
+  { 0x0cdf, 0x2017 }, /*        hebrew_doublelowline ‗ DOUBLE LOW LINE */
+  { 0x0ad0, 0x2018 }, /*         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
+  { 0x0ad1, 0x2019 }, /*        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
+  { 0x0afd, 0x201a }, /*          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
+  { 0x0ad2, 0x201c }, /*         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
+  { 0x0ad3, 0x201d }, /*        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
+  { 0x0afe, 0x201e }, /*          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
+  { 0x0af1, 0x2020 }, /*                      dagger † DAGGER */
+  { 0x0af2, 0x2021 }, /*                doubledagger ‡ DOUBLE DAGGER */
+  { 0x0ae6, 0x2022 }, /*          enfilledcircbullet • BULLET */
+  { 0x0aae, 0x2026 }, /*                    ellipsis … HORIZONTAL ELLIPSIS */
+  { 0x0ad6, 0x2032 }, /*                     minutes ′ PRIME */
+  { 0x0ad7, 0x2033 }, /*                     seconds ″ DOUBLE PRIME */
+  { 0x0afc, 0x2038 }, /*                       caret ‸ CARET */
+  { 0x047e, 0x203e }, /*                    overline ‾ OVERLINE */
+  { 0x20a0, 0x20a0 }, /*                     EcuSign ₠ EURO-CURRENCY SIGN */
+  { 0x20a1, 0x20a1 }, /*                   ColonSign ₡ COLON SIGN */
+  { 0x20a2, 0x20a2 }, /*                CruzeiroSign ₢ CRUZEIRO SIGN */
+  { 0x20a3, 0x20a3 }, /*                  FFrancSign ₣ FRENCH FRANC SIGN */
+  { 0x20a4, 0x20a4 }, /*                    LiraSign ₤ LIRA SIGN */
+  { 0x20a5, 0x20a5 }, /*                    MillSign ₥ MILL SIGN */
+  { 0x20a6, 0x20a6 }, /*                   NairaSign ₦ NAIRA SIGN */
+  { 0x20a7, 0x20a7 }, /*                  PesetaSign ₧ PESETA SIGN */
+  { 0x20a8, 0x20a8 }, /*                   RupeeSign ₨ RUPEE SIGN */
+  { 0x0eff, 0x20a9 }, /*                  Korean_Won ₩ WON SIGN */
+  { 0x20a9, 0x20a9 }, /*                     WonSign ₩ WON SIGN */
+  { 0x20aa, 0x20aa }, /*               NewSheqelSign ₪ NEW SHEQEL SIGN */
+  { 0x20ab, 0x20ab }, /*                    DongSign ₫ DONG SIGN */
+  { 0x20ac, 0x20ac }, /*                    EuroSign € EURO SIGN */
+  { 0x0ab8, 0x2105 }, /*                      careof ℅ CARE OF */
+  { 0x06b0, 0x2116 }, /*                  numerosign № NUMERO SIGN */
+  { 0x0afb, 0x2117 }, /*         phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
+  { 0x0ad4, 0x211e }, /*                prescription ℞ PRESCRIPTION TAKE */
+  { 0x0ac9, 0x2122 }, /*                   trademark ™ TRADE MARK SIGN */
+  { 0x0ab0, 0x2153 }, /*                    onethird ⅓ VULGAR FRACTION ONE THIRD */
+  { 0x0ab1, 0x2154 }, /*                   twothirds ⅔ VULGAR FRACTION TWO THIRDS */
+  { 0x0ab2, 0x2155 }, /*                    onefifth ⅕ VULGAR FRACTION ONE FIFTH */
+  { 0x0ab3, 0x2156 }, /*                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
+  { 0x0ab4, 0x2157 }, /*                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
+  { 0x0ab5, 0x2158 }, /*                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
+  { 0x0ab6, 0x2159 }, /*                    onesixth ⅙ VULGAR FRACTION ONE SIXTH */
+  { 0x0ab7, 0x215a }, /*                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
+  { 0x0ac3, 0x215b }, /*                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
+  { 0x0ac4, 0x215c }, /*                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
+  { 0x0ac5, 0x215d }, /*                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
+  { 0x0ac6, 0x215e }, /*                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
+  { 0x08fb, 0x2190 }, /*                   leftarrow ← LEFTWARDS ARROW */
+  { 0x08fc, 0x2191 }, /*                     uparrow ↑ UPWARDS ARROW */
+  { 0x08fd, 0x2192 }, /*                  rightarrow → RIGHTWARDS ARROW */
+  { 0x08fe, 0x2193 }, /*                   downarrow ↓ DOWNWARDS ARROW */
+  { 0x08ce, 0x21d2 }, /*                     implies ⇒ RIGHTWARDS DOUBLE ARROW */
+  { 0x08cd, 0x21d4 }, /*                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
+  { 0x08ef, 0x2202 }, /*           partialderivative ∂ PARTIAL DIFFERENTIAL */
+  { 0x08c5, 0x2207 }, /*                       nabla ∇ NABLA */
+  { 0x0bca, 0x2218 }, /*                         jot ∘ RING OPERATOR */
+  { 0x08d6, 0x221a }, /*                     radical √ SQUARE ROOT */
+  { 0x08c1, 0x221d }, /*                   variation ∝ PROPORTIONAL TO */
+  { 0x08c2, 0x221e }, /*                    infinity ∞ INFINITY */
+  { 0x08de, 0x2227 }, /*                  logicaland ∧ LOGICAL AND */
+  { 0x0ba9, 0x2227 }, /*                     upcaret ∧ LOGICAL AND */
+  { 0x08df, 0x2228 }, /*                   logicalor ∨ LOGICAL OR */
+  { 0x0ba8, 0x2228 }, /*                   downcaret ∨ LOGICAL OR */
+  { 0x08dc, 0x2229 }, /*                intersection ∩ INTERSECTION */
+  { 0x0bc3, 0x2229 }, /*                      upshoe ∩ INTERSECTION */
+  { 0x08dd, 0x222a }, /*                       union ∪ UNION */
+  { 0x0bd6, 0x222a }, /*                    downshoe ∪ UNION */
+  { 0x08bf, 0x222b }, /*                    integral ∫ INTEGRAL */
+  { 0x08c0, 0x2234 }, /*                   therefore ∴ THEREFORE */
+  { 0x08c8, 0x2245 }, /*                 approximate ≅ APPROXIMATELY EQUAL TO */
+  { 0x08bd, 0x2260 }, /*                    notequal ≠ NOT EQUAL TO */
+  { 0x08cf, 0x2261 }, /*                   identical ≡ IDENTICAL TO */
+  { 0x08bc, 0x2264 }, /*               lessthanequal ≤ LESS-THAN OR EQUAL TO */
+  { 0x08be, 0x2265 }, /*            greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
+  { 0x08da, 0x2282 }, /*                  includedin ⊂ SUBSET OF */
+  { 0x0bda, 0x2282 }, /*                    leftshoe ⊂ SUBSET OF */
+  { 0x08db, 0x2283 }, /*                    includes ⊃ SUPERSET OF */
+  { 0x0bd8, 0x2283 }, /*                   rightshoe ⊃ SUPERSET OF */
+  { 0x0bfc, 0x22a2 }, /*                   righttack ⊢ RIGHT TACK */
+  { 0x0bdc, 0x22a3 }, /*                    lefttack ⊣ LEFT TACK */
+  { 0x0bc2, 0x22a4 }, /*                    downtack ⊤ DOWN TACK */
+  { 0x0bce, 0x22a5 }, /*                      uptack ⊥ UP TACK */
+  { 0x0bd3, 0x2308 }, /*                     upstile ⌈ LEFT CEILING */
+  { 0x0bc4, 0x230a }, /*                   downstile ⌊ LEFT FLOOR */
+  { 0x0afa, 0x2315 }, /*           telephonerecorder ⌕ TELEPHONE RECORDER */
+  { 0x08a4, 0x2320 }, /*                 topintegral ⌠ TOP HALF INTEGRAL */
+  { 0x08a5, 0x2321 }, /*                 botintegral ⌡ BOTTOM HALF INTEGRAL */
+  { 0x0abc, 0x2329 }, /*            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
+  { 0x0abe, 0x232a }, /*           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
+  { 0x0bcc, 0x2395 }, /*                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */
+  { 0x09e2, 0x2409 }, /*                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
+  { 0x09e5, 0x240a }, /*                          lf ␊ SYMBOL FOR LINE FEED */
+  { 0x09e9, 0x240b }, /*                          vt ␋ SYMBOL FOR VERTICAL TABULATION */
+  { 0x09e3, 0x240c }, /*                          ff ␌ SYMBOL FOR FORM FEED */
+  { 0x09e4, 0x240d }, /*                          cr ␍ SYMBOL FOR CARRIAGE RETURN */
+  { 0x09df, 0x2422 }, /*                       blank ␢ BLANK SYMBOL */
+  { 0x09e8, 0x2424 }, /*                          nl ␤ SYMBOL FOR NEWLINE */
+  { 0x09f1, 0x2500 }, /*              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
+  { 0x08a6, 0x2502 }, /*               vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
+  { 0x09f8, 0x2502 }, /*                     vertbar │ BOX DRAWINGS LIGHT VERTICAL */
+  { 0x09ec, 0x250c }, /*                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
+  { 0x09eb, 0x2510 }, /*               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
+  { 0x09ed, 0x2514 }, /*               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
+  { 0x09ea, 0x2518 }, /*              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
+  { 0x09f4, 0x251c }, /*                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
+  { 0x09f5, 0x2524 }, /*                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
+  { 0x09f7, 0x252c }, /*                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
+  { 0x09f6, 0x2534 }, /*                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
+  { 0x09ee, 0x253c }, /*               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
+  { 0x09e1, 0x2592 }, /*                checkerboard ▒ MEDIUM SHADE */
+  { 0x0adf, 0x25a0 }, /*                emfilledrect ■ BLACK SQUARE */
+  { 0x0acf, 0x25a1 }, /*             emopenrectangle □ WHITE SQUARE */
+  { 0x0ae7, 0x25aa }, /*            enfilledsqbullet ▪ BLACK SMALL SQUARE */
+  { 0x0ae1, 0x25ab }, /*          enopensquarebullet ▫ WHITE SMALL SQUARE */
+  { 0x0adb, 0x25ac }, /*            filledrectbullet ▬ BLACK RECTANGLE */
+  { 0x0ae2, 0x25ad }, /*              openrectbullet ▭ WHITE RECTANGLE */
+  { 0x0ae8, 0x25b2 }, /*           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
+  { 0x0ae3, 0x25b3 }, /*             opentribulletup △ WHITE UP-POINTING TRIANGLE */
+  { 0x0add, 0x25b6 }, /*        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
+  { 0x0acd, 0x25b7 }, /*           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
+  { 0x0ae9, 0x25bc }, /*         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
+  { 0x0ae4, 0x25bd }, /*           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
+  { 0x0adc, 0x25c0 }, /*         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
+  { 0x0acc, 0x25c1 }, /*            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
+  { 0x09e0, 0x25c6 }, /*                soliddiamond ◆ BLACK DIAMOND */
+  { 0x0ace, 0x25cb }, /*                emopencircle ○ WHITE CIRCLE */
+  { 0x0bcf, 0x25cb }, /*                      circle ○ WHITE CIRCLE */
+  { 0x0ade, 0x25cf }, /*              emfilledcircle ● BLACK CIRCLE */
+  { 0x0ae0, 0x25e6 }, /*            enopencircbullet ◦ WHITE BULLET */
+  { 0x0ae5, 0x2606 }, /*                    openstar ☆ WHITE STAR */
+  { 0x0af9, 0x260e }, /*                   telephone ☎ BLACK TELEPHONE */
+  { 0x0aca, 0x2613 }, /*               signaturemark ☓ SALTIRE */
+  { 0x0aea, 0x261c }, /*                 leftpointer ☜ WHITE LEFT POINTING INDEX */
+  { 0x0aeb, 0x261e }, /*                rightpointer ☞ WHITE RIGHT POINTING INDEX */
+  { 0x0af8, 0x2640 }, /*                femalesymbol ♀ FEMALE SIGN */
+  { 0x0af7, 0x2642 }, /*                  malesymbol ♂ MALE SIGN */
+  { 0x0aec, 0x2663 }, /*                        club ♣ BLACK CLUB SUIT */
+  { 0x0aee, 0x2665 }, /*                       heart ♥ BLACK HEART SUIT */
+  { 0x0aed, 0x2666 }, /*                     diamond ♦ BLACK DIAMOND SUIT */
+  { 0x0af6, 0x266d }, /*                 musicalflat ♭ MUSIC FLAT SIGN */
+  { 0x0af5, 0x266f }, /*                musicalsharp ♯ MUSIC SHARP SIGN */
+  { 0x0af3, 0x2713 }, /*                   checkmark ✓ CHECK MARK */
+  { 0x0af4, 0x2717 }, /*                 ballotcross ✗ BALLOT X */
+  { 0x0ad9, 0x271d }, /*                  latincross ✝ LATIN CROSS */
+  { 0x0af0, 0x2720 }, /*                maltesecross ✠ MALTESE CROSS */
+  { 0x04a4, 0x3001 }, /*                  kana_comma 、 IDEOGRAPHIC COMMA */
+  { 0x04a1, 0x3002 }, /*               kana_fullstop 。 IDEOGRAPHIC FULL STOP */
+  { 0x04a2, 0x300c }, /*         kana_openingbracket 「 LEFT CORNER BRACKET */
+  { 0x04a3, 0x300d }, /*         kana_closingbracket 」 RIGHT CORNER BRACKET */
+  { 0x04de, 0x309b }, /*                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
+  { 0x04df, 0x309c }, /*             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
+  { 0x04a7, 0x30a1 }, /*                      kana_a ァ KATAKANA LETTER SMALL A */
+  { 0x04b1, 0x30a2 }, /*                      kana_A ア KATAKANA LETTER A */
+  { 0x04a8, 0x30a3 }, /*                      kana_i ィ KATAKANA LETTER SMALL I */
+  { 0x04b2, 0x30a4 }, /*                      kana_I イ KATAKANA LETTER I */
+  { 0x04a9, 0x30a5 }, /*                      kana_u ゥ KATAKANA LETTER SMALL U */
+  { 0x04b3, 0x30a6 }, /*                      kana_U ウ KATAKANA LETTER U */
+  { 0x04aa, 0x30a7 }, /*                      kana_e ェ KATAKANA LETTER SMALL E */
+  { 0x04b4, 0x30a8 }, /*                      kana_E エ KATAKANA LETTER E */
+  { 0x04ab, 0x30a9 }, /*                      kana_o ォ KATAKANA LETTER SMALL O */
+  { 0x04b5, 0x30aa }, /*                      kana_O オ KATAKANA LETTER O */
+  { 0x04b6, 0x30ab }, /*                     kana_KA カ KATAKANA LETTER KA */
+  { 0x04b7, 0x30ad }, /*                     kana_KI キ KATAKANA LETTER KI */
+  { 0x04b8, 0x30af }, /*                     kana_KU ク KATAKANA LETTER KU */
+  { 0x04b9, 0x30b1 }, /*                     kana_KE ケ KATAKANA LETTER KE */
+  { 0x04ba, 0x30b3 }, /*                     kana_KO コ KATAKANA LETTER KO */
+  { 0x04bb, 0x30b5 }, /*                     kana_SA サ KATAKANA LETTER SA */
+  { 0x04bc, 0x30b7 }, /*                    kana_SHI シ KATAKANA LETTER SI */
+  { 0x04bd, 0x30b9 }, /*                     kana_SU ス KATAKANA LETTER SU */
+  { 0x04be, 0x30bb }, /*                     kana_SE セ KATAKANA LETTER SE */
+  { 0x04bf, 0x30bd }, /*                     kana_SO ソ KATAKANA LETTER SO */
+  { 0x04c0, 0x30bf }, /*                     kana_TA タ KATAKANA LETTER TA */
+  { 0x04c1, 0x30c1 }, /*                    kana_CHI チ KATAKANA LETTER TI */
+  { 0x04af, 0x30c3 }, /*                    kana_tsu ッ KATAKANA LETTER SMALL TU */
+  { 0x04c2, 0x30c4 }, /*                    kana_TSU ツ KATAKANA LETTER TU */
+  { 0x04c3, 0x30c6 }, /*                     kana_TE テ KATAKANA LETTER TE */
+  { 0x04c4, 0x30c8 }, /*                     kana_TO ト KATAKANA LETTER TO */
+  { 0x04c5, 0x30ca }, /*                     kana_NA ナ KATAKANA LETTER NA */
+  { 0x04c6, 0x30cb }, /*                     kana_NI ニ KATAKANA LETTER NI */
+  { 0x04c7, 0x30cc }, /*                     kana_NU ヌ KATAKANA LETTER NU */
+  { 0x04c8, 0x30cd }, /*                     kana_NE ネ KATAKANA LETTER NE */
+  { 0x04c9, 0x30ce }, /*                     kana_NO ノ KATAKANA LETTER NO */
+  { 0x04ca, 0x30cf }, /*                     kana_HA ハ KATAKANA LETTER HA */
+  { 0x04cb, 0x30d2 }, /*                     kana_HI ヒ KATAKANA LETTER HI */
+  { 0x04cc, 0x30d5 }, /*                     kana_FU フ KATAKANA LETTER HU */
+  { 0x04cd, 0x30d8 }, /*                     kana_HE ヘ KATAKANA LETTER HE */
+  { 0x04ce, 0x30db }, /*                     kana_HO ホ KATAKANA LETTER HO */
+  { 0x04cf, 0x30de }, /*                     kana_MA マ KATAKANA LETTER MA */
+  { 0x04d0, 0x30df }, /*                     kana_MI ミ KATAKANA LETTER MI */
+  { 0x04d1, 0x30e0 }, /*                     kana_MU ム KATAKANA LETTER MU */
+  { 0x04d2, 0x30e1 }, /*                     kana_ME メ KATAKANA LETTER ME */
+  { 0x04d3, 0x30e2 }, /*                     kana_MO モ KATAKANA LETTER MO */
+  { 0x04ac, 0x30e3 }, /*                     kana_ya ャ KATAKANA LETTER SMALL YA */
+  { 0x04d4, 0x30e4 }, /*                     kana_YA ヤ KATAKANA LETTER YA */
+  { 0x04ad, 0x30e5 }, /*                     kana_yu ュ KATAKANA LETTER SMALL YU */
+  { 0x04d5, 0x30e6 }, /*                     kana_YU ユ KATAKANA LETTER YU */
+  { 0x04ae, 0x30e7 }, /*                     kana_yo ョ KATAKANA LETTER SMALL YO */
+  { 0x04d6, 0x30e8 }, /*                     kana_YO ヨ KATAKANA LETTER YO */
+  { 0x04d7, 0x30e9 }, /*                     kana_RA ラ KATAKANA LETTER RA */
+  { 0x04d8, 0x30ea }, /*                     kana_RI リ KATAKANA LETTER RI */
+  { 0x04d9, 0x30eb }, /*                     kana_RU ル KATAKANA LETTER RU */
+  { 0x04da, 0x30ec }, /*                     kana_RE レ KATAKANA LETTER RE */
+  { 0x04db, 0x30ed }, /*                     kana_RO ロ KATAKANA LETTER RO */
+  { 0x04dc, 0x30ef }, /*                     kana_WA ワ KATAKANA LETTER WA */
+  { 0x04a6, 0x30f2 }, /*                     kana_WO ヲ KATAKANA LETTER WO */
+  { 0x04dd, 0x30f3 }, /*                      kana_N ン KATAKANA LETTER N */
+  { 0x04a5, 0x30fb }, /*            kana_conjunctive ・ KATAKANA MIDDLE DOT */
+  { 0x04b0, 0x30fc }, /*              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
+  { 0x0ea1, 0x3131 }, /*               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
+  { 0x0ea2, 0x3132 }, /*          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
+  { 0x0ea3, 0x3133 }, /*           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
+  { 0x0ea4, 0x3134 }, /*                Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
+  { 0x0ea5, 0x3135 }, /*           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
+  { 0x0ea6, 0x3136 }, /*           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
+  { 0x0ea7, 0x3137 }, /*               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
+  { 0x0ea8, 0x3138 }, /*          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
+  { 0x0ea9, 0x3139 }, /*                Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
+  { 0x0eaa, 0x313a }, /*          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
+  { 0x0eab, 0x313b }, /*           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
+  { 0x0eac, 0x313c }, /*           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
+  { 0x0ead, 0x313d }, /*            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
+  { 0x0eae, 0x313e }, /*           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
+  { 0x0eaf, 0x313f }, /*          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
+  { 0x0eb0, 0x3140 }, /*           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
+  { 0x0eb1, 0x3141 }, /*                Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
+  { 0x0eb2, 0x3142 }, /*                Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
+  { 0x0eb3, 0x3143 }, /*           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
+  { 0x0eb4, 0x3144 }, /*            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
+  { 0x0eb5, 0x3145 }, /*                 Hangul_Sios ㅅ HANGUL LETTER SIOS */
+  { 0x0eb6, 0x3146 }, /*            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
+  { 0x0eb7, 0x3147 }, /*                Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
+  { 0x0eb8, 0x3148 }, /*                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
+  { 0x0eb9, 0x3149 }, /*           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
+  { 0x0eba, 0x314a }, /*                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
+  { 0x0ebb, 0x314b }, /*               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
+  { 0x0ebc, 0x314c }, /*                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
+  { 0x0ebd, 0x314d }, /*               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
+  { 0x0ebe, 0x314e }, /*                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
+  { 0x0ebf, 0x314f }, /*                    Hangul_A ㅏ HANGUL LETTER A */
+  { 0x0ec0, 0x3150 }, /*                   Hangul_AE ㅐ HANGUL LETTER AE */
+  { 0x0ec1, 0x3151 }, /*                   Hangul_YA ㅑ HANGUL LETTER YA */
+  { 0x0ec2, 0x3152 }, /*                  Hangul_YAE ㅒ HANGUL LETTER YAE */
+  { 0x0ec3, 0x3153 }, /*                   Hangul_EO ㅓ HANGUL LETTER EO */
+  { 0x0ec4, 0x3154 }, /*                    Hangul_E ㅔ HANGUL LETTER E */
+  { 0x0ec5, 0x3155 }, /*                  Hangul_YEO ㅕ HANGUL LETTER YEO */
+  { 0x0ec6, 0x3156 }, /*                   Hangul_YE ㅖ HANGUL LETTER YE */
+  { 0x0ec7, 0x3157 }, /*                    Hangul_O ㅗ HANGUL LETTER O */
+  { 0x0ec8, 0x3158 }, /*                   Hangul_WA ㅘ HANGUL LETTER WA */
+  { 0x0ec9, 0x3159 }, /*                  Hangul_WAE ㅙ HANGUL LETTER WAE */
+  { 0x0eca, 0x315a }, /*                   Hangul_OE ㅚ HANGUL LETTER OE */
+  { 0x0ecb, 0x315b }, /*                   Hangul_YO ㅛ HANGUL LETTER YO */
+  { 0x0ecc, 0x315c }, /*                    Hangul_U ㅜ HANGUL LETTER U */
+  { 0x0ecd, 0x315d }, /*                  Hangul_WEO ㅝ HANGUL LETTER WEO */
+  { 0x0ece, 0x315e }, /*                   Hangul_WE ㅞ HANGUL LETTER WE */
+  { 0x0ecf, 0x315f }, /*                   Hangul_WI ㅟ HANGUL LETTER WI */
+  { 0x0ed0, 0x3160 }, /*                   Hangul_YU ㅠ HANGUL LETTER YU */
+  { 0x0ed1, 0x3161 }, /*                   Hangul_EU ㅡ HANGUL LETTER EU */
+  { 0x0ed2, 0x3162 }, /*                   Hangul_YI ㅢ HANGUL LETTER YI */
+  { 0x0ed3, 0x3163 }, /*                    Hangul_I ㅣ HANGUL LETTER I */
+  { 0x0eef, 0x316d }, /*     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
+  { 0x0ef0, 0x3171 }, /*    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
+  { 0x0ef1, 0x3178 }, /*    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
+  { 0x0ef2, 0x317f }, /*              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
+  { 0x0ef4, 0x3184 }, /*   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
+  { 0x0ef5, 0x3186 }, /*          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
+  { 0x0ef6, 0x318d }, /*                Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
+  { 0x0ef7, 0x318e }, /*               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
+};
+
+static guint
+unicode_to_keyval (wchar_t ucs)
+{
+  int min = 0;
+  int max = sizeof(u2ktab) / sizeof(u2ktab[0]) - 1;
+  int mid;
+
+  /* First check for Latin-1 characters (1:1 mapping) */
+  if ((ucs >= 0x0020 && ucs <= 0x007e) ||
+      (ucs >= 0x00a0 && ucs <= 0x00ff))
+    return ucs;
+
+  /* Binary search in table */
+  while (max >= min) {
+    mid = (min + max) / 2;
+    if (u2ktab[mid].ucs < ucs)
+      min = mid + 1;
+    else if (u2ktab[mid].ucs > ucs)
+      max = mid - 1;
+    else {
+      /* found it */
+      return u2ktab[mid].keysym;
+    }
+  }
+  
+  /*
+   * No matching keysym value found, return Unicode value plus 0x01000000
+   * (a convention introduced in the UTF-8 work on xterm).
+   */
+  return ucs | 0x01000000;
+}
+
+static void
+build_key_event_state (GdkEvent *event)
+{
+  event->key.state = 0;
+  if (GetKeyState (VK_SHIFT) < 0)
+    event->key.state |= GDK_SHIFT_MASK;
+  if (GetKeyState (VK_CAPITAL) & 0x1)
+    event->key.state |= GDK_LOCK_MASK;
+  if (!is_AltGr_key)
+    {
+      if (GetKeyState (VK_CONTROL) < 0)
+       {
+         event->key.state |= GDK_CONTROL_MASK;
+         if (event->key.keyval < ' ')
+           event->key.keyval += '@';
+       }
+      else if (event->key.keyval < ' ')
+       {
+         event->key.state |= GDK_CONTROL_MASK;
+         event->key.keyval += '@';
+       }
+      if (GetKeyState (VK_MENU) < 0)
+       event->key.state |= GDK_MOD1_MASK;
+    }
+}
+
+static void
+build_keypress_event (GdkWindowPrivate *window_private,
+                     GdkEvent         *event,
+                     MSG              *xevent)
+{
+  gint i, bytesleft, bytecount, ucount, ucleft, len;
+  guchar buf[100], *bp;
+  wchar_t wbuf[100], *wcp;
+
+  event->key.type = GDK_KEY_PRESS;
+  event->key.time = xevent->time;
+  
+  if (xevent->message == WM_CHAR)
+    {
+      bytecount = MIN ((xevent->lParam & 0xFFFF), sizeof (buf));
+      for (i = 0; i < bytecount; i++)
+       buf[i] = xevent->wParam;
+    }
+  else
+    {
+      /* WM_IME_CHAR */
+      event->key.keyval = GDK_VoidSymbol;
+      if (xevent->wParam & 0xFF00)
+       {
+         /* Contrary to the documentation,
+          * the lead byte is the msb byte.
+          */
+         buf[0] = ((xevent->wParam >> 8) & 0xFF);
+         buf[1] = (xevent->wParam & 0xFF);
+         bytecount = 2;
+       }
+      else
+       {
+         buf[0] = (xevent->wParam & 0xFF);
+         bytecount = 1;
+       }
+    }
+
+  /* Convert from the window's current code page
+   * to Unicode. Then convert to UTF-8.
+   * We don't handle the surrogate stuff. Should we?
+   */
+  ucount = MultiByteToWideChar (window_private->charset_info.ciACP,
+                               0, buf, bytecount, wbuf, 100);
+  
+  if (ucount == 0)
+    event->key.keyval = GDK_VoidSymbol;
+  else if (xevent->message == WM_CHAR)
+    if (xevent->wParam < ' ')
+      event->key.keyval = xevent->wParam + '@';
+    else
+      event->key.keyval = unicode_to_keyval (wbuf[0]);
+  else
+    event->key.keyval = GDK_VoidSymbol;
+
+  build_key_event_state (event);
+
+  ucleft = ucount;
+  len = 0;
+  wcp = wbuf;
+  while (ucleft-- > 0)
+    {
+      wchar_t c = *wcp++;
+
+      if (c < 0x80)
+       len += 1;
+      else if (c < 0x800)
+       len += 2;
+      else
+       len += 3;
+    }
+
+  event->key.string = g_malloc (len + 1);
+  event->key.length = len;
+  
+  ucleft = ucount;
+  wcp = wbuf;
+  bp = event->key.string;
+  while (ucleft-- > 0)
+    {
+      int first;
+      int i;
+      wchar_t c = *wcp++;
+
+      if (c < 0x80)
+       {
+         first = 0;
+         len = 1;
+       }
+      else if (c < 0x800)
+       {
+         first = 0xc0;
+         len = 2;
+       }
+      else
+       {
+         first = 0xe0;
+         len = 3;
+       }
+
+#if 1      
+      /* Woo-hoo! */
+      switch (len)
+       {
+       case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 1: bp[0] = c | first;
+       }
+#else
+      for (i = len - 1; i > 0; --i)
+       {
+         bp[i] = (c & 0x3f) | 0x80;
+         c >>= 6;
+       }
+      bp[0] = c | first;
+#endif
+
+      bp += len;
+    }
+  *bp = 0;
+}
+
+static void
+print_event_state (gint state)
+{
+  if (state & GDK_SHIFT_MASK)
+    g_print ("SHIFT ");
+  if (state & GDK_LOCK_MASK)
+    g_print ("LOCK ");
+  if (state & GDK_CONTROL_MASK)
+    g_print ("CONTROL ");
+  if (state & GDK_MOD1_MASK)
+    g_print ("MOD1 ");
+  if (state & GDK_BUTTON1_MASK)
+    g_print ("BUTTON1 ");
+  if (state & GDK_BUTTON2_MASK)
+    g_print ("BUTTON2 ");
+  if (state & GDK_BUTTON3_MASK)
+    g_print ("BUTTON3 ");
+}
+
+static void
+print_event (GdkEvent *event)
+{
+  gchar *escaped, *kvname;
+
+  switch (event->any.type)
+    {
+    case GDK_NOTHING: g_print ("GDK_NOTHING "); break;
+    case GDK_DELETE: g_print ("GDK_DELETE "); break;
+    case GDK_DESTROY: g_print ("GDK_DESTROY "); break;
+    case GDK_EXPOSE: g_print ("GDK_EXPOSE "); break;
+    case GDK_MOTION_NOTIFY: g_print ("GDK_MOTION_NOTIFY "); break;
+    case GDK_BUTTON_PRESS: g_print ("GDK_BUTTON_PRESS "); break;
+    case GDK_2BUTTON_PRESS: g_print ("GDK_2BUTTON_PRESS "); break;
+    case GDK_3BUTTON_PRESS: g_print ("GDK_3BUTTON_PRESS "); break;
+    case GDK_BUTTON_RELEASE: g_print ("GDK_BUTTON_RELEASE "); break;
+    case GDK_KEY_PRESS: g_print ("GDK_KEY_PRESS "); break;
+    case GDK_KEY_RELEASE: g_print ("GDK_KEY_RELEASE "); break;
+    case GDK_ENTER_NOTIFY: g_print ("GDK_ENTER_NOTIFY "); break;
+    case GDK_LEAVE_NOTIFY: g_print ("GDK_LEAVE_NOTIFY "); break;
+    case GDK_FOCUS_CHANGE: g_print ("GDK_FOCUS_CHANGE "); break;
+    case GDK_CONFIGURE: g_print ("GDK_CONFIGURE "); break;
+    case GDK_MAP: g_print ("GDK_MAP "); break;
+    case GDK_UNMAP: g_print ("GDK_UNMAP "); break;
+    case GDK_PROPERTY_NOTIFY: g_print ("GDK_PROPERTY_NOTIFY "); break;
+    case GDK_SELECTION_CLEAR: g_print ("GDK_SELECTION_CLEAR "); break;
+    case GDK_SELECTION_REQUEST: g_print ("GDK_SELECTION_REQUEST "); break;
+    case GDK_SELECTION_NOTIFY: g_print ("GDK_SELECTION_NOTIFY "); break;
+    case GDK_PROXIMITY_IN: g_print ("GDK_PROXIMITY_IN "); break;
+    case GDK_PROXIMITY_OUT: g_print ("GDK_PROXIMITY_OUT "); break;
+    case GDK_DRAG_ENTER: g_print ("GDK_DRAG_ENTER "); break;
+    case GDK_DRAG_LEAVE: g_print ("GDK_DRAG_LEAVE "); break;
+    case GDK_DRAG_MOTION: g_print ("GDK_DRAG_MOTION "); break;
+    case GDK_DRAG_STATUS: g_print ("GDK_DRAG_STATUS "); break;
+    case GDK_DROP_START: g_print ("GDK_DROP_START "); break;
+    case GDK_DROP_FINISHED: g_print ("GDK_DROP_FINISHED "); break;
+    case GDK_CLIENT_EVENT: g_print ("GDK_CLIENT_EVENT "); break;
+    case GDK_VISIBILITY_NOTIFY: g_print ("GDK_VISIBILITY_NOTIFY "); break;
+    case GDK_NO_EXPOSE: g_print ("GDK_NO_EXPOSE "); break;
+    }
+  g_print ("%#x ", GDK_DRAWABLE_XID (event->any.window));
+
+  switch (event->any.type)
+    {
+    case GDK_EXPOSE:
+      g_print ("%dx%d@+%d+%d %d",
+              event->expose.area.width,
+              event->expose.area.height,
+              event->expose.area.x,
+              event->expose.area.y,
+              event->expose.count);
+      break;
+    case GDK_MOTION_NOTIFY:
+      print_event_state (event->motion.state);
+      break;
+    case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      g_print ("%d ", event->button.button);
+      print_event_state (event->button.state);
+      break;
+    case GDK_KEY_PRESS: 
+    case GDK_KEY_RELEASE:
+      if (event->key.length == 0)
+       escaped = g_strdup ("");
+      else
+       escaped = g_strescape (event->key.string, NULL);
+      kvname = gdk_keyval_name (event->key.keyval);
+      g_print ("%s %d:\"%s\" ",
+              (kvname ? kvname : "??"),
+              event->key.length,
+              escaped);
+      g_free (escaped);
+      print_event_state (event->key.state);
+      break;
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      g_print (" %s",
+              (event->crossing.detail == GDK_NOTIFY_INFERIOR ? "INFERIOR" :
+               (event->crossing.detail == GDK_NOTIFY_ANCESTOR ? "ANCESTOR" :
+                (event->crossing.detail == GDK_NOTIFY_NONLINEAR ? "NONLINEAR" :
+                 "???"))));
+      break;
+    }  
+  g_print ("\n");
+}
+
 static void
 synthesize_crossing_events (GdkWindow *window,
                            MSG       *xevent)
 {
+  TRACKMOUSEEVENT tme;
   GdkEvent *event;
-  GdkWindowPrivate *window_private = (GdkWindowPrivate *) window;
-  GdkWindowPrivate *curWnd_private = (GdkWindowPrivate *) curWnd;
   
-  if (curWnd && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
+  /* If we are not using TrackMouseEvent, generate a leave notify
+   * event if necessary
+   */
+  if (p_TrackMouseEvent == NULL
+      && curWnd
+      && (WINDOW_PRIVATE(curWnd)->event_mask & GDK_LEAVE_NOTIFY_MASK))
     {
       GDK_NOTE (EVENTS, g_print ("synthesizing LEAVE_NOTIFY event\n"));
 
@@ -1099,15 +3073,21 @@ synthesize_crossing_events (GdkWindow *window,
       event->crossing.x_root = curXroot;
       event->crossing.y_root = curYroot;
       event->crossing.mode = GDK_CROSSING_NORMAL;
-      event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+      if (IsChild (GDK_DRAWABLE_XID (curWnd), GDK_DRAWABLE_XID (window)))
+       event->crossing.detail = GDK_NOTIFY_INFERIOR;
+      else if (IsChild (GDK_DRAWABLE_XID (window), GDK_DRAWABLE_XID (curWnd)))
+       event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+      else
+       event->crossing.detail = GDK_NOTIFY_NONLINEAR;
 
       event->crossing.focus = TRUE; /* ??? */
       event->crossing.state = 0; /* ??? */
 
       gdk_event_queue_append (event);
+      GDK_NOTE (EVENTS, print_event (event));
     }
 
-  if (window_private && (window_private->event_mask & GDK_ENTER_NOTIFY_MASK))
+  if (WINDOW_PRIVATE(window)->event_mask & GDK_ENTER_NOTIFY_MASK)
     {
       GDK_NOTE (EVENTS, g_print ("synthesizing ENTER_NOTIFY event\n"));
       
@@ -1122,35 +3102,217 @@ synthesize_crossing_events (GdkWindow *window,
       event->crossing.x_root = (gfloat) xevent->pt.x;
       event->crossing.y_root = (gfloat) xevent->pt.y;
       event->crossing.mode = GDK_CROSSING_NORMAL;
-      event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+      if (curWnd
+         && IsChild (GDK_DRAWABLE_XID (curWnd), GDK_DRAWABLE_XID (window)))
+       event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+      else if (curWnd
+              && IsChild (GDK_DRAWABLE_XID (window), GDK_DRAWABLE_XID (curWnd)))
+       event->crossing.detail = GDK_NOTIFY_INFERIOR;
+      else
+       event->crossing.detail = GDK_NOTIFY_NONLINEAR;
       
       event->crossing.focus = TRUE; /* ??? */
       event->crossing.state = 0; /* ??? */
       
       gdk_event_queue_append (event);
 
-      if (window_private->extension_events != 0
+      GDK_NOTE (EVENTS, print_event (event));
+
+      if (WINDOW_PRIVATE(window)->extension_events != 0
          && gdk_input_vtable.enter_event)
        gdk_input_vtable.enter_event (&event->crossing, window);
+
     }
   
   if (curWnd)
     gdk_window_unref (curWnd);
   curWnd = window;
   gdk_window_ref (curWnd);
+  if (p_TrackMouseEvent != NULL)
+    {
+      tme.cbSize = sizeof (TRACKMOUSEEVENT);
+      tme.dwFlags = TME_LEAVE;
+      tme.hwndTrack = GDK_DRAWABLE_XID (curWnd);
+      tme.dwHoverTime = HOVER_DEFAULT;
+      
+      (*p_TrackMouseEvent) (&tme);
+    }
+}
+
+static GdkWindow *
+key_propagate (GdkWindow *window,
+              MSG       *xevent)
+{
+  gdk_window_unref (window);
+  window = WINDOW_PRIVATE(window)->parent;
+  gdk_window_ref (window);
+  GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
+                            GDK_DRAWABLE_XID (window)));
+
+  return window;
+}  
+
+static GdkWindow *
+mouse_propagate (GdkWindow *window,
+                MSG       *xevent)
+{
+  POINT pt;
+
+  pt.x = LOWORD (xevent->lParam);
+  pt.y = HIWORD (xevent->lParam);
+  ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
+  gdk_window_unref (window);
+  window = WINDOW_PRIVATE(window)->parent;
+  gdk_window_ref (window);
+  ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
+  xevent->lParam = MAKELPARAM (pt.x, pt.y);
+  GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
+                            GDK_DRAWABLE_XID (window)));
+  return window;
+}
+
+#ifdef NEW_PROPAGATION_CODE
+
+static gboolean
+propagate (GdkWindow  **window,
+          MSG         *xevent,
+          GdkWindow   *grab_window,
+          gboolean     grab_owner_events,
+          gint         grab_mask,
+          gboolean   (*doesnt_want_it) (gint mask,
+                                        MSG *xevent),
+          GdkWindow *(*propagate) (GdkWindow *window,
+                                   MSG       *xevent))
+{
+  if (grab_window != NULL && !grab_owner_events)
+    {
+      /* Event source is grabbed with owner_events FALSE */
+      GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE, "));
+      if ((*doesnt_want_it) (grab_mask, xevent))
+       {
+         GDK_NOTE (EVENTS, g_print ("...grabber doesn't want it\n"));
+         return FALSE;
+       }
+      else
+       {
+         GDK_NOTE (EVENTS, g_print ("...sending to grabber %#x\n",
+                                    GDK_DRAWABLE_XID (grab_window)));
+         gdk_window_unref (*window);
+         *window = grab_window;
+         gdk_window_ref (*window);
+         return TRUE;
+       }
+    }
+  while (TRUE)
+    {
+     if ((*doesnt_want_it) (WINDOW_PRIVATE(*window)->event_mask, xevent))
+       {
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(*window)->parent == (GdkWindow *) gdk_root_parent)
+           {
+             /* No parent; check if grabbed */
+             if (grab_window != NULL)
+               {
+                 /* Event source is grabbed with owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 if ((*doesnt_want_it) (grab_mask, xevent))
+                   {
+                     /* Grabber doesn't want it either */
+                     GDK_NOTE (EVENTS, g_print ("...grabber doesn't want it\n"));
+                     return FALSE;
+                   }
+                 else
+                   {
+                     /* Grabbed! */
+                     GDK_NOTE (EVENTS, g_print ("...sending to grabber %#x\n",
+                                                GDK_DRAWABLE_XID (grab_window)));
+                     gdk_window_unref (*window);
+                     *window = grab_window;
+                     gdk_window_ref (*window);
+                     return TRUE;
+                   }
+               }
+             else
+               {
+                 GDK_NOTE (EVENTS, "...undelivered\n");
+                 return FALSE;
+               }
+           }
+         else
+           {
+             *window = (*propagate) (*window, xevent);
+             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
+                                        GDK_DRAWABLE_XID (*window)));
+             /* The only branch where we actually continue the loop */
+           }
+       }
+      else
+       return TRUE;
+    }
+}
+
+static gboolean
+doesnt_want_key (gint mask,
+                MSG *xevent)
+{
+  return (((xevent->message == WM_KEYUP
+           || xevent->message == WM_SYSKEYUP)
+          && !(mask & GDK_KEY_RELEASE_MASK))
+         ||
+         ((xevent->message == WM_KEYDOWN
+           || xevent->message == WM_SYSKEYDOWN)
+          && !(mask & GDK_KEY_PRESS_MASK)));
+}
+
+static gboolean
+doesnt_want_char (gint mask,
+                 MSG *xevent)
+{
+  return !(mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK));
+}
+
+static gboolean
+doesnt_want_button_press (gint mask,
+                         MSG *xevent)
+{
+  return !(mask & GDK_BUTTON_PRESS_MASK);
+}
+
+static gboolean
+doesnt_want_button_release (gint mask,
+                           MSG *xevent)
+{
+  return !(mask & GDK_BUTTON_RELEASE_MASK);
+}
+
+static gboolean
+doesnt_want_button_motion (gint mask,
+                          MSG *xevent)
+{
+  return !((mask & GDK_POINTER_MOTION_MASK)
+          || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
+              && (mask & GDK_BUTTON_MOTION_MASK))
+          || ((xevent->wParam & MK_LBUTTON)
+              && (mask & GDK_BUTTON1_MOTION_MASK))
+          || ((xevent->wParam & MK_MBUTTON)
+              && (mask & GDK_BUTTON2_MOTION_MASK))
+          || ((xevent->wParam & MK_RBUTTON)
+              && (mask & GDK_BUTTON3_MOTION_MASK)));
 }
 
-static gint
+#endif
+
+static gboolean
 gdk_event_translate (GdkEvent *event,
                     MSG      *xevent,
                     gboolean *ret_val_flagp,
                     gint     *ret_valp)
 {
-  GdkWindow *window;
-  GdkWindowPrivate *window_private;
-
+  GdkWindow *window, *orig_window;
   GdkColormapPrivate *colormap_private;
   HWND owner;
+  DWORD pidActWin;
+  DWORD pidThis;
   DWORD dwStyle;
   PAINTSTRUCT paintstruct;
   HDC hdc;
@@ -1158,7 +3320,6 @@ gdk_event_translate (GdkEvent *event,
   RECT rect;
   POINT pt;
   MINMAXINFO *lpmmi;
-  GdkWindowPrivate *curWnd_private;
   GdkEventMask mask;
   GdkDrawablePrivate *pixmap_private;
   HDC bgdc;
@@ -1166,8 +3327,8 @@ gdk_event_translate (GdkEvent *event,
   int button;
   int i, j;
   gchar buf[256];
-  gint charcount;
-  gint return_val;
+  gchar *msgname;
+  gboolean return_val;
   gboolean flag;
   
   return_val = FALSE;
@@ -1175,16 +3336,15 @@ gdk_event_translate (GdkEvent *event,
   if (ret_val_flagp)
     *ret_val_flagp = FALSE;
 
+#ifndef USE_DISPATCHMESSAGE
   if (xevent->message == gdk_ping_msg)
     {
       /* Messages we post ourselves just to wakeup WaitMessage.  */
+      GDK_NOTE (EVENTS, g_print ("gdk_ping_msg\n"));
+
       return FALSE;
     }
-
-  window = gdk_window_lookup (xevent->hwnd);
-  window_private = (GdkWindowPrivate *) window;
-  
-  if (xevent->message == g_pipe_readable_msg)
+  else if (xevent->message == g_pipe_readable_msg)
     {
       GDK_NOTE (EVENTS, g_print ("g_pipe_readable_msg: %d %d\n",
                                 xevent->wParam, xevent->lParam));
@@ -1192,7 +3352,11 @@ gdk_event_translate (GdkEvent *event,
       g_io_channel_win32_pipe_readable (xevent->wParam, xevent->lParam);
       return FALSE;
     }
+#endif
 
+  window = gdk_window_lookup (xevent->hwnd);
+  orig_window = window;
+  
   if (window != NULL)
     gdk_window_ref (window);
   else
@@ -1218,18 +3382,12 @@ gdk_event_translate (GdkEvent *event,
       return FALSE;
     }
   
-  event->any.window = window;
-
-  if (window_private && GDK_DRAWABLE_DESTROYED (window))
-    {
-    }
-  else
+  if (!GDK_DRAWABLE_DESTROYED (window))
     {
       /* Check for filters for this window */
       GdkFilterReturn result;
       result = gdk_event_apply_filters
-       (xevent, event,
-        window_private ? window_private->filters : gdk_default_filters);
+       (xevent, event, WINDOW_PRIVATE(window)->filters);
       
       if (result != GDK_FILTER_CONTINUE)
        {
@@ -1249,7 +3407,7 @@ gdk_event_translate (GdkEvent *event,
       event->selection.property = gdk_selection_property;
       event->selection.time = xevent->time;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
 
       /* Will pass through switch below without match */
     }
@@ -1266,7 +3424,7 @@ gdk_event_translate (GdkEvent *event,
       event->selection.requestor = (guint32) xevent->hwnd;
       event->selection.time = xevent->time;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
 
       /* Again, will pass through switch below without match */
     }
@@ -1280,7 +3438,7 @@ gdk_event_translate (GdkEvent *event,
       event->selection.selection = xevent->wParam;
       event->selection.time = xevent->time;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = GDK_DRAWABLE_DESTROYED (window);
 
       /* Once again, we will pass through switch below without match */
     }
@@ -1325,6 +3483,16 @@ gdk_event_translate (GdkEvent *event,
 
   switch (xevent->message)
     {
+    case WM_INPUTLANGCHANGE:
+      GDK_NOTE (EVENTS,
+               g_print ("WM_INPUTLANGCHANGE: %#x charset %d locale %x\n",
+                        xevent->hwnd, xevent->wParam, xevent->lParam));
+      WINDOW_PRIVATE(window)->input_locale = (HKL) xevent->lParam;
+      TranslateCharsetInfo ((DWORD FAR *) xevent->wParam,
+                           &WINDOW_PRIVATE(window)->charset_info,
+                           TCI_SRCCHARSET);
+      break;
+
     case WM_SYSKEYUP:
     case WM_SYSKEYDOWN:
       GDK_NOTE (EVENTS,
@@ -1367,50 +3535,57 @@ gdk_event_translate (GdkEvent *event,
 
       ignore_WM_CHAR = TRUE;
     keyup_or_down:
+
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+                     doesnt_want_key,
+                     key_propagate))
+         break;
+      event->key.window = window;
+#else
       if (k_grab_window != NULL && !k_grab_owner_events)
        {
          /* Keyboard is grabbed with owner_events FALSE */
-         GDK_NOTE (EVENTS,
-                   g_print ("...grabbed, owner_events FALSE, "
-                            "sending to %#x\n",
-                            GDK_DRAWABLE_XID (k_grab_window)));
+         GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE, "
+                                    "sending to %#x\n",
+                                    GDK_DRAWABLE_XID (k_grab_window)));
          event->key.window = k_grab_window;
+         /* Continue with switch statement below */
        }
-      else if (window_private
-              && (((xevent->message == WM_KEYUP
+      else if (((xevent->message == WM_KEYUP
                     || xevent->message == WM_SYSKEYUP)
-                   && !(window_private->event_mask & GDK_KEY_RELEASE_MASK))
+                   && !(WINDOW_PRIVATE(window)->event_mask & GDK_KEY_RELEASE_MASK))
                   || ((xevent->message == WM_KEYDOWN
                        || xevent->message == WM_SYSKEYDOWN)
-                      && !(window_private->event_mask & GDK_KEY_PRESS_MASK))))
+                      && !(WINDOW_PRIVATE(window)->event_mask & GDK_KEY_PRESS_MASK)))
        {
-         /* Owner window doesn't want it */
-         if (k_grab_window != NULL && k_grab_owner_events)
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Keyboard is grabbed with owner_events TRUE */
-             GDK_NOTE (EVENTS,
-                       g_print ("...grabbed, owner_events TRUE, doesn't want it, "
-                                "sending to %#x\n",
-                                GDK_DRAWABLE_XID (k_grab_window)));
-             event->key.window = k_grab_window;
+             /* No parent; check if grabbed */
+             if (k_grab_window != NULL)
+               {
+                 /* Keyboard is grabbed with owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 event->key.window = k_grab_window;
+                 /* Continue with switch statement below */
+               }
+             else
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               break;
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = key_propagate (window, xevent);
+             /* Jump back up */
              goto keyup_or_down;
            }
        }
-             
+      else
+       event->key.window = window;
+
+      g_assert (event->key.window == window);
+#endif       
       switch (xevent->wParam)
        {
        case VK_LBUTTON:
@@ -1505,34 +3680,22 @@ gdk_event_translate (GdkEvent *event,
        case VK_MULTIPLY:
          event->key.keyval = GDK_KP_Multiply; break;
        case VK_ADD:
-#if 0
-         event->key.keyval = GDK_KP_Add; break;
-#else
          /* Pass it on as an ASCII plus in WM_CHAR. */
          ignore_WM_CHAR = FALSE;
          break;
-#endif
        case VK_SEPARATOR:
          event->key.keyval = GDK_KP_Separator; break;
        case VK_SUBTRACT:
-#if 0
-         event->key.keyval = GDK_KP_Subtract; break;
-#else
          /* Pass it on as an ASCII minus in WM_CHAR. */
          ignore_WM_CHAR = FALSE;
          break;
-#endif
        case VK_DECIMAL:
-#if 0
-         event->key.keyval = GDK_KP_Decimal; break;
-#else
          /* The keypad decimal key should also be passed on as the decimal
           * sign ('.' or ',' depending on the Windows locale settings,
           * apparently). So wait for the WM_CHAR here, also.
           */
          ignore_WM_CHAR = FALSE;
          break;
-#endif
        case VK_DIVIDE:
          event->key.keyval = GDK_KP_Divide; break;
        case VK_F1:
@@ -1579,24 +3742,32 @@ gdk_event_translate (GdkEvent *event,
        case '9':
          if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0
                                || GetKeyState (VK_MENU) < 0))
-           /* Control- or Alt-digits won't come in as a WM_CHAR */
+           /* Control- or Alt-digits won't come in as a WM_CHAR,
+            * but beware of AltGr-digits, which are used for instance
+            * on Finnish keyboards.
+            */
            event->key.keyval = GDK_0 + (xevent->wParam - '0');
          else
-           {
-             ignore_WM_CHAR = FALSE;
-             event->key.keyval = GDK_VoidSymbol;
-           }
+           ignore_WM_CHAR = FALSE;
+         break;
+       case VK_OEM_PLUS:       /* On my Win98, the '+' key comes in
+                                * as VK_OEM_PLUS
+                                */
+         if (!is_AltGr_key && (GetKeyState (VK_CONTROL) < 0
+                               || GetKeyState (VK_MENU) < 0))
+           /* Control- or Alt-plus won't come in as WM_CHAR,
+            * but beware of AltGr-plus which is backslash on
+            * Finnish keyboards
+            */
+           event->key.keyval = '+';
+         else
+           ignore_WM_CHAR = FALSE;
          break;
        default:
          if (xevent->message == WM_SYSKEYDOWN || xevent->message == WM_SYSKEYUP)
-           {
-             event->key.keyval = xevent->wParam;
-           }
+           event->key.keyval = xevent->wParam;
          else
-           {
-             ignore_WM_CHAR = FALSE;
-             event->key.keyval = GDK_VoidSymbol;
-           }
+           ignore_WM_CHAR = FALSE;
          break;
        }
 
@@ -1607,7 +3778,6 @@ gdk_event_translate (GdkEvent *event,
       event->key.type = ((xevent->message == WM_KEYDOWN
                          || xevent->message == WM_SYSKEYDOWN) ?
                         GDK_KEY_PRESS : GDK_KEY_RELEASE);
-      event->key.window = window;
       event->key.time = xevent->time;
       event->key.state = 0;
       if (GetKeyState (VK_SHIFT) < 0)
@@ -1618,17 +3788,21 @@ gdk_event_translate (GdkEvent *event,
        event->key.state |= GDK_CONTROL_MASK;
       if (xevent->wParam != VK_MENU && GetKeyState (VK_MENU) < 0)
        event->key.state |= GDK_MOD1_MASK;
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
       event->key.string = NULL;
       event->key.length = 0;
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
+    case WM_IME_CHAR:
+      GDK_NOTE (EVENTS,
+               g_print ("WM_IME_CHAR: %#x  bytes: %#.04x\n",
+                        xevent->hwnd, xevent->wParam));
+      goto wm_char;
+      
     case WM_CHAR:
       GDK_NOTE (EVENTS, 
                g_print ("WM_CHAR: %#x  char: %#x %#.08x  %s\n",
-                        xevent->hwnd,
-                        xevent->wParam,
-                        xevent->lParam,
+                        xevent->hwnd, xevent->wParam, xevent->lParam,
                         (ignore_WM_CHAR ? "ignored" : "")));
 
       if (ignore_WM_CHAR)
@@ -1638,9 +3812,17 @@ gdk_event_translate (GdkEvent *event,
        }
 
     wm_char:
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+                     doesnt_want_char,
+                     key_propagate))
+         break;
+      event->key.window = window;
+#else
       /* This doesn't handle the rather theorethical case that a window
        * wants key presses but still wants releases to be propagated,
-       * for instance.
+       * for instance. Or is that so theorethical?
        */
       if (k_grab_window != NULL && !k_grab_owner_events)
        {
@@ -1651,126 +3833,63 @@ gdk_event_translate (GdkEvent *event,
                             GDK_DRAWABLE_XID (k_grab_window)));
          event->key.window = k_grab_window;
        }
-      else if (window_private
-              && !(window_private->event_mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)))
+      else if (!(WINDOW_PRIVATE(window)->event_mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)))
        {
-         /* Owner window doesn't want it */
-         if (k_grab_window != NULL && k_grab_owner_events)
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Keyboard is grabbed with owner_events TRUE */
-             GDK_NOTE (EVENTS,
-                       g_print ("...grabbed, owner_events TRUE, doesn't want it, "
-                                "sending to %#x\n",
-                                GDK_DRAWABLE_XID (k_grab_window)));
-             event->key.window = k_grab_window;
+             /* No parent; check if grabbed */
+             if (k_grab_window != NULL)
+               {
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 event->key.window = k_grab_window;
+               }
+             else
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               g_assert_not_reached (); /* Should've been handled above */
-
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = key_propagate (window, xevent);
+             /* Jump back up */
              goto wm_char;
            }
        }
-      
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      if (return_val && (window_private->event_mask & GDK_KEY_RELEASE_MASK))
+      else
+       event->key.window = window;
+
+      g_assert (event->key.window == window);
+#endif
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
+      if (return_val && (event->key.window == k_grab_window
+                        || (WINDOW_PRIVATE(window)->event_mask & GDK_KEY_RELEASE_MASK)))
        {
-         /* Return the release event, and maybe append the press
-          * event to the queued_events list (from which it will vbe
-          * fetched before the release event).
-          */
-         event->key.type = GDK_KEY_RELEASE;
-         event->key.keyval = xevent->wParam;
-         event->key.window = window;
-         event->key.time = xevent->time;
-         event->key.state = 0;
-         if (GetKeyState (VK_SHIFT) < 0)
-           event->key.state |= GDK_SHIFT_MASK;
-         if (GetKeyState (VK_CAPITAL) & 0x1)
-           event->key.state |= GDK_LOCK_MASK;
-         if (is_AltGr_key)
-           ;
-         else if (GetKeyState (VK_CONTROL) < 0)
-           {
-             event->key.state |= GDK_CONTROL_MASK;
-             if (event->key.keyval < ' ')
-               event->key.keyval += '@';
-           }
-         else if (event->key.keyval < ' ')
+         if (window == k_grab_window
+             || (WINDOW_PRIVATE(window)->event_mask & GDK_KEY_PRESS_MASK))
            {
-             event->key.state |= GDK_CONTROL_MASK;
-             event->key.keyval += '@';
-           }
-         if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
-           event->key.state |= GDK_MOD1_MASK;
-         event->key.string = g_malloc (2);
-         event->key.length = 1;
-         event->key.string[0] = xevent->wParam; /* ??? */
-         event->key.string[1] = 0;
-
-         if (window_private->event_mask & GDK_KEY_PRESS_MASK)
-           {
-             /* Append also a GDK_KEY_PRESS event to the pushback list.  */
-             GdkEvent *event2 = gdk_event_copy (event);
-             event2->key.type = GDK_KEY_PRESS;
-             charcount = xevent->lParam & 0xFFFF;
-             if (charcount > sizeof (buf)- 1)
-               charcount = sizeof (buf) - 1;
-             g_free (event2->key.string);
-             event2->key.string = g_malloc (charcount + 1);
-             for (i = 0; i < charcount; i++)
-               event2->key.string[i] = event->key.keyval;
-             event2->key.string[charcount] = 0;
-             event2->key.length = charcount;
-
+             /* Append a GDK_KEY_PRESS event to the pushback list
+              * (from which it will be fetched before the release
+              * event).
+              */
+             GdkEvent *event2 = gdk_event_new ();
+             build_keypress_event (WINDOW_PRIVATE(window), event2, xevent);
+             event2->key.window = window;
+             gdk_window_ref (window);
              gdk_event_queue_append (event2);
+             GDK_NOTE (EVENTS, print_event (event2));
            }
+         /* Return the release event.  */
+         event->key.type = GDK_KEY_RELEASE;
+         event->key.keyval = xevent->wParam;
+         event->key.time = xevent->time;
+         build_key_event_state (event);
+         event->key.string = NULL;
+         event->key.length = 0;
        }
-      else if (return_val && (window_private->event_mask & GDK_KEY_PRESS_MASK))
+      else if (return_val
+              && (WINDOW_PRIVATE(window)->event_mask & GDK_KEY_PRESS_MASK))
        {
          /* Return just the GDK_KEY_PRESS event. */
-         event->key.type = GDK_KEY_PRESS;
-         charcount = xevent->lParam & 0xFFFF;
-         if (charcount > sizeof (buf)- 1)
-           charcount = sizeof (buf) - 1;
-         event->key.keyval = xevent->wParam;
-         event->key.window = window;
-         event->key.time = xevent->time;
-         event->key.state = 0;
-         if (GetKeyState (VK_SHIFT) < 0)
-           event->key.state |= GDK_SHIFT_MASK;
-         if (GetKeyState (VK_CAPITAL) & 0x1)
-           event->key.state |= GDK_LOCK_MASK;
-         if (is_AltGr_key)
-           ;
-         else if (GetKeyState (VK_CONTROL) < 0)
-           {
-             event->key.state |= GDK_CONTROL_MASK;
-             if (event->key.keyval < ' ')
-               event->key.keyval += '@';
-           }
-         else if (event->key.keyval < ' ')
-           {
-             event->key.state |= GDK_CONTROL_MASK;
-             event->key.keyval += '@';
-           }
-         if (!is_AltGr_key && GetKeyState (VK_MENU) < 0)
-           event->key.state |= GDK_MOD1_MASK;
-         event->key.string = g_malloc (charcount + 1);
-         for (i = 0; i < charcount; i++)
-           event->key.string[i] = event->key.keyval;
-         event->key.string[charcount] = 0;
-         event->key.length = charcount;
+         build_keypress_event (WINDOW_PRIVATE(window), event, xevent);
        }
       else
        return_val = FALSE;
@@ -1799,8 +3918,7 @@ gdk_event_translate (GdkEvent *event,
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam),
                         button));
 
-      if (window_private
-         && (window_private->extension_events != 0)
+      if (WINDOW_PRIVATE(window)->extension_events != 0
          && gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print ("...ignored\n"));
@@ -1811,18 +3929,23 @@ gdk_event_translate (GdkEvent *event,
        synthesize_crossing_events (window, xevent);
 
       event->button.type = GDK_BUTTON_PRESS;
-    buttondown:
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     p_grab_window, p_grab_owner_events, p_grab_mask,
+                     doesnt_want_button_press,
+                     mouse_propagate))
+         break;
       event->button.window = window;
-      if (window_private)
-       mask = window_private->event_mask;
-      else
-       mask = 0;               /* ??? */
+#else
+    buttondown:
+      mask = WINDOW_PRIVATE(window)->event_mask;
 
       if (p_grab_window != NULL && !p_grab_owner_events)
        {
          /* Pointer is grabbed with owner_events FALSE */
          GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
-         mask = p_grab_event_mask;
+
+         mask = p_grab_mask;
          if (!(mask & GDK_BUTTON_PRESS_MASK))
            /* Grabber doesn't want it */
            break;
@@ -1831,61 +3954,79 @@ gdk_event_translate (GdkEvent *event,
          GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
                                     GDK_DRAWABLE_XID (p_grab_window)));
        }
-      else if (window_private
-              && !(mask & GDK_BUTTON_PRESS_MASK))
+      else if (!(mask & GDK_BUTTON_PRESS_MASK))
        {
-         /* Owner window doesn't want it */
-         if (p_grab_window != NULL && p_grab_owner_events)
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Pointer is grabbed wíth owner_events TRUE */ 
-             GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
-             mask = p_grab_event_mask;
-             if (!(mask & GDK_BUTTON_PRESS_MASK))
-               /* Grabber doesn't want it either */
-               break;
+             /* No parent; check if grabbed */
+             if (p_grab_window != NULL)
+               {
+                 /* Pointer is grabbed wíth owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 mask = p_grab_mask;
+                 if (!(mask & GDK_BUTTON_PRESS_MASK))
+                   {
+                     /* Grabber doesn't want it either */
+                     GDK_NOTE (EVENTS, g_print ("...grabber uninterested\n"));
+                     break;
+                   }
+                 else
+                   event->button.window = p_grab_window;
+                 GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
+                                            GDK_DRAWABLE_XID (p_grab_window)));
+               }
              else
-               event->button.window = p_grab_window;
-             GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
-                                        GDK_DRAWABLE_XID (p_grab_window)));
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             /* Yes, this code is duplicated twice below. So shoot me. */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               break;
-             pt.x = LOWORD (xevent->lParam);
-             pt.y = HIWORD (xevent->lParam);
-             ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
-             xevent->lParam = MAKELPARAM (pt.x, pt.y);
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = mouse_propagate (window, xevent);
+             /* Jump back up */
              goto buttondown; /* What did Dijkstra say? */
            }
        }
+      else
+       event->button.window = window;
 
+      g_assert (event->button.window == window);
+#endif
       /* Emulate X11's automatic active grab */
       if (!p_grab_window)
        {
          /* No explicit active grab, let's start one automatically */
+         gint owner_events =
+           WINDOW_PRIVATE(window)->event_mask
+           & (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);
+         
          GDK_NOTE (EVENTS, g_print ("...automatic grab started\n"));
-         gdk_pointer_grab (window, TRUE, window_private->event_mask,
+         gdk_pointer_grab (window,
+                           owner_events,
+                           WINDOW_PRIVATE(window)->event_mask,
                            NULL, NULL, 0);
          p_grab_automatic = TRUE;
        }
 
       event->button.time = xevent->time;
-      event->button.x = LOWORD (xevent->lParam);
-      event->button.y = HIWORD (xevent->lParam);
-      event->button.x_root = (gfloat)xevent->pt.x;
-      event->button.y_root = (gfloat)xevent->pt.y;
+      if (window == p_grab_window
+         && p_grab_window != orig_window)
+       {
+         /* Translate coordinates to grabber */
+         pt.x = LOWORD (xevent->lParam);
+         pt.y = HIWORD (xevent->lParam);
+         ClientToScreen (xevent->hwnd, &pt);
+         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
+         event->button.x = pt.x;
+         event->button.y = pt.y;
+         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
+       }
+      else
+       {
+         event->button.x = LOWORD (xevent->lParam);
+         event->button.y = HIWORD (xevent->lParam);
+       }
+      event->button.x_root = xevent->pt.x;
+      event->button.y_root = xevent->pt.y;
       event->button.pressure = 0.5;
       event->button.xtilt = 0;
       event->button.ytilt = 0;
@@ -1943,21 +4084,7 @@ gdk_event_translate (GdkEvent *event,
          button_number[1] = -1;
          button_number[0] = event->button.button;
        }
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      if (return_val
-         && p_grab_window != NULL
-         && event->any.window == p_grab_window
-         && p_grab_window != window)
-       {
-         /* Translate coordinates to grabber */
-         pt.x = event->button.x;
-         pt.y = event->button.y;
-         ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
-         event->button.x = pt.x;
-         event->button.y = pt.y;
-         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
-       }
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
     case WM_LBUTTONUP:
@@ -1977,8 +4104,7 @@ gdk_event_translate (GdkEvent *event,
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam),
                         button));
 
-      if (window_private
-         && (window_private->extension_events != 0)
+      if (WINDOW_PRIVATE(window)->extension_events != 0
          && gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print ("...ignored\n"));
@@ -1989,70 +4115,89 @@ gdk_event_translate (GdkEvent *event,
        synthesize_crossing_events (window, xevent);
 
       event->button.type = GDK_BUTTON_RELEASE;
-    buttonup:
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     p_grab_window, p_grab_owner_events, p_grab_mask,
+                     doesnt_want_button_release,
+                     mouse_propagate))
+         break;
       event->button.window = window;
-      if (window_private)
-       mask = window_private->event_mask;
-      else
-       mask = 0;
+#else
+    buttonup:
+      mask = WINDOW_PRIVATE(window)->event_mask;
 
       if (p_grab_window != NULL && !p_grab_owner_events)
        {
          /* Pointer is grabbed with owner_events FALSE */
          GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
-         mask = p_grab_event_mask;
+
+         mask = p_grab_mask;
          if (!(mask & GDK_BUTTON_RELEASE_MASK))
            /* Grabber doesn't want it */
-           break;
+           goto maybe_ungrab;
          else
            event->button.window = p_grab_window;
          GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
                                     GDK_DRAWABLE_XID (p_grab_window)));
        }
-      else if (window_private
-              && !(mask & GDK_BUTTON_RELEASE_MASK))
+      else if (!(mask & GDK_BUTTON_RELEASE_MASK))
        {
-         /* Owner window doesn't want it */
-         if (p_grab_window != NULL && p_grab_owner_events)
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Pointer is grabbed wíth owner_events TRUE */
-             GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
-             mask = p_grab_event_mask;
-             if (!(mask & GDK_BUTTON_RELEASE_MASK))
-               /* Grabber doesn't want it */
-               break;
+             /* No parent; check if grabbed */
+             if (p_grab_window != NULL)
+               {
+                 /* Pointer is grabbed wíth owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 mask = p_grab_mask;
+                 if (!(mask & GDK_BUTTON_RELEASE_MASK))
+                   {
+                     /* Grabber doesn't want it either */
+                     GDK_NOTE (EVENTS, g_print ("...grabber uninterested\n"));
+                     goto maybe_ungrab;
+                   }
+                 else
+                   event->button.window = p_grab_window;
+                 GDK_NOTE (EVENTS,
+                           g_print ("...sending to %#x\n",
+                                    GDK_DRAWABLE_XID (p_grab_window)));
+               }
              else
-               event->button.window = p_grab_window;
-             GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
-                                        GDK_DRAWABLE_XID (p_grab_window)));
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               break;
-             pt.x = LOWORD (xevent->lParam);
-             pt.y = HIWORD (xevent->lParam);
-             ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
-             xevent->lParam = MAKELPARAM (pt.x, pt.y);
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = mouse_propagate (window, xevent);
+             /* Jump back up */
              goto buttonup;
            }
        }
+      else
+       event->button.window = window;
 
+      g_assert (event->button.window == window);
+#endif
       event->button.time = xevent->time;
-      event->button.x = LOWORD (xevent->lParam);
-      event->button.y = HIWORD (xevent->lParam);
-      event->button.x_root = (gfloat)xevent->pt.x;
-      event->button.y_root = (gfloat)xevent->pt.y;
+      if (window == p_grab_window
+         && p_grab_window != orig_window)
+       {
+         /* Translate coordinates to grabber */
+         pt.x = LOWORD (xevent->lParam);
+         pt.y = HIWORD (xevent->lParam);
+         ClientToScreen (xevent->hwnd, &pt);
+         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
+         event->button.x = pt.x;
+         event->button.y = pt.y;
+         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
+       }
+      else
+       {
+         event->button.x = LOWORD (xevent->lParam);
+         event->button.y = HIWORD (xevent->lParam);
+       }
+      event->button.x_root = xevent->pt.x;
+      event->button.y_root = xevent->pt.y;
       event->button.pressure = 0.5;
       event->button.xtilt = 0;
       event->button.ytilt = 0;
@@ -2067,24 +4212,17 @@ gdk_event_translate (GdkEvent *event,
        event->button.state |= GDK_BUTTON3_MASK;
       if (xevent->wParam & MK_SHIFT)
        event->button.state |= GDK_SHIFT_MASK;
+      if (GetKeyState (VK_MENU) < 0)
+       event->button.state |= GDK_MOD1_MASK;
+      if (GetKeyState (VK_CAPITAL) & 0x1)
+       event->button.state |= GDK_LOCK_MASK;
       event->button.button = button;
       event->button.source = GDK_SOURCE_MOUSE;
       event->button.deviceid = GDK_CORE_POINTER;
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      if (return_val
-         && p_grab_window != NULL
-         && event->any.window == p_grab_window
-         && p_grab_window != window)
-       {
-         /* Translate coordinates to grabber */
-         pt.x = event->button.x;
-         pt.y = event->button.y;
-         ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
-         event->button.x = pt.x;
-         event->button.y = pt.y;
-         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
-       }
+
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
+
+    maybe_ungrab:
       if (p_grab_window != NULL
          && p_grab_automatic
          && (event->button.state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK)) == 0)
@@ -2097,58 +4235,41 @@ gdk_event_translate (GdkEvent *event,
                         xevent->hwnd, xevent->wParam,
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
 
-#if 0
-      /* Try hard not to generate events for windows that shouldn't
-        get any.  This is hard because we don't want pushbuttons to
-        highlight when the cursor moves over them if the window is
-        inactive. We dont want tooltips windows to be active. OTOH,
-        also menus are popup windows, but they definitely should
-        get events. Aw shit. Skip this.
-       */
-      dwStyle = GetWindowLong (xevent->hwnd, GWL_STYLE);
-      if (active == NULL ||
-         !(active == xevent->hwnd
-           || (dwStyle & WS_POPUP)
-           || IsChild (active, xevent->hwnd)))
+      /* HB: only process mouse move messages if we own the active window. */
+
+      GetWindowThreadProcessId(GetActiveWindow(), &pidActWin);
+      GetWindowThreadProcessId(xevent->hwnd, &pidThis);
+      if (pidActWin != pidThis)
        break;
-#else
-      { /* HB: only process mouse move messages
-         * if we own the active window.
-         */
-         DWORD ProcessID_ActWin;
-         DWORD ProcessID_this;
-
-         GetWindowThreadProcessId(GetActiveWindow(), &ProcessID_ActWin);
-         GetWindowThreadProcessId(xevent->hwnd, &ProcessID_this);
-         if (ProcessID_ActWin != ProcessID_this)
-          break;
-     }
-#endif
+
       if (window != curWnd)
        synthesize_crossing_events (window, xevent);
 
-      if (window_private
-         && (window_private->extension_events != 0)
+      if (WINDOW_PRIVATE(window)->extension_events != 0
          && gdk_input_ignore_core)
        {
          GDK_NOTE (EVENTS, g_print ("...ignored\n"));
          break;
        }
 
-    mousemotion:
       event->motion.type = GDK_MOTION_NOTIFY;
+#ifdef NEW_PROPAGATION_CODE
+      if (!propagate (&window, xevent,
+                     p_grab_window, p_grab_owner_events, p_grab_mask,
+                     doesnt_want_button_motion,
+                     mouse_propagate))
+         break;
       event->motion.window = window;
-      if (window_private)
-       mask = window_private->event_mask;
-      else
-       mask = 0;
+#else
+    mousemotion:
+      mask = WINDOW_PRIVATE(window)->event_mask;
 
-      if (p_grab_window && !p_grab_owner_events)
+      if (p_grab_window != NULL && !p_grab_owner_events)
        {
          /* Pointer is grabbed with owner_events FALSE */
-         GDK_NOTE (EVENTS,
-                   g_print ("...grabbed, owner_events FALSE\n"));
-         mask = p_grab_event_mask;
+         GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events FALSE\n"));
+
+         mask = p_grab_mask;
          if (!((mask & GDK_POINTER_MOTION_MASK)
                || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
                    && (mask & GDK_BUTTON_MOTION_MASK))
@@ -2158,70 +4279,83 @@ gdk_event_translate (GdkEvent *event,
                    && (mask & GDK_BUTTON2_MOTION_MASK))
                || ((xevent->wParam & MK_RBUTTON)
                    && (mask & GDK_BUTTON3_MOTION_MASK))))
+           /* Grabber doesn't want it */
            break;
          else
            event->motion.window = p_grab_window;
          GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
                                     GDK_DRAWABLE_XID (p_grab_window)));
        }
-      else if (window_private
-              && !((mask & GDK_POINTER_MOTION_MASK)
-                   || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
-                       && (mask & GDK_BUTTON_MOTION_MASK))
-                   || ((xevent->wParam & MK_LBUTTON)
-                       && (mask & GDK_BUTTON1_MOTION_MASK))
-                   || ((xevent->wParam & MK_MBUTTON)
-                       && (mask & GDK_BUTTON2_MOTION_MASK))
-                   || ((xevent->wParam & MK_RBUTTON)
-                       && (mask & GDK_BUTTON3_MOTION_MASK))))
-       {
-         /* Owner window doesn't want it */
-         if (p_grab_window != NULL && p_grab_owner_events)
+      else if (!((mask & GDK_POINTER_MOTION_MASK)
+                || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
+                    && (mask & GDK_BUTTON_MOTION_MASK))
+                || ((xevent->wParam & MK_LBUTTON)
+                    && (mask & GDK_BUTTON1_MOTION_MASK))
+                || ((xevent->wParam & MK_MBUTTON)
+                    && (mask & GDK_BUTTON2_MOTION_MASK))
+                || ((xevent->wParam & MK_RBUTTON)
+                    && (mask & GDK_BUTTON3_MOTION_MASK))))
+       {
+         /* Owner doesn't want it, propagate to parent. */
+         if (WINDOW_PRIVATE(window)->parent == (GdkWindow *) gdk_root_parent)
            {
-             /* Pointer is grabbed wíth owner_events TRUE */
-             GDK_NOTE (EVENTS, g_print ("...grabbed, owner_events TRUE, doesn't want it\n"));
-             mask = p_grab_event_mask;
-             if (!((p_grab_event_mask & GDK_POINTER_MOTION_MASK)
-                   || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
-                       && (mask & GDK_BUTTON_MOTION_MASK))
-                   || ((xevent->wParam & MK_LBUTTON)
-                       && (mask & GDK_BUTTON1_MOTION_MASK))
-                   || ((xevent->wParam & MK_MBUTTON)
-                       && (mask & GDK_BUTTON2_MOTION_MASK))
-                   || ((xevent->wParam & MK_RBUTTON)
-                       && (mask & GDK_BUTTON3_MOTION_MASK))))
-               /* Grabber doesn't want it either */
-               break;
+             /* No parent; check if grabbed */
+             if (p_grab_window != NULL)
+               {
+                 /* Pointer is grabbed wíth owner_events TRUE */
+                 GDK_NOTE (EVENTS, g_print ("...undelivered, but grabbed\n"));
+                 mask = p_grab_mask;
+                 if (!((p_grab_mask & GDK_POINTER_MOTION_MASK)
+                       || ((xevent->wParam & (MK_LBUTTON|MK_MBUTTON|MK_RBUTTON))
+                           && (mask & GDK_BUTTON_MOTION_MASK))
+                       || ((xevent->wParam & MK_LBUTTON)
+                           && (mask & GDK_BUTTON1_MOTION_MASK))
+                       || ((xevent->wParam & MK_MBUTTON)
+                           && (mask & GDK_BUTTON2_MOTION_MASK))
+                       || ((xevent->wParam & MK_RBUTTON)
+                           && (mask & GDK_BUTTON3_MOTION_MASK))))
+                   {
+                     /* Grabber doesn't want it either */
+                     GDK_NOTE (EVENTS, g_print ("...grabber uninterested\n"));
+                     break;
+                   }
+                 else
+                   event->motion.window = p_grab_window;
+                 GDK_NOTE (EVENTS,
+                           g_print ("...sending to %#x\n",
+                                    GDK_DRAWABLE_XID (p_grab_window)));
+               }
              else
-               event->motion.window = p_grab_window;
-             GDK_NOTE (EVENTS, g_print ("...sending to %#x\n",
-                                        GDK_DRAWABLE_XID (p_grab_window)));
+               break;
            }
          else
            {
-             /* Owner doesn't want it, neither is it grabbed, so
-              * propagate to parent.
-              */
-             if (window_private->parent == (GdkWindow *) &gdk_root_parent)
-               break;
-             pt.x = LOWORD (xevent->lParam);
-             pt.y = HIWORD (xevent->lParam);
-             ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-             gdk_window_unref (window);
-             window = window_private->parent;
-             gdk_window_ref (window);
-             window_private = (GdkWindowPrivate *) window;
-             ScreenToClient (GDK_DRAWABLE_XID (window), &pt);
-             xevent->lParam = MAKELPARAM (pt.x, pt.y);
-             GDK_NOTE (EVENTS, g_print ("...propagating to %#x\n",
-                                        GDK_DRAWABLE_XID (window)));
+             window = mouse_propagate (window, xevent);
+             /* Jump back up */
              goto mousemotion;
            }
        }
-
+      else
+       event->motion.window = window;
+#endif
       event->motion.time = xevent->time;
-      event->motion.x = curX = LOWORD (xevent->lParam);
-      event->motion.y = curY = HIWORD (xevent->lParam);
+      if (window == p_grab_window
+         && p_grab_window != orig_window)
+       {
+         /* Translate coordinates to grabber */
+         pt.x = curX = LOWORD (xevent->lParam);
+         pt.y = curY = HIWORD (xevent->lParam);
+         ClientToScreen (xevent->hwnd, &pt);
+         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
+         event->motion.x = pt.x;
+         event->motion.y = pt.y;
+         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
+       }
+      else
+       {
+         event->motion.x = curX = LOWORD (xevent->lParam);
+         event->motion.y = curY = HIWORD (xevent->lParam);
+       }
       event->motion.x_root = xevent->pt.x;
       event->motion.y_root = xevent->pt.y;
       curXroot = event->motion.x_root;
@@ -2240,6 +4374,10 @@ gdk_event_translate (GdkEvent *event,
        event->button.state |= GDK_BUTTON3_MASK;
       if (xevent->wParam & MK_SHIFT)
        event->button.state |= GDK_SHIFT_MASK;
+      if (GetKeyState (VK_MENU) < 0)
+       event->button.state |= GDK_MOD1_MASK;
+      if (GetKeyState (VK_CAPITAL) & 0x1)
+       event->button.state |= GDK_LOCK_MASK;
       if (mask & GDK_POINTER_MOTION_HINT_MASK)
        event->motion.is_hint = NotifyHint;
       else
@@ -2247,21 +4385,7 @@ gdk_event_translate (GdkEvent *event,
       event->motion.source = GDK_SOURCE_MOUSE;
       event->motion.deviceid = GDK_CORE_POINTER;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      if (return_val
-         && p_grab_window != NULL
-         && event->any.window == p_grab_window
-         && p_grab_window != window)
-       {
-         /* Translate coordinates to grabber */
-         pt.x = event->motion.x;
-         pt.y = event->motion.y;
-         ClientToScreen (GDK_DRAWABLE_XID (window), &pt);
-         ScreenToClient (GDK_DRAWABLE_XID (p_grab_window), &pt);
-         event->motion.x = pt.x;
-         event->motion.y = pt.y;
-         GDK_NOTE (EVENTS, g_print ("...new coords are +%d+%d\n", pt.x, pt.y));
-       }
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
     case WM_NCMOUSEMOVE:
@@ -2269,13 +4393,9 @@ gdk_event_translate (GdkEvent *event,
                g_print ("WM_NCMOUSEMOVE: %#x  x,y: %d %d\n",
                         xevent->hwnd,
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
-#if 0
-      if (active == NULL || active != xevent->hwnd)
-       break;
-#endif
-      curWnd_private = (GdkWindowPrivate *) curWnd;
-      if (curWnd != NULL
-         && (curWnd_private->event_mask & GDK_LEAVE_NOTIFY_MASK))
+      if (p_TrackMouseEvent == NULL
+         && curWnd != NULL
+         && (WINDOW_PRIVATE(curWnd)->event_mask & GDK_LEAVE_NOTIFY_MASK))
        {
          GDK_NOTE (EVENTS, g_print ("...synthesizing LEAVE_NOTIFY event\n"));
 
@@ -2288,49 +4408,83 @@ gdk_event_translate (GdkEvent *event,
          event->crossing.x_root = curXroot;
          event->crossing.y_root = curYroot;
          event->crossing.mode = GDK_CROSSING_NORMAL;
-         event->crossing.detail = GDK_NOTIFY_UNKNOWN;
+         event->crossing.detail = GDK_NOTIFY_NONLINEAR;
 
          event->crossing.focus = TRUE; /* ??? */
          event->crossing.state = 0; /* ??? */
+         return_val = TRUE;
+       }
+
+      if (curWnd)
+       {
          gdk_window_unref (curWnd);
          curWnd = NULL;
-
-         return_val = TRUE;
        }
+
       break;
 
-    case WM_SETFOCUS:
-    case WM_KILLFOCUS:
-      if (window_private
-         && !(window_private->event_mask & GDK_FOCUS_CHANGE_MASK))
+#ifdef USE_TRACKMOUSEEVENT
+    case WM_MOUSELEAVE:
+      GDK_NOTE (EVENTS, g_print ("WM_MOUSELEAVE: %#x\n", xevent->hwnd));
+
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
        break;
 
+      event->crossing.type = GDK_LEAVE_NOTIFY;
+      event->crossing.window = window;
+      event->crossing.subwindow = NULL;
+      event->crossing.time = xevent->time;
+      event->crossing.x = curX;
+      event->crossing.y = curY;
+      event->crossing.x_root = curXroot;
+      event->crossing.y_root = curYroot;
+      event->crossing.mode = GDK_CROSSING_NORMAL;
+      if (curWnd
+         && IsChild (GDK_DRAWABLE_XID (curWnd), GDK_DRAWABLE_XID (window)))
+       event->crossing.detail = GDK_NOTIFY_INFERIOR;
+      else if (curWnd
+              && IsChild (GDK_DRAWABLE_XID (window), GDK_DRAWABLE_XID (curWnd)))
+       event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+      else
+       event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+
+      event->crossing.focus = TRUE; /* ??? */
+      event->crossing.state = 0; /* ??? */
+
+      if (curWnd)
+       {
+         gdk_window_unref (curWnd);
+         curWnd = NULL;
+       }
+
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
+      break;
+#endif
+       
+    case WM_SETFOCUS:
+    case WM_KILLFOCUS:
       GDK_NOTE (EVENTS, g_print ("WM_%sFOCUS: %#x\n",
-                                (xevent->message == WM_SETFOCUS ? "SET" : "KILL"),
+                                (xevent->message == WM_SETFOCUS ?
+                                 "SET" : "KILL"),
                                 xevent->hwnd));
       
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_FOCUS_CHANGE_MASK))
+       break;
+
       event->focus_change.type = GDK_FOCUS_CHANGE;
       event->focus_change.window = window;
       event->focus_change.in = (xevent->message == WM_SETFOCUS);
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
-      break;
-#if 0
-    case WM_ACTIVATE:
-      GDK_NOTE (EVENTS, g_print ("WM_ACTIVATE: %#x  %d\n",
-                                xevent->hwnd, LOWORD (xevent->wParam)));
-      if (LOWORD (xevent->wParam) == WA_INACTIVE)
-       active = (HWND) xevent->lParam;
-      else
-       active = xevent->hwnd;
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
-#endif
+
     case WM_ERASEBKGND:
       GDK_NOTE (EVENTS, g_print ("WM_ERASEBKGND: %#x  dc %#x\n",
                                 xevent->hwnd, xevent->wParam));
       
-      if (!window_private || GDK_DRAWABLE_DESTROYED (window))
+      if (GDK_DRAWABLE_DESTROYED (window))
        break;
-      colormap_private = (GdkColormapPrivate *) window_private->drawable.colormap;
+
+      colormap_private = (GdkColormapPrivate *) WINDOW_PRIVATE(window)->drawable.colormap;
       hdc = (HDC) xevent->wParam;
       if (colormap_private
          && colormap_private->xcolormap->rc_palette)
@@ -2350,32 +4504,38 @@ gdk_event_translate (GdkEvent *event,
       *ret_val_flagp = TRUE;
       *ret_valp = 1;
 
-      if (window_private->bg_type == GDK_WIN32_BG_TRANSPARENT)
+      if (WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_TRANSPARENT)
        break;
 
-      if (window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
+      if (WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
        {
          /* If this window should have the same background as the
           * parent, fetch the parent. (And if the same goes for
           * the parent, fetch the grandparent, etc.)
           */
-         while (window_private
-                && window_private->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
-           window_private = (GdkWindowPrivate *) window_private->parent;
+         while (window
+                && WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_PARENT_RELATIVE)
+           {
+             gdk_window_unref (window);
+             window = WINDOW_PRIVATE(window)->parent;
+             gdk_window_ref (window);
+           }
        }
 
-      if (window_private->bg_type == GDK_WIN32_BG_PIXEL)
+      if (WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_PIXEL)
        {
          COLORREF bg;
          GetClipBox (hdc, &rect);
-         GDK_NOTE (EVENTS, g_print ("...%dx%d@+%d+%d BG_PIXEL %s\n",
-                                    rect.right - rect.left,
-                                    rect.bottom - rect.top,
-                                    rect.left, rect.top,
-                                    gdk_color_to_string (&window_private->bg_pixel)));
-         bg = GetNearestColor (hdc, RGB (window_private->bg_pixel.red >> 8,
-                                         window_private->bg_pixel.green >> 8,
-                                         window_private->bg_pixel.blue >> 8));
+         GDK_NOTE (EVENTS,
+                   g_print ("...%dx%d@+%d+%d BG_PIXEL %s\n",
+                            rect.right - rect.left,
+                            rect.bottom - rect.top,
+                            rect.left, rect.top,
+                            gdk_color_to_string (&WINDOW_PRIVATE(window)->bg_pixel)));
+         bg = GetNearestColor
+           (hdc, RGB (WINDOW_PRIVATE(window)->bg_pixel.red >> 8,
+                      WINDOW_PRIVATE(window)->bg_pixel.green >> 8,
+                      WINDOW_PRIVATE(window)->bg_pixel.blue >> 8));
          hbr = CreateSolidBrush (bg);
 #if 0
          g_print ("...CreateSolidBrush (%.08x) = %.08x\n", bg, hbr);
@@ -2384,9 +4544,10 @@ gdk_event_translate (GdkEvent *event,
            g_warning ("WM_ERASEBKGND: FillRect failed");
          DeleteObject (hbr);
        }
-      else if (window_private->bg_type == GDK_WIN32_BG_PIXMAP)
+      else if (WINDOW_PRIVATE(window)->bg_type == GDK_WIN32_BG_PIXMAP)
        {
-         pixmap_private = (GdkDrawablePrivate*) window_private->bg_pixmap;
+         pixmap_private =
+           (GdkDrawablePrivate*) WINDOW_PRIVATE(window)->bg_pixmap;
          GetClipBox (hdc, &rect);
 
          if (pixmap_private->width <= 8
@@ -2470,8 +4631,7 @@ gdk_event_translate (GdkEvent *event,
 
       EndPaint (xevent->hwnd, &paintstruct);
 
-      if (window_private
-         && !(window_private->event_mask & GDK_EXPOSURE_MASK))
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_EXPOSURE_MASK))
        break;
 
       event->expose.type = GDK_EXPOSE;
@@ -2482,7 +4642,7 @@ gdk_event_translate (GdkEvent *event,
       event->expose.area.height = paintstruct.rcPaint.bottom - paintstruct.rcPaint.top;
       event->expose.count = 0;
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       if (return_val)
        {
          GList *list = queued_events;
@@ -2503,7 +4663,6 @@ gdk_event_translate (GdkEvent *event,
                                 xevent->hwnd,
                                 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
 
-      return_val = FALSE;
       if (LOWORD (xevent->lParam) != HTCLIENT)
        break;
       if (p_grab_window != NULL && p_grab_cursor != NULL)
@@ -2511,44 +4670,27 @@ gdk_event_translate (GdkEvent *event,
          GDK_NOTE (EVENTS, g_print ("...SetCursor(%#x)\n", p_grab_cursor));
          SetCursor (p_grab_cursor);
        }
-      else if (window_private
-              && !GDK_DRAWABLE_DESTROYED (window)
-              && window_private->xcursor)
+      else if (!GDK_DRAWABLE_DESTROYED (window)
+              && WINDOW_PRIVATE(window)->xcursor)
        {
          GDK_NOTE (EVENTS, g_print ("...SetCursor(%#x)\n",
-                                    window_private->xcursor));
-         SetCursor (window_private->xcursor);
+                                    WINDOW_PRIVATE(window)->xcursor));
+         SetCursor (WINDOW_PRIVATE(window)->xcursor);
        }
-      *ret_val_flagp = TRUE;
-      *ret_valp = FALSE;
-      break;
 
-#if 0
-    case WM_QUERYOPEN:
-      GDK_NOTE (EVENTS, g_print ("WM_QUERYOPEN: %#x\n",
-                                xevent->hwnd));
-      *ret_val_flagp = TRUE;
-      *ret_valp = TRUE;
-
-      if (window_private
-         && !(window_private->event_mask & GDK_STRUCTURE_MASK))
-       break;
-
-      event->any.type = GDK_MAP;
-      event->any.window = window;
+      if (window != curWnd)
+       synthesize_crossing_events (window, xevent);
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      *ret_val_flagp = TRUE;
+      *ret_valp = FALSE;
       break;
-#endif
 
-#if 1
     case WM_SHOWWINDOW:
       GDK_NOTE (EVENTS, g_print ("WM_SHOWWINDOW: %#x  %d\n",
                                 xevent->hwnd,
                                 xevent->wParam));
 
-      if (window_private
-         && !(window_private->event_mask & GDK_STRUCTURE_MASK))
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_STRUCTURE_MASK))
        break;
 
       event->any.type = (xevent->wParam ? GDK_MAP : GDK_UNMAP);
@@ -2562,9 +4704,9 @@ gdk_event_translate (GdkEvent *event,
          && k_grab_window == window)
        gdk_keyboard_ungrab (xevent->time);
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
-#endif
+
     case WM_SIZE:
       GDK_NOTE (EVENTS,
                g_print ("WM_SIZE: %#x  %s %dx%d\n",
@@ -2576,13 +4718,11 @@ gdk_event_translate (GdkEvent *event,
                             (xevent->wParam == SIZE_RESTORED ? "RESTORED" : "?"))))),
                         LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
 
-      if (window_private
-         && !(window_private->event_mask & GDK_STRUCTURE_MASK))
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_STRUCTURE_MASK))
        break;
-      if (window_private != NULL
-         && xevent->wParam == SIZE_MINIMIZED)
+
+      if (xevent->wParam == SIZE_MINIMIZED)
        {
-#if 1
          event->any.type = GDK_UNMAP;
          event->any.window = window;
 
@@ -2593,11 +4733,9 @@ gdk_event_translate (GdkEvent *event,
            gdk_keyboard_ungrab (xevent->time);
 
          return_val = !GDK_DRAWABLE_DESTROYED (window);
-#endif
        }
-      else if (window_private != NULL
-              && (xevent->wParam == SIZE_RESTORED
-                  || xevent->wParam == SIZE_MAXIMIZED)
+      else if ((xevent->wParam == SIZE_RESTORED
+               || xevent->wParam == SIZE_MAXIMIZED)
 #if 1
               && GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_CHILD
 #endif
@@ -2615,121 +4753,49 @@ gdk_event_translate (GdkEvent *event,
          event->configure.y = pt.y;
          event->configure.width = LOWORD (xevent->lParam);
          event->configure.height = HIWORD (xevent->lParam);
-         window_private->x = event->configure.x;
-         window_private->y = event->configure.y;
-         window_private->drawable.width = event->configure.width;
-         window_private->drawable.height = event->configure.height;
-         if (window_private->resize_count > 1)
-           window_private->resize_count -= 1;
+         WINDOW_PRIVATE(window)->x = event->configure.x;
+         WINDOW_PRIVATE(window)->y = event->configure.y;
+         WINDOW_PRIVATE(window)->drawable.width = event->configure.width;
+         WINDOW_PRIVATE(window)->drawable.height = event->configure.height;
+         if (WINDOW_PRIVATE(window)->resize_count > 1)
+           WINDOW_PRIVATE(window)->resize_count -= 1;
          
          return_val = !GDK_DRAWABLE_DESTROYED (window);
          if (return_val
-             && window_private->extension_events != 0
+             && WINDOW_PRIVATE(window)->extension_events != 0
              && gdk_input_vtable.configure_event)
            gdk_input_vtable.configure_event (&event->configure, window);
        }
       break;
-#if 0 /* Bernd Herd suggests responding to WM_GETMINMAXINFO instead,
-       * which indeed is much easier.
-       */
-    case WM_SIZING:
-      GDK_NOTE (EVENTS, g_print ("WM_SIZING: %#x\n", xevent->hwnd));
-      if (ret_val_flagp == NULL)
-         g_warning ("ret_val_flagp is NULL but we got a WM_SIZING?");
-      else if (window_private != NULL
-              && window_private->hint_flags &
-              (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE))
-       {
-         LPRECT lprc = (LPRECT) xevent->lParam;
 
-         if (window_private->hint_flags & GDK_HINT_MIN_SIZE)
-           {
-             gint w = lprc->right - lprc->left;
-             gint h = lprc->bottom - lprc->top;
-
-             if (w < window_private->hint_min_width)
-               {
-                 if (xevent->wParam == WMSZ_BOTTOMLEFT
-                     || xevent->wParam == WMSZ_LEFT
-                     || xevent->wParam == WMSZ_TOPLEFT)
-                   lprc->left = lprc->right - window_private->hint_min_width;
-                 else
-                   lprc->right = lprc->left + window_private->hint_min_width;
-                 *ret_val_flagp = TRUE;
-                 *ret_valp = TRUE;
-               }
-             if (h < window_private->hint_min_height)
-               {
-                 if (xevent->wParam == WMSZ_BOTTOMLEFT
-                     || xevent->wParam == WMSZ_BOTTOM
-                     || xevent->wParam == WMSZ_BOTTOMRIGHT)
-                   lprc->bottom = lprc->top + window_private->hint_min_height;
-                 else
-                   lprc->top = lprc->bottom - window_private->hint_min_height;
-                 *ret_val_flagp = TRUE;
-                 *ret_valp = TRUE;
-               }
-           }
-         if (window_private->hint_flags & GDK_HINT_MAX_SIZE)
-           {
-             gint w = lprc->right - lprc->left;
-             gint h = lprc->bottom - lprc->top;
-
-             if (w > window_private->hint_max_width)
-               {
-                 if (xevent->wParam == WMSZ_BOTTOMLEFT
-                     || xevent->wParam == WMSZ_LEFT
-                     || xevent->wParam == WMSZ_TOPLEFT)
-                   lprc->left = lprc->right - window_private->hint_max_width;
-                 else
-                   lprc->right = lprc->left + window_private->hint_max_width;
-                 *ret_val_flagp = TRUE;
-                 *ret_valp = TRUE;
-               }
-             if (h > window_private->hint_max_height)
-               {
-                 if (xevent->wParam == WMSZ_BOTTOMLEFT
-                     || xevent->wParam == WMSZ_BOTTOM
-                     || xevent->wParam == WMSZ_BOTTOMRIGHT)
-                   lprc->bottom = lprc->top + window_private->hint_max_height;
-                 else
-                   lprc->top = lprc->bottom - window_private->hint_max_height;
-                 *ret_val_flagp = TRUE;
-                 *ret_valp = TRUE;
-               }
-           }
-       }
-      break;
-#else
     case WM_GETMINMAXINFO:
       GDK_NOTE (EVENTS, g_print ("WM_GETMINMAXINFO: %#x\n", xevent->hwnd));
+
       lpmmi = (MINMAXINFO*) xevent->lParam;
-      if (window_private->hint_flags & GDK_HINT_MIN_SIZE)
+      if (WINDOW_PRIVATE(window)->hint_flags & GDK_HINT_MIN_SIZE)
        {
-         lpmmi->ptMinTrackSize.x = window_private->hint_min_width;
-         lpmmi->ptMinTrackSize.y = window_private->hint_min_height;
+         lpmmi->ptMinTrackSize.x = WINDOW_PRIVATE(window)->hint_min_width;
+         lpmmi->ptMinTrackSize.y = WINDOW_PRIVATE(window)->hint_min_height;
        }
-      if (window_private->hint_flags & GDK_HINT_MAX_SIZE)
+      if (WINDOW_PRIVATE(window)->hint_flags & GDK_HINT_MAX_SIZE)
        {
-         lpmmi->ptMaxTrackSize.x = window_private->hint_max_width;
-         lpmmi->ptMaxTrackSize.y = window_private->hint_max_height;
+         lpmmi->ptMaxTrackSize.x = WINDOW_PRIVATE(window)->hint_max_width;
+         lpmmi->ptMaxTrackSize.y = WINDOW_PRIVATE(window)->hint_max_height;
            
-         lpmmi->ptMaxSize.x = window_private->hint_max_width;
-         lpmmi->ptMaxSize.y = window_private->hint_max_height;
+         lpmmi->ptMaxSize.x = WINDOW_PRIVATE(window)->hint_max_width;
+         lpmmi->ptMaxSize.y = WINDOW_PRIVATE(window)->hint_max_height;
        }
       break;
-#endif
 
     case WM_MOVE:
       GDK_NOTE (EVENTS, g_print ("WM_MOVE: %#x  +%d+%d\n",
                                 xevent->hwnd,
                                 LOWORD (xevent->lParam), HIWORD (xevent->lParam)));
 
-      if (window_private
-         && !(window_private->event_mask & GDK_STRUCTURE_MASK))
+      if (!(WINDOW_PRIVATE(window)->event_mask & GDK_STRUCTURE_MASK))
        break;
-      if (window_private != NULL
-         && GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_CHILD)
+
+      if (GDK_DRAWABLE_TYPE (window) != GDK_WINDOW_CHILD)
        {
          event->configure.type = GDK_CONFIGURE;
          event->configure.window = window;
@@ -2738,10 +4804,10 @@ gdk_event_translate (GdkEvent *event,
          GetClientRect (xevent->hwnd, &rect);
          event->configure.width = rect.right;
          event->configure.height = rect.bottom;
-         window_private->x = event->configure.x;
-         window_private->y = event->configure.y;
-         window_private->drawable.width = event->configure.width;
-         window_private->drawable.height = event->configure.height;
+         WINDOW_PRIVATE(window)->x = event->configure.x;
+         WINDOW_PRIVATE(window)->y = event->configure.y;
+         WINDOW_PRIVATE(window)->drawable.width = event->configure.width;
+         WINDOW_PRIVATE(window)->drawable.height = event->configure.height;
          
          return_val = !GDK_DRAWABLE_DESTROYED (window);
        }
@@ -2749,10 +4815,11 @@ gdk_event_translate (GdkEvent *event,
 
     case WM_CLOSE:
       GDK_NOTE (EVENTS, g_print ("WM_CLOSE: %#x\n", xevent->hwnd));
+
       event->any.type = GDK_DELETE;
       event->any.window = window;
       
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
 #if 0
@@ -2795,7 +4862,7 @@ gdk_event_translate (GdkEvent *event,
       event->selection.property = gdk_selection_property;
       event->selection.requestor = (guint32) xevent->hwnd;
       event->selection.time = xevent->time;
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
 #else
       /* Test code, to see if SetClipboardData works when called from
        * the window procedure.
@@ -2817,6 +4884,7 @@ gdk_event_translate (GdkEvent *event,
 
     case WM_DESTROY:
       GDK_NOTE (EVENTS, g_print ("WM_DESTROY: %#x\n", xevent->hwnd));
+
       event->any.type = GDK_DESTROY;
       event->any.window = window;
       if (window != NULL && window == curWnd)
@@ -2831,7 +4899,7 @@ gdk_event_translate (GdkEvent *event,
       if (k_grab_window == window)
        gdk_keyboard_ungrab (xevent->time);
 
-      return_val = window_private && !GDK_DRAWABLE_DESTROYED (window);
+      return_val = !GDK_DRAWABLE_DESTROYED (window);
       break;
 
 #ifdef HAVE_WINTAB
@@ -2871,6 +4939,8 @@ bypass_switch:
           (event->any.type == GDK_LEAVE_NOTIFY)) &&
          (event->crossing.subwindow != NULL))
        gdk_window_ref (event->crossing.subwindow);
+
+      GDK_NOTE (EVENTS, print_event (event));
     }
   else
     {
@@ -2891,17 +4961,31 @@ gdk_events_queue (void)
   GList *node;
   GdkEvent *event;
   MSG msg;
-
-  GDK_NOTE (EVENTS, g_print ("gdk_events_queue: %s\n",
-                            (queued_events ? "yes" : "none")));
+  LRESULT lres;
 
   while (!gdk_event_queue_find_first()
         && PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
     {
-      GDK_NOTE (EVENTS, g_print ("gdk_events_queue:  PeekMessage: %#x\n",
-                                msg.message));
-      TranslateMessage (&msg);
+      GDK_NOTE (EVENTS, g_print ("PeekMessage: %#x %#x\n",
+                                msg.hwnd, msg.message));
 
+      if (paimmmpo == NULL
+         || (paimmmpo->lpVtbl->OnTranslateMessage) (paimmmpo, &msg) != S_OK)
+       TranslateMessage (&msg);
+
+#ifdef USE_DISPATCHMESSAGE
+      if (msg.message == g_pipe_readable_msg)
+       {
+         GDK_NOTE (EVENTS, g_print ("g_pipe_readable_msg: %d %d\n",
+                                    msg.wParam, msg.lParam));
+
+         g_io_channel_win32_pipe_readable (msg.wParam, msg.lParam);
+
+         continue;
+       }
+      
+      DispatchMessage (&msg);
+#else
       event = gdk_event_new ();
       
       event->any.type = GDK_NOTHING;
@@ -2914,14 +4998,20 @@ gdk_events_queue (void)
       node = queued_tail;
 
       if (gdk_event_translate (event, &msg, NULL, NULL))
-         ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+       ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
       else
        {
-         DefWindowProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
+         if (paimmapp == NULL
+             || (paimmapp->lpVtbl->OnDefWindowProc) (paimmapp, msg.hwnd,
+                                                     msg.message,
+                                                     msg.wParam, msg.lParam,
+                                                     &lres) == S_FALSE)
+           DefWindowProc (msg.hwnd, msg.message, msg.wParam, msg.lParam);
          gdk_event_queue_remove_link (node);
          g_list_free_1 (node);
          gdk_event_free (event);
        }
+#endif
     }
 }
 
@@ -2937,8 +5027,6 @@ gdk_event_prepare (gpointer  source_data,
 
   *timeout = -1;
 
-  GDK_NOTE (EVENTS, g_print ("gdk_event_prepare\n"));
-
   retval = (gdk_event_queue_find_first () != NULL)
              || PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
 
@@ -2954,8 +5042,6 @@ gdk_event_check (gpointer  source_data,
   MSG msg;
   gboolean retval;
   
-  GDK_NOTE (EVENTS, g_print ("gdk_event_check\n"));
-
   GDK_THREADS_ENTER ();
 
   if (event_poll_fd.revents & G_IO_IN)
@@ -2994,8 +5080,6 @@ gdk_event_dispatch (gpointer  source_data,
 {
   GdkEvent *event;
  
-  GDK_NOTE (EVENTS, g_print ("gdk_event_dispatch\n"));
-
   GDK_THREADS_ENTER ();
 
   gdk_events_queue();
index d28c1f77c0615491ab1ad52cb0eb032e83fc7d97..5c85d476a174e9fd520168631566f1d31811899b 100644 (file)
@@ -117,7 +117,8 @@ charset_name (DWORD charset)
 }
 
 GdkFont*
-gdk_font_load (const gchar *font_name)
+gdk_font_load_internal (GdkFontType  type,
+                       const gchar *font_name)
 {
   GdkFont *font;
   GdkFontPrivate *private;
@@ -142,9 +143,9 @@ gdk_font_load (const gchar *font_name)
 
   g_return_val_if_fail (font_name != NULL, NULL);
 
-  GDK_NOTE (MISC, g_print ("gdk_font_load: %s\n", font_name));
+  GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name));
 
-  font = gdk_font_hash_lookup (GDK_FONT_FONT, font_name);
+  font = gdk_font_hash_lookup (type, font_name);
   if (font)
     return font;
 
@@ -417,7 +418,6 @@ gdk_font_load (const gchar *font_name)
   private->xfont = hfont;
   private->ref_count = 1;
   private->names = NULL;
-  font->type = GDK_FONT_FONT;
   GetObject (private->xfont, sizeof (logfont), &logfont);
   oldfont = SelectObject (gdk_DC, private->xfont);
   GetTextMetrics (gdk_DC, &textmetric);
@@ -426,6 +426,7 @@ gdk_font_load (const gchar *font_name)
   TranslateCharsetInfo ((DWORD *) private->charset, &csi, TCI_SRCCHARSET);
   private->codepage = csi.ciACP;
   GetCPInfo (private->codepage, &private->cpinfo);
+  font->type = type;
   font->ascent = textmetric.tmAscent;
   font->descent = textmetric.tmDescent;
 
@@ -442,17 +443,21 @@ gdk_font_load (const gchar *font_name)
   *f = (HANDLE) ((guint) private->xfont + HFONT_DITHER);
   gdk_xid_table_insert (f, font);
 
-  gdk_font_hash_insert (GDK_FONT_FONT, font, font_name);
+  gdk_font_hash_insert (type, font, font_name);
 
   return font;
 }
 
 GdkFont*
-gdk_fontset_load (gchar *fontset_name)
+gdk_font_load (const gchar *font_name)
 {
-  g_warning ("gdk_fontset_load: Not implemented");
+  return gdk_font_load_internal (GDK_FONT_FONT, font_name);
+}
 
-  return NULL;
+GdkFont*
+gdk_fontset_load (gchar *fontset_name)
+{
+  return gdk_font_load_internal (GDK_FONT_FONTSET, fontset_name);
 }
 
 GdkFont*
@@ -493,6 +498,7 @@ gdk_font_unref (GdkFont *font)
       switch (font->type)
        {
        case GDK_FONT_FONT:
+       case GDK_FONT_FONTSET:  /* XXX */
          gdk_xid_table_remove ((HANDLE) ((guint) private->xfont + HFONT_DITHER));
          DeleteObject (private->xfont);
          break;
@@ -515,9 +521,8 @@ gdk_font_id (const GdkFont *font)
 
   if (font->type == GDK_FONT_FONT)
     return (gint) font_private->xfont;
-
-  g_assert_not_reached ();
-  return 0;
+  else
+    return 0;
 }
 
 gint
@@ -535,9 +540,10 @@ gdk_font_equal (const GdkFont *fonta,
 
   if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
     return (privatea->xfont == privateb->xfont);
-
-  g_assert_not_reached ();
-  return 0;
+  else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
+    return (privatea->xfont == privateb->xfont);
+  else
+    return 0;
 }
 
 gint
@@ -547,55 +553,59 @@ gdk_string_width (GdkFont     *font,
   return gdk_text_width (font, string, strlen (string));
 }
 
-gint
-gdk_text_width (GdkFont      *font,
-               const gchar  *text,
-               gint          text_length)
+static gboolean
+gdk_text_size (GdkFont      *font,
+              const gchar  *text,
+              gint          text_length,
+              SIZE          *sizep)
 {
   GdkFontPrivate *private;
   HGDIOBJ oldfont;
-  SIZE size;
-  gint width, wlen;
+  gint wlen;
   wchar_t *wcstr;
 
-  g_return_val_if_fail (font != NULL, -1);
-  g_return_val_if_fail (text != NULL, -1);
+  g_return_val_if_fail (font != NULL, FALSE);
+  g_return_val_if_fail (text != NULL, FALSE);
 
   if (text_length == 0)
     return 0;
 
   private = (GdkFontPrivate*) font;
 
-  switch (font->type)
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
+  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
     {
-    case GDK_FONT_FONT:
-      oldfont = SelectObject (gdk_DC, private->xfont);
-      if (private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (private->codepage, 0,
-                                          text, text_length,
-                                          wcstr, text_length)) == 0)
-           {
-             g_warning ("gdk_text_width: MultiByteToWideChar failed");
-             size.cx = 0;
-           }
-         else
-           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
-         g_free (wcstr);
-       }
-      else
-       {
-         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
-       }
-      SelectObject (gdk_DC, oldfont);
-      width = size.cx;
-      break;
+      g_warning ("gdk_text_width: SelectObject failed");
+      return FALSE;
+    }
 
-    default:
-      g_assert_not_reached ();
+  wcstr = g_new (wchar_t, text_length);
+  if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
+    {
+      g_warning ("gdk_text_size: gdk_nmbstowchar_ts failed");
+      return FALSE;
     }
-  return width;
+
+  GetTextExtentPoint32W (gdk_DC, wcstr, wlen, sizep);
+
+  g_free (wcstr);
+  SelectObject (gdk_DC, oldfont);
+
+  return TRUE;
+}
+
+gint
+gdk_text_width (GdkFont      *font,
+               const gchar  *text,
+               gint          text_length)
+{
+  SIZE size;
+
+  if (!gdk_text_size (font, text, text_length, &size))
+    return -1;
+
+  return size.cx;
 }
 
 gint
@@ -608,7 +618,7 @@ gdk_text_width_wc (GdkFont    *font,
   SIZE size;
   wchar_t *wcstr;
   guchar *str;
-  gint i, width, wlen;
+  gint i;
 
   g_return_val_if_fail (font != NULL, -1);
   g_return_val_if_fail (text != NULL, -1);
@@ -616,58 +626,44 @@ gdk_text_width_wc (GdkFont          *font,
   if (text_length == 0)
     return 0;
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   private = (GdkFontPrivate*) font;
 
-  switch (font->type)
+  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
+    
+    g_warning ("gdk_text_width_wc: SelectObject failed");
+
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
     {
-    case GDK_FONT_FONT:
-      oldfont = SelectObject (gdk_DC, private->xfont);
-#if 0 /* No. Don't assume Unicode here either.
-       * (Read the comments in gdk_draw_text_wc.)
-       */
       wcstr = g_new (wchar_t, text_length);
       for (i = 0; i < text_length; i++)
        wcstr[i] = text[i];
-      GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
-      g_free (wcstr);
-#else
-      str = g_new (guchar, text_length);
-      for (i = 0; i < text_length; i++)
-       str[i] = text[i];
-      if (private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (private->codepage, 0,
-                                          str, text_length,
-                                          wcstr, text_length)) == 0)
-           {
-             g_warning ("gdk_text_width_wc: MultiByteToWideChar failed");
-             size.cx = 0;
-           }
-         else
-           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
-         g_free (wcstr);
-       }
-      else
-       {
-         GetTextExtentPoint32A (gdk_DC, str, text_length, &size);
-       }
-      g_free (str);
-#endif
-      SelectObject (gdk_DC, oldfont);
-      width = size.cx;
-      break;
-
-    default:
-      width = 0;
     }
-  return width;
+  else
+    wcstr = (wchar_t *) text;
+
+  GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
+
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
+    g_free (wcstr);
+
+  if (oldfont != NULL)
+    SelectObject (gdk_DC, oldfont);
+
+  return size.cx;
 }
 
 gint
 gdk_char_width (GdkFont *font,
                gchar    character)
 {
+  if (((guchar) character) >= 128)
+    {
+      /* gtktext calls us with non-ASCII characters, sigh */
+      GdkWChar wc = (guchar) character;
+      return gdk_text_width_wc (font, &wc, 1);
+    }
   return gdk_text_width (font, &character, 1);
 }
 
@@ -722,48 +718,37 @@ gdk_text_extents (GdkFont     *font,
       return;
     }
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   private = (GdkFontPrivate*) font;
 
-  switch (font->type)
-    {
-    case GDK_FONT_FONT:
-      oldfont = SelectObject (gdk_DC, private->xfont);
-      if (private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (private->codepage, 0,
-                                          text, text_length,
-                                          wcstr, text_length)) == 0)
-           {
-             g_warning ("gdk_text_extents: MultiByteToWideChar failed");
-             size.cx = 0;
-             size.cy = 0;
-           }
-         else
-           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
-         g_free (wcstr);
-       }
-      else
-       {
-         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
-       }
-      SelectObject (gdk_DC, oldfont);
-      /* XXX This is all quite bogus */
-      if (lbearing)
-       *lbearing = 0;
-      if (rbearing)
-       *rbearing = 0;
-      if (width)
-       *width = size.cx;
-      if (ascent)
-       *ascent = size.cy + 1;
-      if (descent)
-       *descent = font->descent + 1;
-      break;
+  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
+    g_warning ("gdk_text_extents: SelectObject failed");
 
-    default:
-      g_assert_not_reached ();
+  wcstr = g_new (wchar_t, text_length);
+  if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
+    {
+      g_warning ("gdk_text_extents: gdk_nmbstowchar_ts failed");
+      size.cx = 0;
+      size.cy = 0;
     }
+  else
+    GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+
+  if (oldfont != NULL)
+    SelectObject (gdk_DC, oldfont);
+
+  /* XXX This is all quite bogus */
+  if (lbearing)
+    *lbearing = 0;
+  if (rbearing)
+    *rbearing = 0;
+  if (width)
+    *width = size.cx;
+  if (ascent)
+    *ascent = size.cy + 1;
+  if (descent)
+    *descent = font->descent + 1;
 }
 
 void
@@ -800,35 +785,41 @@ gdk_text_extents_wc (GdkFont        *font,
       return;
     }
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   private = (GdkFontPrivate*) font;
 
-  switch (font->type)
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
     {
-    case GDK_FONT_FONT:
       wcstr = g_new (wchar_t, text_length);
       for (i = 0; i < text_length; i++)
        wcstr[i] = text[i];
-      oldfont = SelectObject (gdk_DC, private->xfont);
-      GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
-      g_free (wcstr);
-      SelectObject (gdk_DC, oldfont);
-
-      /* XXX This is all quite bogus */
-      if (lbearing)
-       *lbearing = 0;
-      if (rbearing)
-       *rbearing = 0;
-      if (width)
-       *width = size.cx;
-      if (ascent)
-       *ascent = size.cy + 1;
-      if (descent)
-       *descent = font->descent + 1;
-      break;
-
-    default:
-      g_assert_not_reached ();
     }
+  else
+    wcstr = (wchar_t *) text;
+
+  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
+    g_warning ("gdk_text_extents_wc: SelectObject failed");
+
+  GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
+
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
+    g_free (wcstr);
+
+  if (oldfont != NULL)
+    SelectObject (gdk_DC, oldfont);
+
+  /* XXX This is all quite bogus */
+  if (lbearing)
+    *lbearing = 0;
+  if (rbearing)
+    *rbearing = 0;
+  if (width)
+    *width = size.cx;
+  if (ascent)
+    *ascent = size.cy + 1;
+  if (descent)
+    *descent = font->descent + 1;
 }
 
 void
@@ -853,24 +844,7 @@ gdk_text_measure (GdkFont     *font,
                   const gchar *text,
                   gint         text_length)
 {
-  GdkFontPrivate *private;
-  gint width;
-
-  g_return_val_if_fail (font != NULL, -1);
-  g_return_val_if_fail (text != NULL, -1);
-
-  private = (GdkFontPrivate*) font;
-
-  switch (font->type)
-    {
-    case GDK_FONT_FONT:
-      return gdk_text_width (font, text, text_length); /* ??? */
-      break;
-
-    default:
-      g_assert_not_reached ();
-    }
-  return 0;
+  return gdk_text_width (font, text, text_length); /* ??? */
 }
 
 gint
@@ -895,52 +869,12 @@ gdk_text_height (GdkFont     *font,
                 const gchar *text,
                 gint         text_length)
 {
-  GdkFontPrivate *private;
-  HGDIOBJ oldfont;
   SIZE size;
-  gint height, wlen;
-  wchar_t *wcstr;
-
-  g_return_val_if_fail (font != NULL, -1);
-  g_return_val_if_fail (text != NULL, -1);
-
-  if (text_length == 0)
-    return 0;
 
-  private = (GdkFontPrivate*) font;
-
-  switch (font->type)
-    {
-    case GDK_FONT_FONT:
-      oldfont = SelectObject (gdk_DC, private->xfont);
-      if (private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (private->codepage, 0,
-                                          text, text_length,
-                                          wcstr, text_length)) == 0)
-           {
-             g_warning ("gdk_text_height: MultiByteToWideChar failed "
-                        "text = %.*s (%d)",
-                        text_length, text, text_length);
-             size.cy = 0;
-           }
-         else
-           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
-         g_free (wcstr);
-       }
-      else
-       {
-         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
-       }
-      SelectObject (gdk_DC, oldfont);
-      height = size.cy;
-      break;
+  if (!gdk_text_size (font, text, text_length, &size))
+    return -1;
 
-    default:
-      g_error ("font->type = %d", font->type);
-    }
-  return height;
+  return size.cy;
 }
 
 gint
index d28c1f77c0615491ab1ad52cb0eb032e83fc7d97..5c85d476a174e9fd520168631566f1d31811899b 100644 (file)
@@ -117,7 +117,8 @@ charset_name (DWORD charset)
 }
 
 GdkFont*
-gdk_font_load (const gchar *font_name)
+gdk_font_load_internal (GdkFontType  type,
+                       const gchar *font_name)
 {
   GdkFont *font;
   GdkFontPrivate *private;
@@ -142,9 +143,9 @@ gdk_font_load (const gchar *font_name)
 
   g_return_val_if_fail (font_name != NULL, NULL);
 
-  GDK_NOTE (MISC, g_print ("gdk_font_load: %s\n", font_name));
+  GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name));
 
-  font = gdk_font_hash_lookup (GDK_FONT_FONT, font_name);
+  font = gdk_font_hash_lookup (type, font_name);
   if (font)
     return font;
 
@@ -417,7 +418,6 @@ gdk_font_load (const gchar *font_name)
   private->xfont = hfont;
   private->ref_count = 1;
   private->names = NULL;
-  font->type = GDK_FONT_FONT;
   GetObject (private->xfont, sizeof (logfont), &logfont);
   oldfont = SelectObject (gdk_DC, private->xfont);
   GetTextMetrics (gdk_DC, &textmetric);
@@ -426,6 +426,7 @@ gdk_font_load (const gchar *font_name)
   TranslateCharsetInfo ((DWORD *) private->charset, &csi, TCI_SRCCHARSET);
   private->codepage = csi.ciACP;
   GetCPInfo (private->codepage, &private->cpinfo);
+  font->type = type;
   font->ascent = textmetric.tmAscent;
   font->descent = textmetric.tmDescent;
 
@@ -442,17 +443,21 @@ gdk_font_load (const gchar *font_name)
   *f = (HANDLE) ((guint) private->xfont + HFONT_DITHER);
   gdk_xid_table_insert (f, font);
 
-  gdk_font_hash_insert (GDK_FONT_FONT, font, font_name);
+  gdk_font_hash_insert (type, font, font_name);
 
   return font;
 }
 
 GdkFont*
-gdk_fontset_load (gchar *fontset_name)
+gdk_font_load (const gchar *font_name)
 {
-  g_warning ("gdk_fontset_load: Not implemented");
+  return gdk_font_load_internal (GDK_FONT_FONT, font_name);
+}
 
-  return NULL;
+GdkFont*
+gdk_fontset_load (gchar *fontset_name)
+{
+  return gdk_font_load_internal (GDK_FONT_FONTSET, fontset_name);
 }
 
 GdkFont*
@@ -493,6 +498,7 @@ gdk_font_unref (GdkFont *font)
       switch (font->type)
        {
        case GDK_FONT_FONT:
+       case GDK_FONT_FONTSET:  /* XXX */
          gdk_xid_table_remove ((HANDLE) ((guint) private->xfont + HFONT_DITHER));
          DeleteObject (private->xfont);
          break;
@@ -515,9 +521,8 @@ gdk_font_id (const GdkFont *font)
 
   if (font->type == GDK_FONT_FONT)
     return (gint) font_private->xfont;
-
-  g_assert_not_reached ();
-  return 0;
+  else
+    return 0;
 }
 
 gint
@@ -535,9 +540,10 @@ gdk_font_equal (const GdkFont *fonta,
 
   if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT)
     return (privatea->xfont == privateb->xfont);
-
-  g_assert_not_reached ();
-  return 0;
+  else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET)
+    return (privatea->xfont == privateb->xfont);
+  else
+    return 0;
 }
 
 gint
@@ -547,55 +553,59 @@ gdk_string_width (GdkFont     *font,
   return gdk_text_width (font, string, strlen (string));
 }
 
-gint
-gdk_text_width (GdkFont      *font,
-               const gchar  *text,
-               gint          text_length)
+static gboolean
+gdk_text_size (GdkFont      *font,
+              const gchar  *text,
+              gint          text_length,
+              SIZE          *sizep)
 {
   GdkFontPrivate *private;
   HGDIOBJ oldfont;
-  SIZE size;
-  gint width, wlen;
+  gint wlen;
   wchar_t *wcstr;
 
-  g_return_val_if_fail (font != NULL, -1);
-  g_return_val_if_fail (text != NULL, -1);
+  g_return_val_if_fail (font != NULL, FALSE);
+  g_return_val_if_fail (text != NULL, FALSE);
 
   if (text_length == 0)
     return 0;
 
   private = (GdkFontPrivate*) font;
 
-  switch (font->type)
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
+  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
     {
-    case GDK_FONT_FONT:
-      oldfont = SelectObject (gdk_DC, private->xfont);
-      if (private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (private->codepage, 0,
-                                          text, text_length,
-                                          wcstr, text_length)) == 0)
-           {
-             g_warning ("gdk_text_width: MultiByteToWideChar failed");
-             size.cx = 0;
-           }
-         else
-           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
-         g_free (wcstr);
-       }
-      else
-       {
-         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
-       }
-      SelectObject (gdk_DC, oldfont);
-      width = size.cx;
-      break;
+      g_warning ("gdk_text_width: SelectObject failed");
+      return FALSE;
+    }
 
-    default:
-      g_assert_not_reached ();
+  wcstr = g_new (wchar_t, text_length);
+  if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
+    {
+      g_warning ("gdk_text_size: gdk_nmbstowchar_ts failed");
+      return FALSE;
     }
-  return width;
+
+  GetTextExtentPoint32W (gdk_DC, wcstr, wlen, sizep);
+
+  g_free (wcstr);
+  SelectObject (gdk_DC, oldfont);
+
+  return TRUE;
+}
+
+gint
+gdk_text_width (GdkFont      *font,
+               const gchar  *text,
+               gint          text_length)
+{
+  SIZE size;
+
+  if (!gdk_text_size (font, text, text_length, &size))
+    return -1;
+
+  return size.cx;
 }
 
 gint
@@ -608,7 +618,7 @@ gdk_text_width_wc (GdkFont    *font,
   SIZE size;
   wchar_t *wcstr;
   guchar *str;
-  gint i, width, wlen;
+  gint i;
 
   g_return_val_if_fail (font != NULL, -1);
   g_return_val_if_fail (text != NULL, -1);
@@ -616,58 +626,44 @@ gdk_text_width_wc (GdkFont          *font,
   if (text_length == 0)
     return 0;
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   private = (GdkFontPrivate*) font;
 
-  switch (font->type)
+  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
+    
+    g_warning ("gdk_text_width_wc: SelectObject failed");
+
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
     {
-    case GDK_FONT_FONT:
-      oldfont = SelectObject (gdk_DC, private->xfont);
-#if 0 /* No. Don't assume Unicode here either.
-       * (Read the comments in gdk_draw_text_wc.)
-       */
       wcstr = g_new (wchar_t, text_length);
       for (i = 0; i < text_length; i++)
        wcstr[i] = text[i];
-      GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
-      g_free (wcstr);
-#else
-      str = g_new (guchar, text_length);
-      for (i = 0; i < text_length; i++)
-       str[i] = text[i];
-      if (private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (private->codepage, 0,
-                                          str, text_length,
-                                          wcstr, text_length)) == 0)
-           {
-             g_warning ("gdk_text_width_wc: MultiByteToWideChar failed");
-             size.cx = 0;
-           }
-         else
-           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
-         g_free (wcstr);
-       }
-      else
-       {
-         GetTextExtentPoint32A (gdk_DC, str, text_length, &size);
-       }
-      g_free (str);
-#endif
-      SelectObject (gdk_DC, oldfont);
-      width = size.cx;
-      break;
-
-    default:
-      width = 0;
     }
-  return width;
+  else
+    wcstr = (wchar_t *) text;
+
+  GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
+
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
+    g_free (wcstr);
+
+  if (oldfont != NULL)
+    SelectObject (gdk_DC, oldfont);
+
+  return size.cx;
 }
 
 gint
 gdk_char_width (GdkFont *font,
                gchar    character)
 {
+  if (((guchar) character) >= 128)
+    {
+      /* gtktext calls us with non-ASCII characters, sigh */
+      GdkWChar wc = (guchar) character;
+      return gdk_text_width_wc (font, &wc, 1);
+    }
   return gdk_text_width (font, &character, 1);
 }
 
@@ -722,48 +718,37 @@ gdk_text_extents (GdkFont     *font,
       return;
     }
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   private = (GdkFontPrivate*) font;
 
-  switch (font->type)
-    {
-    case GDK_FONT_FONT:
-      oldfont = SelectObject (gdk_DC, private->xfont);
-      if (private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (private->codepage, 0,
-                                          text, text_length,
-                                          wcstr, text_length)) == 0)
-           {
-             g_warning ("gdk_text_extents: MultiByteToWideChar failed");
-             size.cx = 0;
-             size.cy = 0;
-           }
-         else
-           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
-         g_free (wcstr);
-       }
-      else
-       {
-         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
-       }
-      SelectObject (gdk_DC, oldfont);
-      /* XXX This is all quite bogus */
-      if (lbearing)
-       *lbearing = 0;
-      if (rbearing)
-       *rbearing = 0;
-      if (width)
-       *width = size.cx;
-      if (ascent)
-       *ascent = size.cy + 1;
-      if (descent)
-       *descent = font->descent + 1;
-      break;
+  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
+    g_warning ("gdk_text_extents: SelectObject failed");
 
-    default:
-      g_assert_not_reached ();
+  wcstr = g_new (wchar_t, text_length);
+  if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1)
+    {
+      g_warning ("gdk_text_extents: gdk_nmbstowchar_ts failed");
+      size.cx = 0;
+      size.cy = 0;
     }
+  else
+    GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+
+  if (oldfont != NULL)
+    SelectObject (gdk_DC, oldfont);
+
+  /* XXX This is all quite bogus */
+  if (lbearing)
+    *lbearing = 0;
+  if (rbearing)
+    *rbearing = 0;
+  if (width)
+    *width = size.cx;
+  if (ascent)
+    *ascent = size.cy + 1;
+  if (descent)
+    *descent = font->descent + 1;
 }
 
 void
@@ -800,35 +785,41 @@ gdk_text_extents_wc (GdkFont        *font,
       return;
     }
 
+  g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET);
+
   private = (GdkFontPrivate*) font;
 
-  switch (font->type)
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
     {
-    case GDK_FONT_FONT:
       wcstr = g_new (wchar_t, text_length);
       for (i = 0; i < text_length; i++)
        wcstr[i] = text[i];
-      oldfont = SelectObject (gdk_DC, private->xfont);
-      GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
-      g_free (wcstr);
-      SelectObject (gdk_DC, oldfont);
-
-      /* XXX This is all quite bogus */
-      if (lbearing)
-       *lbearing = 0;
-      if (rbearing)
-       *rbearing = 0;
-      if (width)
-       *width = size.cx;
-      if (ascent)
-       *ascent = size.cy + 1;
-      if (descent)
-       *descent = font->descent + 1;
-      break;
-
-    default:
-      g_assert_not_reached ();
     }
+  else
+    wcstr = (wchar_t *) text;
+
+  if ((oldfont = SelectObject (gdk_DC, private->xfont)) == NULL)
+    g_warning ("gdk_text_extents_wc: SelectObject failed");
+
+  GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
+
+  if (sizeof (wchar_t) != sizeof (GdkWChar))
+    g_free (wcstr);
+
+  if (oldfont != NULL)
+    SelectObject (gdk_DC, oldfont);
+
+  /* XXX This is all quite bogus */
+  if (lbearing)
+    *lbearing = 0;
+  if (rbearing)
+    *rbearing = 0;
+  if (width)
+    *width = size.cx;
+  if (ascent)
+    *ascent = size.cy + 1;
+  if (descent)
+    *descent = font->descent + 1;
 }
 
 void
@@ -853,24 +844,7 @@ gdk_text_measure (GdkFont     *font,
                   const gchar *text,
                   gint         text_length)
 {
-  GdkFontPrivate *private;
-  gint width;
-
-  g_return_val_if_fail (font != NULL, -1);
-  g_return_val_if_fail (text != NULL, -1);
-
-  private = (GdkFontPrivate*) font;
-
-  switch (font->type)
-    {
-    case GDK_FONT_FONT:
-      return gdk_text_width (font, text, text_length); /* ??? */
-      break;
-
-    default:
-      g_assert_not_reached ();
-    }
-  return 0;
+  return gdk_text_width (font, text, text_length); /* ??? */
 }
 
 gint
@@ -895,52 +869,12 @@ gdk_text_height (GdkFont     *font,
                 const gchar *text,
                 gint         text_length)
 {
-  GdkFontPrivate *private;
-  HGDIOBJ oldfont;
   SIZE size;
-  gint height, wlen;
-  wchar_t *wcstr;
-
-  g_return_val_if_fail (font != NULL, -1);
-  g_return_val_if_fail (text != NULL, -1);
-
-  if (text_length == 0)
-    return 0;
 
-  private = (GdkFontPrivate*) font;
-
-  switch (font->type)
-    {
-    case GDK_FONT_FONT:
-      oldfont = SelectObject (gdk_DC, private->xfont);
-      if (private->cpinfo.MaxCharSize > 1)
-       {
-         wcstr = g_new (wchar_t, text_length);
-         if ((wlen = MultiByteToWideChar (private->codepage, 0,
-                                          text, text_length,
-                                          wcstr, text_length)) == 0)
-           {
-             g_warning ("gdk_text_height: MultiByteToWideChar failed "
-                        "text = %.*s (%d)",
-                        text_length, text, text_length);
-             size.cy = 0;
-           }
-         else
-           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
-         g_free (wcstr);
-       }
-      else
-       {
-         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
-       }
-      SelectObject (gdk_DC, oldfont);
-      height = size.cy;
-      break;
+  if (!gdk_text_size (font, text, text_length, &size))
+    return -1;
 
-    default:
-      g_error ("font->type = %d", font->type);
-    }
-  return height;
+  return size.cy;
 }
 
 gint
index e1cbf8552b0acb608ddef2026c247e9c158f62b3..fb59c593f95619fe9fa3556149ba762e2dc5d30f 100644 (file)
@@ -87,7 +87,8 @@ gdk_gc_new_with_values (GdkWindow     *window,
   else
     private->background = white;
 
-  if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
+  if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT
+                                     || values->font->type == GDK_FONT_FONTSET))
     {
       private->font = (HFONT) ((GdkFontPrivate*) values->font)->xfont;
       GDK_NOTE (MISC, g_print (" font=%#x", private->font));
@@ -480,7 +481,8 @@ gdk_gc_set_font (GdkGC       *gc,
   g_return_if_fail (gc != NULL);
   g_return_if_fail (font != NULL);
 
-  if (font->type == GDK_FONT_FONT)
+  if (font->type == GDK_FONT_FONT
+      || font->type == GDK_FONT_FONTSET)
     {
       gc_private = (GdkGCPrivate*) gc;
       font_private = (GdkFontPrivate*) font;
index e1cbf8552b0acb608ddef2026c247e9c158f62b3..fb59c593f95619fe9fa3556149ba762e2dc5d30f 100644 (file)
@@ -87,7 +87,8 @@ gdk_gc_new_with_values (GdkWindow     *window,
   else
     private->background = white;
 
-  if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT))
+  if ((values_mask & GDK_GC_FONT) && (values->font->type == GDK_FONT_FONT
+                                     || values->font->type == GDK_FONT_FONTSET))
     {
       private->font = (HFONT) ((GdkFontPrivate*) values->font)->xfont;
       GDK_NOTE (MISC, g_print (" font=%#x", private->font));
@@ -480,7 +481,8 @@ gdk_gc_set_font (GdkGC       *gc,
   g_return_if_fail (gc != NULL);
   g_return_if_fail (font != NULL);
 
-  if (font->type == GDK_FONT_FONT)
+  if (font->type == GDK_FONT_FONT
+      || font->type == GDK_FONT_FONTSET)
     {
       gc_private = (GdkGCPrivate*) gc;
       font_private = (GdkFontPrivate*) font;
index cf16cf717cfcf06ec0c3f282864073c12bc5394c..3aa73b6076091a86e021056c6a58694f5360b318 100644 (file)
@@ -28,9 +28,9 @@
 #include "gdkprivate.h"
 
 guint             gdk_debug_flags = 0;
-HWND              gdk_root_window;
+HWND              gdk_root_window = NULL;
 HWND              gdk_leader_window;
-GDKVAR GdkWindowPrivate  gdk_root_parent = { { NULL, }, NULL, };
+GDKVAR GdkWindowPrivate *gdk_root_parent = NULL;
 HDC              gdk_DC;
 HINSTANCE        gdk_DLLInstance;
 HINSTANCE        gdk_ProgInstance;
@@ -45,18 +45,8 @@ gchar            *gdk_progclass = NULL;
 gint              gdk_error_code;
 gint              gdk_error_warnings = TRUE;
 gint              gdk_null_window_warnings = TRUE;
-GList            *gdk_default_filters = NULL;
-
-gboolean      gdk_xim_using;           /* using XIM Protocol if TRUE */
-GdkWindow    *gdk_xim_window;          /* currently using Widow */
-
-GdkWindowPrivate *gdk_xgrab_window = NULL;  /* Window that currently holds the
-                                            *  x pointer grab
-                                            */
 
 GMutex *gdk_threads_mutex = NULL;          /* Global GDK lock */
 
-#ifdef USE_XIM
-GdkICPrivate *gdk_xim_ic;              /* currently using IC */
-GdkWindow *gdk_xim_window;             /* currently using Window */
-#endif
+BOOL (WINAPI *p_TrackMouseEvent) (TRACKMOUSEEVENT *tme) = NULL;
+
index cf16cf717cfcf06ec0c3f282864073c12bc5394c..3aa73b6076091a86e021056c6a58694f5360b318 100644 (file)
@@ -28,9 +28,9 @@
 #include "gdkprivate.h"
 
 guint             gdk_debug_flags = 0;
-HWND              gdk_root_window;
+HWND              gdk_root_window = NULL;
 HWND              gdk_leader_window;
-GDKVAR GdkWindowPrivate  gdk_root_parent = { { NULL, }, NULL, };
+GDKVAR GdkWindowPrivate *gdk_root_parent = NULL;
 HDC              gdk_DC;
 HINSTANCE        gdk_DLLInstance;
 HINSTANCE        gdk_ProgInstance;
@@ -45,18 +45,8 @@ gchar            *gdk_progclass = NULL;
 gint              gdk_error_code;
 gint              gdk_error_warnings = TRUE;
 gint              gdk_null_window_warnings = TRUE;
-GList            *gdk_default_filters = NULL;
-
-gboolean      gdk_xim_using;           /* using XIM Protocol if TRUE */
-GdkWindow    *gdk_xim_window;          /* currently using Widow */
-
-GdkWindowPrivate *gdk_xgrab_window = NULL;  /* Window that currently holds the
-                                            *  x pointer grab
-                                            */
 
 GMutex *gdk_threads_mutex = NULL;          /* Global GDK lock */
 
-#ifdef USE_XIM
-GdkICPrivate *gdk_xim_ic;              /* currently using IC */
-GdkWindow *gdk_xim_window;             /* currently using Window */
-#endif
+BOOL (WINAPI *p_TrackMouseEvent) (TRACKMOUSEEVENT *tme) = NULL;
+
index 35ea6b5683b0f418f5ab237a7410632b4efbce65..0d553176555febc50ba87ebc85c2ac5330ad7ab7 100644 (file)
 #include "gdki18n.h"
 #include "gdkx.h"
 
-/* If this variable is FALSE, it indicates that we should
- * avoid trying to use multibyte conversion functions and
- * assume everything is 1-byte per character
- */
-static gboolean gdk_use_mb;
-
 /*
  *--------------------------------------------------------------
  * gdk_set_locale
@@ -59,22 +53,13 @@ static gboolean gdk_use_mb;
 gchar*
 gdk_set_locale (void)
 {
-  wchar_t result;
   gchar *current_locale;
 
-  gdk_use_mb = FALSE;
-
   if (!setlocale (LC_ALL,""))
     g_warning ("locale not supported by C library");
   
   current_locale = setlocale (LC_ALL, NULL);
 
-  if (MB_CUR_MAX > 1)
-    gdk_use_mb = TRUE;
-
-  GDK_NOTE (XIM, g_message ("%s multi-byte string functions.", 
-                           gdk_use_mb ? "Using" : "Not using"));
-  
   return current_locale;
 }
 
@@ -158,50 +143,91 @@ gdk_ic_get_events (GdkIC *ic)
  * of wide characters. The string is newly allocated. The array of
  * wide characters must be null-terminated. If the conversion is
  * failed, it returns NULL.
+ *
+ * On Win32, we always use UTF-8.
  */
 gchar *
 gdk_wcstombs (const GdkWChar *src)
 {
-  gchar *mbstr;
+  gint len;
+  const GdkWChar *wcp;
+  guchar *mbstr, *bp;
 
-  if (gdk_use_mb)
+  wcp = src;
+  len = 0;
+  while (*wcp)
     {
-      gint i, wcsl, mbsl;
-      wchar_t *src_alt;
-
-      for (wcsl = 0; src[wcsl]; wcsl++)
-       ;
-      src_alt = g_new (wchar_t, wcsl+1);
-      for (i = wcsl; i >= 0; i--)
-       src_alt[i] = src[i];
-      mbsl = WideCharToMultiByte (CP_OEMCP, 0, src_alt, wcsl,
-                                 NULL, 0, NULL, NULL);
-      mbstr = g_new (guchar, mbsl + 1);
-      if (!WideCharToMultiByte (CP_OEMCP, 0, src_alt, wcsl,
-                               mbstr, mbsl, NULL, NULL))
-       {
-         g_warning ("gdk_wcstombs: WideCharToMultiByte failed");
-         g_free (mbstr);
-         g_free (src_alt);
-         return NULL;
-       }
-      mbstr[mbsl] = '\0';
-      g_free (src_alt);
+      const GdkWChar c = *wcp++;
+
+      if (c < 0x80)
+       len += 1;
+      else if (c < 0x800)
+       len += 2;
+      else if (c < 0x10000)
+       len += 3;
+      else if (c < 0x200000)
+       len += 4;
+      else if (c < 0x4000000)
+       len += 5;
+      else
+       len += 6;
     }
-  else
+
+  mbstr = g_malloc (len + 1);
+  
+  wcp = src;
+  bp = mbstr;
+  while (*wcp)
     {
-      gint length = 0;
-      gint i;
+      int first;
+      int i;
+      GdkWChar c = *wcp++;
 
-      while (src[length] != 0)
-       length++;
+      if (c < 0x80)
+       {
+         first = 0;
+         len = 1;
+       }
+      else if (c < 0x800)
+       {
+         first = 0xc0;
+         len = 2;
+       }
+      else if (c < 0x10000)
+       {
+         first = 0xe0;
+         len = 3;
+       }
+      else if (c < 0x200000)
+       {
+         first = 0xf0;
+         len = 4;
+       }
+      else if (c < 0x4000000)
+       {
+         first = 0xf8;
+         len = 5;
+       }
+      else
+       {
+         first = 0xfc;
+         len = 6;
+       }
       
-      mbstr = g_new (gchar, length + 1);
+      /* Woo-hoo! */
+      switch (len)
+       {
+       case 6: bp[5] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 5: bp[4] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 4: bp[3] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 1: bp[0] = c | first;
+       }
 
-      for (i=0; i<length+1; i++)
-       mbstr[i] = src[i];
+      bp += len;
     }
-
+  *bp = 0;
   return mbstr;
 }
 
@@ -209,41 +235,158 @@ gdk_wcstombs (const GdkWChar *src)
 /*
  * gdk_mbstowcs
  *
- * Converts the specified string into wide characters, and, returns the
- * number of wide characters written. The string 'src' must be
- * null-terminated. If the conversion is failed, it returns -1.
+ * Converts the specified string into GDK wide characters, and,
+ * returns the number of wide characters written. The string 'src'
+ * must be null-terminated. If the conversion is failed, it returns
+ * -1.
+ *
+ * On Win32, thr string is assumed to be in UTF-8.  Also note that
+ * GdkWChar is 32 bits, while wchar_t, and the wide characters the
+ * Windows API uses, are 16 bits!
  */
+
+/* First a helper function for not zero-terminated strings */
 gint
-gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max)
+gdk_nmbstowcs (GdkWChar    *dest,
+              const gchar *src,
+              gint         src_len,
+              gint         dest_max)
 {
-  if (gdk_use_mb)
+  guchar *cp, *end;
+  gint n;
+  
+  cp = (guchar *) src;
+  end = cp + src_len;
+  n = 0;
+  while (cp != end && dest != dest + dest_max)
     {
-      gint i, wcsl;
-      wchar_t *wcstr;
+      gint i, mask = 0, len;
+      guchar c = *cp;
+
+      if (c < 0x80)
+       {
+         len = 1;
+         mask = 0x7f;
+       }
+      else if ((c & 0xe0) == 0xc0)
+       {
+         len = 2;
+         mask = 0x1f;
+       }
+      else if ((c & 0xf0) == 0xe0)
+       {
+         len = 3;
+         mask = 0x0f;
+       }
+      else if ((c & 0xf8) == 0xf0)
+       {
+         len = 4;
+         mask = 0x07;
+       }
+      else if ((c & 0xfc) == 0xf8)
+       {
+         len = 5;
+         mask = 0x03;
+       }
+      else if ((c & 0xfc) == 0xfc)
+       {
+         len = 6;
+         mask = 0x01;
+       }
+      else
+       return -1;
+
+      if (cp + len > end)
+       return -1;
 
-      wcsl = MultiByteToWideChar (CP_OEMCP, 0, src, -1, NULL, 0);
-      wcstr = g_new (wchar_t, wcsl);
-      if (!MultiByteToWideChar (CP_OEMCP, 0, src, -1, wcstr, wcsl))
+      *dest = (cp[0] & mask);
+      for (i = 1; i < len; i++)
        {
-         g_warning ("gdk_mbstowcs: MultiByteToWideChar failed");
-         g_free (wcstr);
-         return -1;
+         if ((cp[i] & 0xc0) != 0x80)
+           return -1;
+         *dest <<= 6;
+         *dest |= (cp[i] & 0x3f);
        }
-      if (wcsl > dest_max)
-       wcsl = dest_max;
-      for (i = 0; i < wcsl && wcstr[i]; i++)
-       dest[i] = wcstr[i];
-      g_free (wcstr);
+      if (*dest == -1)
+       return -1;
 
-      return i;
+      cp += len;
+      dest++;
+      n++;
     }
-  else
+  if (cp != end)
+    return -1;
+
+  return n;
+}
+
+gint
+gdk_mbstowcs (GdkWChar    *dest,
+             const gchar *src,
+             gint         dest_max)
+{
+  return gdk_nmbstowcs (dest, src, strlen (src), dest_max);
+}
+
+
+/* A version that converts to wchar_t wide chars */
+
+gint
+gdk_nmbstowchar_ts (wchar_t     *dest,
+                   const gchar *src,
+                   gint         src_len,
+                   gint         dest_max)
+{
+  guchar *cp, *end;
+  gint n;
+  
+  cp = (guchar *) src;
+  end = cp + src_len;
+  n = 0;
+  while (cp != end && dest != dest + dest_max)
     {
-      gint i;
+      gint i, mask = 0, len;
+      guchar c = *cp;
+
+      if (c < 0x80)
+       {
+         len = 1;
+         mask = 0x7f;
+       }
+      else if ((c & 0xe0) == 0xc0)
+       {
+         len = 2;
+         mask = 0x1f;
+       }
+      else if ((c & 0xf0) == 0xe0)
+       {
+         len = 3;
+         mask = 0x0f;
+       }
+      else /* Other lengths are not possible with 16-bit wchar_t! */
+       return -1;
+
+      if (cp + len > end)
+       return -1;
 
-      for (i=0; i<dest_max && src[i]; i++)
-       dest[i] = src[i];
+      *dest = (cp[0] & mask);
+      for (i = 1; i < len; i++)
+       {
+         if ((cp[i] & 0xc0) != 0x80)
+           return -1;
+         *dest <<= 6;
+         *dest |= (cp[i] & 0x3f);
+       }
+      if (*dest == 0xFFFF)
+       return -1;
 
-      return i;
+      cp += len;
+      dest++;
+      n++;
     }
+  if (cp != end)
+    return -1;
+
+  return n;
 }
+
index 35ea6b5683b0f418f5ab237a7410632b4efbce65..0d553176555febc50ba87ebc85c2ac5330ad7ab7 100644 (file)
 #include "gdki18n.h"
 #include "gdkx.h"
 
-/* If this variable is FALSE, it indicates that we should
- * avoid trying to use multibyte conversion functions and
- * assume everything is 1-byte per character
- */
-static gboolean gdk_use_mb;
-
 /*
  *--------------------------------------------------------------
  * gdk_set_locale
@@ -59,22 +53,13 @@ static gboolean gdk_use_mb;
 gchar*
 gdk_set_locale (void)
 {
-  wchar_t result;
   gchar *current_locale;
 
-  gdk_use_mb = FALSE;
-
   if (!setlocale (LC_ALL,""))
     g_warning ("locale not supported by C library");
   
   current_locale = setlocale (LC_ALL, NULL);
 
-  if (MB_CUR_MAX > 1)
-    gdk_use_mb = TRUE;
-
-  GDK_NOTE (XIM, g_message ("%s multi-byte string functions.", 
-                           gdk_use_mb ? "Using" : "Not using"));
-  
   return current_locale;
 }
 
@@ -158,50 +143,91 @@ gdk_ic_get_events (GdkIC *ic)
  * of wide characters. The string is newly allocated. The array of
  * wide characters must be null-terminated. If the conversion is
  * failed, it returns NULL.
+ *
+ * On Win32, we always use UTF-8.
  */
 gchar *
 gdk_wcstombs (const GdkWChar *src)
 {
-  gchar *mbstr;
+  gint len;
+  const GdkWChar *wcp;
+  guchar *mbstr, *bp;
 
-  if (gdk_use_mb)
+  wcp = src;
+  len = 0;
+  while (*wcp)
     {
-      gint i, wcsl, mbsl;
-      wchar_t *src_alt;
-
-      for (wcsl = 0; src[wcsl]; wcsl++)
-       ;
-      src_alt = g_new (wchar_t, wcsl+1);
-      for (i = wcsl; i >= 0; i--)
-       src_alt[i] = src[i];
-      mbsl = WideCharToMultiByte (CP_OEMCP, 0, src_alt, wcsl,
-                                 NULL, 0, NULL, NULL);
-      mbstr = g_new (guchar, mbsl + 1);
-      if (!WideCharToMultiByte (CP_OEMCP, 0, src_alt, wcsl,
-                               mbstr, mbsl, NULL, NULL))
-       {
-         g_warning ("gdk_wcstombs: WideCharToMultiByte failed");
-         g_free (mbstr);
-         g_free (src_alt);
-         return NULL;
-       }
-      mbstr[mbsl] = '\0';
-      g_free (src_alt);
+      const GdkWChar c = *wcp++;
+
+      if (c < 0x80)
+       len += 1;
+      else if (c < 0x800)
+       len += 2;
+      else if (c < 0x10000)
+       len += 3;
+      else if (c < 0x200000)
+       len += 4;
+      else if (c < 0x4000000)
+       len += 5;
+      else
+       len += 6;
     }
-  else
+
+  mbstr = g_malloc (len + 1);
+  
+  wcp = src;
+  bp = mbstr;
+  while (*wcp)
     {
-      gint length = 0;
-      gint i;
+      int first;
+      int i;
+      GdkWChar c = *wcp++;
 
-      while (src[length] != 0)
-       length++;
+      if (c < 0x80)
+       {
+         first = 0;
+         len = 1;
+       }
+      else if (c < 0x800)
+       {
+         first = 0xc0;
+         len = 2;
+       }
+      else if (c < 0x10000)
+       {
+         first = 0xe0;
+         len = 3;
+       }
+      else if (c < 0x200000)
+       {
+         first = 0xf0;
+         len = 4;
+       }
+      else if (c < 0x4000000)
+       {
+         first = 0xf8;
+         len = 5;
+       }
+      else
+       {
+         first = 0xfc;
+         len = 6;
+       }
       
-      mbstr = g_new (gchar, length + 1);
+      /* Woo-hoo! */
+      switch (len)
+       {
+       case 6: bp[5] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 5: bp[4] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 4: bp[3] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 3: bp[2] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 2: bp[1] = (c & 0x3f) | 0x80; c >>= 6; /* Fall through */
+       case 1: bp[0] = c | first;
+       }
 
-      for (i=0; i<length+1; i++)
-       mbstr[i] = src[i];
+      bp += len;
     }
-
+  *bp = 0;
   return mbstr;
 }
 
@@ -209,41 +235,158 @@ gdk_wcstombs (const GdkWChar *src)
 /*
  * gdk_mbstowcs
  *
- * Converts the specified string into wide characters, and, returns the
- * number of wide characters written. The string 'src' must be
- * null-terminated. If the conversion is failed, it returns -1.
+ * Converts the specified string into GDK wide characters, and,
+ * returns the number of wide characters written. The string 'src'
+ * must be null-terminated. If the conversion is failed, it returns
+ * -1.
+ *
+ * On Win32, thr string is assumed to be in UTF-8.  Also note that
+ * GdkWChar is 32 bits, while wchar_t, and the wide characters the
+ * Windows API uses, are 16 bits!
  */
+
+/* First a helper function for not zero-terminated strings */
 gint
-gdk_mbstowcs (GdkWChar *dest, const gchar *src, gint dest_max)
+gdk_nmbstowcs (GdkWChar    *dest,
+              const gchar *src,
+              gint         src_len,
+              gint         dest_max)
 {
-  if (gdk_use_mb)
+  guchar *cp, *end;
+  gint n;
+  
+  cp = (guchar *) src;
+  end = cp + src_len;
+  n = 0;
+  while (cp != end && dest != dest + dest_max)
     {
-      gint i, wcsl;
-      wchar_t *wcstr;
+      gint i, mask = 0, len;
+      guchar c = *cp;
+
+      if (c < 0x80)
+       {
+         len = 1;
+         mask = 0x7f;
+       }
+      else if ((c & 0xe0) == 0xc0)
+       {
+         len = 2;
+         mask = 0x1f;
+       }
+      else if ((c & 0xf0) == 0xe0)
+       {
+         len = 3;
+         mask = 0x0f;
+       }
+      else if ((c & 0xf8) == 0xf0)
+       {
+         len = 4;
+         mask = 0x07;
+       }
+      else if ((c & 0xfc) == 0xf8)
+       {
+         len = 5;
+         mask = 0x03;
+       }
+      else if ((c & 0xfc) == 0xfc)
+       {
+         len = 6;
+         mask = 0x01;
+       }
+      else
+       return -1;
+
+      if (cp + len > end)
+       return -1;
 
-      wcsl = MultiByteToWideChar (CP_OEMCP, 0, src, -1, NULL, 0);
-      wcstr = g_new (wchar_t, wcsl);
-      if (!MultiByteToWideChar (CP_OEMCP, 0, src, -1, wcstr, wcsl))
+      *dest = (cp[0] & mask);
+      for (i = 1; i < len; i++)
        {
-         g_warning ("gdk_mbstowcs: MultiByteToWideChar failed");
-         g_free (wcstr);
-         return -1;
+         if ((cp[i] & 0xc0) != 0x80)
+           return -1;
+         *dest <<= 6;
+         *dest |= (cp[i] & 0x3f);
        }
-      if (wcsl > dest_max)
-       wcsl = dest_max;
-      for (i = 0; i < wcsl && wcstr[i]; i++)
-       dest[i] = wcstr[i];
-      g_free (wcstr);
+      if (*dest == -1)
+       return -1;
 
-      return i;
+      cp += len;
+      dest++;
+      n++;
     }
-  else
+  if (cp != end)
+    return -1;
+
+  return n;
+}
+
+gint
+gdk_mbstowcs (GdkWChar    *dest,
+             const gchar *src,
+             gint         dest_max)
+{
+  return gdk_nmbstowcs (dest, src, strlen (src), dest_max);
+}
+
+
+/* A version that converts to wchar_t wide chars */
+
+gint
+gdk_nmbstowchar_ts (wchar_t     *dest,
+                   const gchar *src,
+                   gint         src_len,
+                   gint         dest_max)
+{
+  guchar *cp, *end;
+  gint n;
+  
+  cp = (guchar *) src;
+  end = cp + src_len;
+  n = 0;
+  while (cp != end && dest != dest + dest_max)
     {
-      gint i;
+      gint i, mask = 0, len;
+      guchar c = *cp;
+
+      if (c < 0x80)
+       {
+         len = 1;
+         mask = 0x7f;
+       }
+      else if ((c & 0xe0) == 0xc0)
+       {
+         len = 2;
+         mask = 0x1f;
+       }
+      else if ((c & 0xf0) == 0xe0)
+       {
+         len = 3;
+         mask = 0x0f;
+       }
+      else /* Other lengths are not possible with 16-bit wchar_t! */
+       return -1;
+
+      if (cp + len > end)
+       return -1;
 
-      for (i=0; i<dest_max && src[i]; i++)
-       dest[i] = src[i];
+      *dest = (cp[0] & mask);
+      for (i = 1; i < len; i++)
+       {
+         if ((cp[i] & 0xc0) != 0x80)
+           return -1;
+         *dest <<= 6;
+         *dest |= (cp[i] & 0x3f);
+       }
+      if (*dest == 0xFFFF)
+       return -1;
 
-      return i;
+      cp += len;
+      dest++;
+      n++;
     }
+  if (cp != end)
+    return -1;
+
+  return n;
 }
+
index 4a864c7eaae55a683f9a4abf2c2b32310dd8557a..2335e989c56ee031d0b4c8bd17ac09bc9027f849 100644 (file)
@@ -1006,7 +1006,7 @@ gdk_input_win32_other_event (GdkEvent  *event,
 #if USE_SYSCONTEXT
   window = gdk_window_at_pointer (&x, &y);
   if (window == NULL)
-    window = (GdkWindow *) &gdk_root_parent;
+    window = (GdkWindow *) gdk_root_parent;
 
   gdk_window_ref (window);
 
@@ -1036,7 +1036,7 @@ gdk_input_win32_other_event (GdkEvent  *event,
   switch (xevent->message)
     {
     case WT_PACKET:
-      if (window_private == &gdk_root_parent)
+      if (window_private == gdk_root_parent)
        {
          GDK_NOTE (EVENTS, g_print ("...is root\n"));
          return FALSE;
@@ -1104,7 +1104,7 @@ gdk_input_win32_other_event (GdkEvent  *event,
        {
          GDK_NOTE (EVENTS, g_print ("...not selected\n"));
 
-         if (window_private->parent == (GdkWindow *) &gdk_root_parent)
+         if (window_private->parent == (GdkWindow *) gdk_root_parent)
            return FALSE;
          
          pt.x = x;
index 4a864c7eaae55a683f9a4abf2c2b32310dd8557a..2335e989c56ee031d0b4c8bd17ac09bc9027f849 100644 (file)
@@ -1006,7 +1006,7 @@ gdk_input_win32_other_event (GdkEvent  *event,
 #if USE_SYSCONTEXT
   window = gdk_window_at_pointer (&x, &y);
   if (window == NULL)
-    window = (GdkWindow *) &gdk_root_parent;
+    window = (GdkWindow *) gdk_root_parent;
 
   gdk_window_ref (window);
 
@@ -1036,7 +1036,7 @@ gdk_input_win32_other_event (GdkEvent  *event,
   switch (xevent->message)
     {
     case WT_PACKET:
-      if (window_private == &gdk_root_parent)
+      if (window_private == gdk_root_parent)
        {
          GDK_NOTE (EVENTS, g_print ("...is root\n"));
          return FALSE;
@@ -1104,7 +1104,7 @@ gdk_input_win32_other_event (GdkEvent  *event,
        {
          GDK_NOTE (EVENTS, g_print ("...not selected\n"));
 
-         if (window_private->parent == (GdkWindow *) &gdk_root_parent)
+         if (window_private->parent == (GdkWindow *) gdk_root_parent)
            return FALSE;
          
          pt.x = x;
index 5a44835c5d0da9cb65796e4be903530874f98eff..9e5cb9f0cabb2f6dea1bdc292df2e1b03e719241 100644 (file)
 #include "gdkinputprivate.h"
 #include "gdkkeysyms.h"
 
+#include <objbase.h>
+
 static void     gdkx_XConvertCase      (KeySym        symbol,
                                         KeySym       *lower,
                                         KeySym       *upper);
-#define XConvertCase gdkx_XConvertCase
-
 static void        gdk_exit_func                (void);
 
 
@@ -234,6 +234,9 @@ gdk_init_check (int    *argc,
   
   gdk_ProgInstance = GetModuleHandle (NULL);
   gdk_DC = CreateDC ("DISPLAY", NULL, NULL, NULL);
+  gdk_root_window = GetDesktopWindow ();
+
+  CoInitialize (NULL);
 
   gdk_selection_request_msg = RegisterWindowMessage ("gdk-selection-request");
   gdk_selection_notify_msg = RegisterWindowMessage ("gdk-selection-notify");
@@ -247,8 +250,6 @@ gdk_init_check (int    *argc,
   gdk_progclass = g_basename (g_get_prgname ());
   gdk_progclass[0] = toupper (gdk_progclass[0]);
 
-  gdk_root_window = HWND_DESKTOP;
-
   g_atexit (gdk_exit_func);
   
   gdk_events_init ();
@@ -333,7 +334,7 @@ gdk_screen_width (void)
 {
   gint return_val;
   
-  return_val = gdk_root_parent.drawable.width;
+  return_val = gdk_root_parent->drawable.width;
 
   return return_val;
 }
@@ -358,7 +359,7 @@ gdk_screen_height (void)
 {
   gint return_val;
   
-  return_val = gdk_root_parent.drawable.height;
+  return_val = gdk_root_parent->drawable.height;
 
   return return_val;
 }
@@ -498,6 +499,9 @@ gdk_exit_func (void)
       gdk_input_exit ();
       gdk_key_repeat_restore ();
       gdk_dnd_exit ();
+
+      CoUninitialize ();
+
       DeleteDC (gdk_DC);
       gdk_DC = NULL;
       gdk_initialized = 0;
@@ -1670,6 +1674,22 @@ static struct gdk_key {
   { 0x000ef9, "Hangul_J_KkogjiDalrinIeung" },
   { 0x000efa, "Hangul_J_YeorinHieuh" },
   { 0x000eff, "Korean_Won" },
+  { 0x0013bc, "OE" },
+  { 0x0013bd, "oe" },
+  { 0x0013be, "Ydiaeresis" },
+  { 0x0020a0, "EcuSign" },
+  { 0x0020a1, "ColonSign" },
+  { 0x0020a2, "CruzeiroSign" },
+  { 0x0020a3, "FFrancSign" },
+  { 0x0020a4, "LiraSign" },
+  { 0x0020a5, "MillSign" },
+  { 0x0020a6, "NairaSign" },
+  { 0x0020a7, "PesetaSign" },
+  { 0x0020a8, "RupeeSign" },
+  { 0x0020a9, "WonSign" },
+  { 0x0020aa, "NewSheqelSign" },
+  { 0x0020ab, "DongSign" },
+  { 0x0020ac, "EuroSign" },
   { 0x00fd01, "3270_Duplicate" },
   { 0x00fd02, "3270_FieldMark" },
   { 0x00fd03, "3270_Right2" },
@@ -1826,11 +1846,21 @@ static struct gdk_key {
   { 0x00ff2e, "Kana_Shift" },
   { 0x00ff2f, "Eisu_Shift" },
   { 0x00ff30, "Eisu_toggle" },
+  { 0x00ff31, "Hangul" },
+  { 0x00ff32, "Hangul_Start" },
+  { 0x00ff33, "Hangul_End" },
+  { 0x00ff34, "Hangul_Hanja" },
+  { 0x00ff35, "Hangul_Jamo" },
+  { 0x00ff36, "Hangul_Romaja" },
+  { 0x00ff37, "Codeinput" },
+  { 0x00ff38, "Hangul_Jeonja" },
+  { 0x00ff39, "Hangul_Banja" },
+  { 0x00ff3a, "Hangul_PreHanja" },
+  { 0x00ff3b, "Hangul_PostHanja" },
   { 0x00ff3c, "SingleCandidate" },
   { 0x00ff3d, "MultipleCandidate" },
-  { 0x00ff3d, "Zen_Koho" },
-  { 0x00ff3e, "Mae_Koho" },
   { 0x00ff3e, "PreviousCandidate" },
+  { 0x00ff3f, "Hangul_Special" },
   { 0x00ff50, "Home" },
   { 0x00ff51, "Left" },
   { 0x00ff52, "Up" },
@@ -1949,21 +1979,6 @@ static struct gdk_key {
   { 0x00ffed, "Hyper_L" },
   { 0x00ffee, "Hyper_R" },
   { 0x00ffff, "Delete" },
-  { 0x00ff31, "Hangul" },
-  { 0x00ff32, "Hangul_Start" },
-  { 0x00ff33, "Hangul_End" },
-  { 0x00ff34, "Hangul_Hanja" },
-  { 0x00ff35, "Hangul_Jamo" },
-  { 0x00ff36, "Hangul_Romaja" },
-  { 0x00ff37, "Hangul_Codeinput" },
-  { 0x00ff38, "Hangul_Jeonja" },
-  { 0x00ff39, "Hangul_Banja" },
-  { 0x00ff3a, "Hangul_PreHanja" },
-  { 0x00ff3b, "Hangul_PostHanja" },
-  { 0x00ff3c, "Hangul_SingleCandidate" },
-  { 0x00ff3d, "Hangul_MultipleCandidate" },
-  { 0x00ff3e, "Hangul_PreviousCandidate" },
-  { 0x00ff3f, "Hangul_Special" },
   { 0xffffff, "VoidSymbol" },
 };
 
@@ -1985,7 +2000,7 @@ gdk_keyval_name (guint          keyval)
             GDK_NUM_KEYS, sizeof (struct gdk_key),
             gdk_keys_keyval_compare);
   if (found != NULL)
-    return found->name;
+    return (gchar *) found->name;
   else
     return NULL;
 }
@@ -2037,7 +2052,7 @@ gdk_keyval_to_upper (guint          keyval)
       KeySym lower_val = 0;
       KeySym upper_val = 0;
       
-      XConvertCase (keyval, &lower_val, &upper_val);
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
       return upper_val;
     }
   return 0;
@@ -2051,7 +2066,7 @@ gdk_keyval_to_lower (guint          keyval)
       KeySym lower_val = 0;
       KeySym upper_val = 0;
       
-      XConvertCase (keyval, &lower_val, &upper_val);
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
       return lower_val;
     }
   return 0;
@@ -2065,7 +2080,7 @@ gdk_keyval_is_upper (guint          keyval)
       KeySym lower_val = 0;
       KeySym upper_val = 0;
       
-      XConvertCase (keyval, &lower_val, &upper_val);
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
       return upper_val == keyval;
     }
   return TRUE;
@@ -2079,7 +2094,7 @@ gdk_keyval_is_lower (guint        keyval)
       KeySym lower_val = 0;
       KeySym upper_val = 0;
       
-      XConvertCase (keyval, &lower_val, &upper_val);
+      gdkx_XConvertCase (keyval, &lower_val, &upper_val);
       return lower_val == keyval;
     }
   return TRUE;
index 8e4e027813bbf7d191e60d41c44280082e97fb2c..a78fca93558a356099e0fe2603af64870c7b6547 100644 (file)
@@ -77,7 +77,7 @@ gdk_pixmap_new (GdkWindow *window,
   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
 
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = (GdkWindow*) gdk_root_parent;
 
   if (GDK_DRAWABLE_DESTROYED (window))
     return NULL;
@@ -287,7 +287,7 @@ gdk_bitmap_create_from_data (GdkWindow   *window,
   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
 
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = (GdkWindow*) gdk_root_parent;
 
   if (GDK_DRAWABLE_DESTROYED (window))
     return NULL;
@@ -616,7 +616,7 @@ _gdk_pixmap_create_from_xpm (GdkWindow   *window,
     g_warning ("Creating pixmap from xpm with NULL window and colormap");
 
   if (window == NULL)
-    window = (GdkWindow *)&gdk_root_parent;
+    window = (GdkWindow *) gdk_root_parent;
 
   if (colormap == NULL)
     {
@@ -929,7 +929,7 @@ gdk_pixmap_foreign_new (guint32 anid)
   /* set the pixmap to the passed in value */
   xpixmap = (HBITMAP) anid;
   /* get the root window */
-  window_private = &gdk_root_parent;
+  window_private = gdk_root_parent;
 
   /* get information about the BITMAP to fill in the structure for
      the gdk window */
index 8e4e027813bbf7d191e60d41c44280082e97fb2c..a78fca93558a356099e0fe2603af64870c7b6547 100644 (file)
@@ -77,7 +77,7 @@ gdk_pixmap_new (GdkWindow *window,
   g_return_val_if_fail ((width != 0) && (height != 0), NULL);
 
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = (GdkWindow*) gdk_root_parent;
 
   if (GDK_DRAWABLE_DESTROYED (window))
     return NULL;
@@ -287,7 +287,7 @@ gdk_bitmap_create_from_data (GdkWindow   *window,
   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
 
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = (GdkWindow*) gdk_root_parent;
 
   if (GDK_DRAWABLE_DESTROYED (window))
     return NULL;
@@ -616,7 +616,7 @@ _gdk_pixmap_create_from_xpm (GdkWindow   *window,
     g_warning ("Creating pixmap from xpm with NULL window and colormap");
 
   if (window == NULL)
-    window = (GdkWindow *)&gdk_root_parent;
+    window = (GdkWindow *) gdk_root_parent;
 
   if (colormap == NULL)
     {
@@ -929,7 +929,7 @@ gdk_pixmap_foreign_new (guint32 anid)
   /* set the pixmap to the passed in value */
   xpixmap = (HBITMAP) anid;
   /* get the root window */
-  window_private = &gdk_root_parent;
+  window_private = gdk_root_parent;
 
   /* get information about the BITMAP to fill in the structure for
      the gdk window */
index a45044d8e635f0a5c5078f09a6fc600830319ff2..25ed2e071fe5d9c86452e7f6e7abb675382d5e11 100644 (file)
 #define VIETNAMESE_CHARSET 163
 #endif
 
-/* MB_CUR_MAX is missing */
-#ifndef MB_CUR_MAX
-extern int *__imp___mb_cur_max;
-#define MB_CUR_MAX (*__imp___mb_cur_max)
+#ifndef VM_OEM_PLUS
+#define VK_OEM_PLUS 0xBB
 #endif
 
 #include <time.h>
@@ -217,6 +215,9 @@ struct _GdkWindowPrivate
 
   GList *filters;
   GList *children;
+
+  HKL input_locale;
+  CHARSETINFO charset_info;
 };
 
 struct _GdkImagePrivate
@@ -304,6 +305,9 @@ struct _GdkVisualPrivate
 struct _GdkFontPrivate
 {
   GdkFont font;
+  /* For now, both GDK_FONT_FONT and GDK_FONT_FONTSET fonts
+   * just have one Windows font loaded. This will change.
+   */
   HFONT xfont;
   guint ref_count;
 
@@ -382,6 +386,15 @@ void    gdk_sel_prop_store (GdkWindow *owner,
 
 void       gdk_event_queue_append (GdkEvent *event);
 
+gint      gdk_nmbstowcs (GdkWChar    *dest,
+                         const gchar *src,
+                         gint         src_len,
+                         gint         dest_max);
+gint      gdk_nmbstowchar_ts (wchar_t     *dest,
+                              const gchar *src,
+                              gint         src_len,
+                              gint         dest_max);
+
 /* Please see gdkwindow.c for comments on how to use */ 
 HWND gdk_window_xid_at(HWND base, gint bx, gint by, gint x, gint y, GList *excludes, gboolean excl_child);
 HWND gdk_window_xid_at_coords(gint x, gint y, GList *excludes, gboolean excl_child);
@@ -391,14 +404,12 @@ extern gint                gdk_show_events;
 extern gint             gdk_stack_trace;
 extern HWND             gdk_root_window;
 extern HWND             gdk_leader_window;
-GDKVAR GdkWindowPrivate         gdk_root_parent;
+GDKVAR GdkWindowPrivate        *gdk_root_parent;
 GDKVAR Atom             gdk_selection_property;
-extern GdkWindow       *selection_owner[];
 GDKVAR gchar           *gdk_progclass;
 GDKVAR gint             gdk_error_code;
 GDKVAR gint             gdk_error_warnings;
 GDKVAR gint              gdk_null_window_warnings;
-extern GList            *gdk_default_filters;
 extern gint             gdk_event_func_from_window_proc;
 
 extern HDC              gdk_DC;
@@ -411,6 +422,7 @@ extern UINT          gdk_selection_clear_msg;
 extern GdkAtom          gdk_clipboard_atom;
 extern GdkAtom          gdk_win32_dropfiles_atom;
 extern GdkAtom          gdk_ole2_dnd_atom;
+extern BOOL (WINAPI *p_TrackMouseEvent) (TRACKMOUSEEVENT *tme);
 
 extern LRESULT CALLBACK gdk_WindowProc (HWND, UINT, WPARAM, LPARAM);
 
index a45044d8e635f0a5c5078f09a6fc600830319ff2..25ed2e071fe5d9c86452e7f6e7abb675382d5e11 100644 (file)
 #define VIETNAMESE_CHARSET 163
 #endif
 
-/* MB_CUR_MAX is missing */
-#ifndef MB_CUR_MAX
-extern int *__imp___mb_cur_max;
-#define MB_CUR_MAX (*__imp___mb_cur_max)
+#ifndef VM_OEM_PLUS
+#define VK_OEM_PLUS 0xBB
 #endif
 
 #include <time.h>
@@ -217,6 +215,9 @@ struct _GdkWindowPrivate
 
   GList *filters;
   GList *children;
+
+  HKL input_locale;
+  CHARSETINFO charset_info;
 };
 
 struct _GdkImagePrivate
@@ -304,6 +305,9 @@ struct _GdkVisualPrivate
 struct _GdkFontPrivate
 {
   GdkFont font;
+  /* For now, both GDK_FONT_FONT and GDK_FONT_FONTSET fonts
+   * just have one Windows font loaded. This will change.
+   */
   HFONT xfont;
   guint ref_count;
 
@@ -382,6 +386,15 @@ void    gdk_sel_prop_store (GdkWindow *owner,
 
 void       gdk_event_queue_append (GdkEvent *event);
 
+gint      gdk_nmbstowcs (GdkWChar    *dest,
+                         const gchar *src,
+                         gint         src_len,
+                         gint         dest_max);
+gint      gdk_nmbstowchar_ts (wchar_t     *dest,
+                              const gchar *src,
+                              gint         src_len,
+                              gint         dest_max);
+
 /* Please see gdkwindow.c for comments on how to use */ 
 HWND gdk_window_xid_at(HWND base, gint bx, gint by, gint x, gint y, GList *excludes, gboolean excl_child);
 HWND gdk_window_xid_at_coords(gint x, gint y, GList *excludes, gboolean excl_child);
@@ -391,14 +404,12 @@ extern gint                gdk_show_events;
 extern gint             gdk_stack_trace;
 extern HWND             gdk_root_window;
 extern HWND             gdk_leader_window;
-GDKVAR GdkWindowPrivate         gdk_root_parent;
+GDKVAR GdkWindowPrivate        *gdk_root_parent;
 GDKVAR Atom             gdk_selection_property;
-extern GdkWindow       *selection_owner[];
 GDKVAR gchar           *gdk_progclass;
 GDKVAR gint             gdk_error_code;
 GDKVAR gint             gdk_error_warnings;
 GDKVAR gint              gdk_null_window_warnings;
-extern GList            *gdk_default_filters;
 extern gint             gdk_event_func_from_window_proc;
 
 extern HDC              gdk_DC;
@@ -411,6 +422,7 @@ extern UINT          gdk_selection_clear_msg;
 extern GdkAtom          gdk_clipboard_atom;
 extern GdkAtom          gdk_win32_dropfiles_atom;
 extern GdkAtom          gdk_ole2_dnd_atom;
+extern BOOL (WINAPI *p_TrackMouseEvent) (TRACKMOUSEEVENT *tme);
 
 extern LRESULT CALLBACK gdk_WindowProc (HWND, UINT, WPARAM, LPARAM);
 
index 782c39da25b5a5745a158cc2df81ae82286098bb..033867289396d6b713dd70e6f7546391c331f9eb 100644 (file)
@@ -257,11 +257,11 @@ gdk_selection_convert (GdkWindow *requestor,
        */
       GdkSelProp *prop;
 
-      prop = g_hash_table_lookup (sel_prop_table, &gdk_root_parent.drawable.xwindow);
+      prop = g_hash_table_lookup (sel_prop_table, &gdk_root_parent->drawable.xwindow);
 
       if (prop != NULL)
        {
-         g_hash_table_remove (sel_prop_table, &gdk_root_parent.drawable.xwindow);
+         g_hash_table_remove (sel_prop_table, &gdk_root_parent->drawable.xwindow);
          gdk_sel_prop_store (requestor, prop->type, prop->format,
                              prop->data, prop->length);
          g_free (prop);
index 782c39da25b5a5745a158cc2df81ae82286098bb..033867289396d6b713dd70e6f7546391c331f9eb 100644 (file)
@@ -257,11 +257,11 @@ gdk_selection_convert (GdkWindow *requestor,
        */
       GdkSelProp *prop;
 
-      prop = g_hash_table_lookup (sel_prop_table, &gdk_root_parent.drawable.xwindow);
+      prop = g_hash_table_lookup (sel_prop_table, &gdk_root_parent->drawable.xwindow);
 
       if (prop != NULL)
        {
-         g_hash_table_remove (sel_prop_table, &gdk_root_parent.drawable.xwindow);
+         g_hash_table_remove (sel_prop_table, &gdk_root_parent->drawable.xwindow);
          gdk_sel_prop_store (requestor, prop->type, prop->format,
                              prop->data, prop->length);
          g_free (prop);
index 7e8f8aded09e4ebec9f59edd0447bb447d63ff07..092765b89e5c41e4e57e9e34ad495526cfb6c4b3 100644 (file)
@@ -34,7 +34,7 @@
 #include <locale.h>
 
 #define GDK_ROOT_WINDOW()             ((guint32) HWND_DESKTOP)
-#define GDK_ROOT_PARENT()             ((GdkWindow *)&gdk_root_parent)
+#define GDK_ROOT_PARENT()             ((GdkWindow *) gdk_root_parent)
 #define GDK_DISPLAY()                 NULL
 #define GDK_DRAWABLE_XDISPLAY(win)    NULL
 #define GDK_DRAWABLE_XID(win)         (((GdkDrawablePrivate*) win)->xwindow)
index d76694dbaa685fec5267e5de5b4200047bf5c3af..0d2a5b056e38859b30caa0042c05be8f361552d6 100644 (file)
@@ -105,29 +105,25 @@ gdk_window_xid_at_coords (gint     x,
 void
 gdk_window_init (void)
 {
-  unsigned int width;
-  unsigned int height;
-#if 0
-  width = GetSystemMetrics (SM_CXSCREEN);
-  height = GetSystemMetrics (SM_CYSCREEN);
-#else
-  { RECT r; /* //HB: don't obscure tray window (task bar) */
-    SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
-    width  = r.right - r.left;
-    height = r.bottom - r.top;
-  }
-#endif
+  RECT r;
+  guint width;
+  guint height;
+
+  SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+  width  = r.right - r.left;
+  height = r.bottom - r.top;
 
-  gdk_root_parent.drawable.xwindow = gdk_root_window;
-  gdk_root_parent.drawable.window_type = GDK_WINDOW_ROOT;
-  gdk_root_parent.drawable.drawable.user_data = NULL;
-  gdk_root_parent.drawable.width = width;
-  gdk_root_parent.drawable.height = height;
-  gdk_root_parent.drawable.ref_count = 1;
-  gdk_root_parent.drawable.colormap = NULL;
-  gdk_root_parent.children = NULL;
+  gdk_root_parent = g_new (GdkWindowPrivate, 1);
+  gdk_root_parent->drawable.xwindow = gdk_root_window;
+  gdk_root_parent->drawable.window_type = GDK_WINDOW_ROOT;
+  gdk_root_parent->drawable.drawable.user_data = NULL;
+  gdk_root_parent->drawable.width = width;
+  gdk_root_parent->drawable.height = height;
+  gdk_root_parent->drawable.ref_count = 1;
+  gdk_root_parent->drawable.colormap = NULL;
+  gdk_root_parent->children = NULL;
 
-  gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent);
+  gdk_xid_table_insert (&gdk_root_window, gdk_root_parent);
 }
 
 /* RegisterGdkClass
@@ -258,14 +254,19 @@ gdk_window_new (GdkWindow     *parent,
   ATOM klass = 0;
   DWORD dwStyle, dwExStyle;
   RECT rect;
+  UINT acp;
   int width, height;
   int x, y;
   char *title;
+  gint titlelen;
+  wchar_t *wctitle;
+  gint wlen;
+  char *mbtitle;
 
   g_return_val_if_fail (attributes != NULL, NULL);
 
   if (!parent)
-    parent = (GdkWindow*) &gdk_root_parent;
+    parent = (GdkWindow*) gdk_root_parent;
 
   parent_private = (GdkWindowPrivate*) parent;
   if (GDK_DRAWABLE_DESTROYED (parent))
@@ -413,10 +414,23 @@ gdk_window_new (GdkWindow     *parent,
       height = private->drawable.height;
     }
 
+  acp = GetACP ();
+  private->input_locale = GetKeyboardLayout (0);
+  TranslateCharsetInfo ((DWORD FAR *) acp,
+                       &private->charset_info,
+                       TCI_SRCCODEPAGE);
+
+  titlelen = strlen (title);
+  wctitle = g_new (wchar_t, titlelen);
+  mbtitle = g_new (char, 3*titlelen + 1);
+  wlen = gdk_nmbstowchar_ts (wctitle, title, titlelen, titlelen);
+  WideCharToMultiByte (GetACP (), 0, wctitle, wlen,
+                      mbtitle, 3*titlelen, NULL, NULL);
+  
   private->drawable.xwindow =
     CreateWindowEx (dwExStyle,
                    MAKEINTRESOURCE(klass),
-                   title,
+                   mbtitle,
                    dwStyle,
                    x, y, 
                    width, height,
@@ -424,19 +438,31 @@ gdk_window_new (GdkWindow     *parent,
                    NULL,
                    gdk_ProgInstance,
                    NULL);
+
+  g_free (mbtitle);
+  g_free (wctitle);
+
+  if (private->drawable.xwindow == NULL)
+    {
+      g_warning ("gdk_window_create: CreateWindowEx failed");
+      g_free (private);
+      return NULL;
+    }
+
   GDK_NOTE (MISC,
-           g_print ("gdk_window_create: %s %s %#x %#x %dx%d@+%d+%d %#x = %#x\n",
+           g_print ("gdk_window_create: %s %s %dx%d@+%d+%d %#x = %#x\n"
+                    "...locale %#x codepage %d\n",
                     (private->drawable.window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
                      (private->drawable.window_type == GDK_WINDOW_CHILD ? "CHILD" :
                       (private->drawable.window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
                        (private->drawable.window_type == GDK_WINDOW_TEMP ? "TEMP" :
                         "???")))),
                     title,
-                    dwStyle,
-                    private->event_mask,
                     width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
                     xparent,
-                    private->drawable.xwindow));
+                    private->drawable.xwindow,
+                    private->input_locale,
+                    private->charset_info.ciACP));
 
   gdk_window_ref (window);
   gdk_xid_table_insert (&private->drawable.xwindow, window);
@@ -477,7 +503,7 @@ gdk_window_foreign_new (guint32 anid)
   point.x = rect.left;
   point.y = rect.right;
   ClientToScreen ((HWND) anid, &point);
-  if (parent != HWND_DESKTOP)
+  if (parent != GetDesktopWindow ())
     ScreenToClient (parent, &point);
   private->x = point.x;
   private->y = point.y;
@@ -727,6 +753,7 @@ gdk_window_show (GdkWindow *window)
          ShowWindow (private->drawable.xwindow, SW_SHOWNORMAL);
          ShowWindow (private->drawable.xwindow, SW_RESTORE);
          SetForegroundWindow (private->drawable.xwindow);
+         BringWindowToTop (private->drawable.xwindow);
 #if 0
          ShowOwnedPopups (private->drawable.xwindow, TRUE);
 #endif
@@ -991,7 +1018,7 @@ gdk_window_reparent (GdkWindow *window,
   g_return_if_fail (window != NULL);
 
   if (!new_parent)
-    new_parent = (GdkWindow*) &gdk_root_parent;
+    new_parent = (GdkWindow*) gdk_root_parent;
 
   window_private = (GdkWindowPrivate*) window;
   old_parent_private = (GdkWindowPrivate*)window_private->parent;
@@ -1370,6 +1397,11 @@ void
 gdk_window_set_title (GdkWindow   *window,
                      const gchar *title)
 {
+  gint titlelen;
+  wchar_t *wcstr;
+  gint wlen;
+  char *mbstr;
+
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
@@ -1377,8 +1409,21 @@ gdk_window_set_title (GdkWindow   *window,
                           GDK_DRAWABLE_XID (window), title));
   if (!GDK_DRAWABLE_DESTROYED (window))
     {
-      if (!SetWindowText (GDK_DRAWABLE_XID (window), title))
+      /* As the title most is in UTF-8 we must translate it
+       * to the system codepage.
+       */
+      titlelen = strlen (title);
+      wcstr = g_new (wchar_t, titlelen);
+      mbstr = g_new (char, 3*titlelen + 1);
+      wlen = gdk_nmbstowchar_ts (wcstr, title, titlelen, titlelen);
+      WideCharToMultiByte (GetACP (), 0, wcstr, wlen,
+                          mbstr, 3*titlelen, NULL, NULL);
+
+      if (!SetWindowText (GDK_DRAWABLE_XID (window), mbstr))
        g_warning ("gdk_window_set_title: SetWindowText failed");
+
+      g_free (mbstr);
+      g_free (wcstr);
     }
 }
 
@@ -1527,7 +1572,7 @@ gdk_window_get_geometry (GdkWindow *window,
   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
   
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = (GdkWindow*) gdk_root_parent;
   
   if (!GDK_DRAWABLE_DESTROYED (window))
     {
@@ -1660,7 +1705,7 @@ gdk_window_get_pointer (GdkWindow       *window,
   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
   
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = (GdkWindow*) gdk_root_parent;
 
   return_val = NULL;
   GetCursorPos (&pointc);
@@ -1724,7 +1769,7 @@ gdk_window_at_pointer (gint *win_x,
 
   if (hwnd == NULL)
     {
-      window = (GdkWindow *) &gdk_root_parent;
+      window = (GdkWindow *) gdk_root_parent;
       if (win_x)
        *win_x = pointc.x;
       if (win_y)
@@ -1902,10 +1947,7 @@ gdk_window_add_filter (GdkWindow     *window,
   if (private && GDK_DRAWABLE_DESTROYED (window))
     return;
   
-  if (private)
-    tmp_list = private->filters;
-  else
-    tmp_list = gdk_default_filters;
+  tmp_list = private->filters;
   
   while (tmp_list)
     {
@@ -1919,10 +1961,7 @@ gdk_window_add_filter (GdkWindow     *window,
   filter->function = function;
   filter->data = data;
   
-  if (private)
-    private->filters = g_list_append (private->filters, filter);
-  else
-    gdk_default_filters = g_list_append (gdk_default_filters, filter);
+  private->filters = g_list_append (private->filters, filter);
 }
 
 void
@@ -1939,10 +1978,7 @@ gdk_window_remove_filter (GdkWindow     *window,
 
   private = (GdkWindowPrivate*) window;
   
-  if (private)
-    tmp_list = private->filters;
-  else
-    tmp_list = gdk_default_filters;
+  tmp_list = private->filters;
   
   while (tmp_list)
     {
@@ -1952,10 +1988,8 @@ gdk_window_remove_filter (GdkWindow     *window,
       
       if ((filter->function == function) && (filter->data == data))
        {
-         if (private)
-           private->filters = g_list_remove_link (private->filters, node);
-         else
-           gdk_default_filters = g_list_remove_link (gdk_default_filters, node);
+         private->filters = g_list_remove_link (private->filters, node);
+
          g_list_free_1 (node);
          g_free (filter);
          
@@ -2091,7 +2125,7 @@ gdk_window_get_toplevels (void)
   GList *new_list = NULL;
   GList *tmp_list;
 
-  tmp_list = gdk_root_parent.children;
+  tmp_list = gdk_root_parent->children;
   while (tmp_list)
     {
       new_list = g_list_prepend (new_list, tmp_list->data);
@@ -2244,7 +2278,7 @@ gdk_window_is_viewable (GdkWindow *window)
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
   while (private && 
-        (private != &gdk_root_parent) &&
+        (private != gdk_root_parent) &&
         (private->drawable.window_type != GDK_WINDOW_FOREIGN))
     {
       if (!private->mapped)
index d76694dbaa685fec5267e5de5b4200047bf5c3af..0d2a5b056e38859b30caa0042c05be8f361552d6 100644 (file)
@@ -105,29 +105,25 @@ gdk_window_xid_at_coords (gint     x,
 void
 gdk_window_init (void)
 {
-  unsigned int width;
-  unsigned int height;
-#if 0
-  width = GetSystemMetrics (SM_CXSCREEN);
-  height = GetSystemMetrics (SM_CYSCREEN);
-#else
-  { RECT r; /* //HB: don't obscure tray window (task bar) */
-    SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
-    width  = r.right - r.left;
-    height = r.bottom - r.top;
-  }
-#endif
+  RECT r;
+  guint width;
+  guint height;
+
+  SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
+  width  = r.right - r.left;
+  height = r.bottom - r.top;
 
-  gdk_root_parent.drawable.xwindow = gdk_root_window;
-  gdk_root_parent.drawable.window_type = GDK_WINDOW_ROOT;
-  gdk_root_parent.drawable.drawable.user_data = NULL;
-  gdk_root_parent.drawable.width = width;
-  gdk_root_parent.drawable.height = height;
-  gdk_root_parent.drawable.ref_count = 1;
-  gdk_root_parent.drawable.colormap = NULL;
-  gdk_root_parent.children = NULL;
+  gdk_root_parent = g_new (GdkWindowPrivate, 1);
+  gdk_root_parent->drawable.xwindow = gdk_root_window;
+  gdk_root_parent->drawable.window_type = GDK_WINDOW_ROOT;
+  gdk_root_parent->drawable.drawable.user_data = NULL;
+  gdk_root_parent->drawable.width = width;
+  gdk_root_parent->drawable.height = height;
+  gdk_root_parent->drawable.ref_count = 1;
+  gdk_root_parent->drawable.colormap = NULL;
+  gdk_root_parent->children = NULL;
 
-  gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent);
+  gdk_xid_table_insert (&gdk_root_window, gdk_root_parent);
 }
 
 /* RegisterGdkClass
@@ -258,14 +254,19 @@ gdk_window_new (GdkWindow     *parent,
   ATOM klass = 0;
   DWORD dwStyle, dwExStyle;
   RECT rect;
+  UINT acp;
   int width, height;
   int x, y;
   char *title;
+  gint titlelen;
+  wchar_t *wctitle;
+  gint wlen;
+  char *mbtitle;
 
   g_return_val_if_fail (attributes != NULL, NULL);
 
   if (!parent)
-    parent = (GdkWindow*) &gdk_root_parent;
+    parent = (GdkWindow*) gdk_root_parent;
 
   parent_private = (GdkWindowPrivate*) parent;
   if (GDK_DRAWABLE_DESTROYED (parent))
@@ -413,10 +414,23 @@ gdk_window_new (GdkWindow     *parent,
       height = private->drawable.height;
     }
 
+  acp = GetACP ();
+  private->input_locale = GetKeyboardLayout (0);
+  TranslateCharsetInfo ((DWORD FAR *) acp,
+                       &private->charset_info,
+                       TCI_SRCCODEPAGE);
+
+  titlelen = strlen (title);
+  wctitle = g_new (wchar_t, titlelen);
+  mbtitle = g_new (char, 3*titlelen + 1);
+  wlen = gdk_nmbstowchar_ts (wctitle, title, titlelen, titlelen);
+  WideCharToMultiByte (GetACP (), 0, wctitle, wlen,
+                      mbtitle, 3*titlelen, NULL, NULL);
+  
   private->drawable.xwindow =
     CreateWindowEx (dwExStyle,
                    MAKEINTRESOURCE(klass),
-                   title,
+                   mbtitle,
                    dwStyle,
                    x, y, 
                    width, height,
@@ -424,19 +438,31 @@ gdk_window_new (GdkWindow     *parent,
                    NULL,
                    gdk_ProgInstance,
                    NULL);
+
+  g_free (mbtitle);
+  g_free (wctitle);
+
+  if (private->drawable.xwindow == NULL)
+    {
+      g_warning ("gdk_window_create: CreateWindowEx failed");
+      g_free (private);
+      return NULL;
+    }
+
   GDK_NOTE (MISC,
-           g_print ("gdk_window_create: %s %s %#x %#x %dx%d@+%d+%d %#x = %#x\n",
+           g_print ("gdk_window_create: %s %s %dx%d@+%d+%d %#x = %#x\n"
+                    "...locale %#x codepage %d\n",
                     (private->drawable.window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
                      (private->drawable.window_type == GDK_WINDOW_CHILD ? "CHILD" :
                       (private->drawable.window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
                        (private->drawable.window_type == GDK_WINDOW_TEMP ? "TEMP" :
                         "???")))),
                     title,
-                    dwStyle,
-                    private->event_mask,
                     width, height, (x == CW_USEDEFAULT ? -9999 : x), y, 
                     xparent,
-                    private->drawable.xwindow));
+                    private->drawable.xwindow,
+                    private->input_locale,
+                    private->charset_info.ciACP));
 
   gdk_window_ref (window);
   gdk_xid_table_insert (&private->drawable.xwindow, window);
@@ -477,7 +503,7 @@ gdk_window_foreign_new (guint32 anid)
   point.x = rect.left;
   point.y = rect.right;
   ClientToScreen ((HWND) anid, &point);
-  if (parent != HWND_DESKTOP)
+  if (parent != GetDesktopWindow ())
     ScreenToClient (parent, &point);
   private->x = point.x;
   private->y = point.y;
@@ -727,6 +753,7 @@ gdk_window_show (GdkWindow *window)
          ShowWindow (private->drawable.xwindow, SW_SHOWNORMAL);
          ShowWindow (private->drawable.xwindow, SW_RESTORE);
          SetForegroundWindow (private->drawable.xwindow);
+         BringWindowToTop (private->drawable.xwindow);
 #if 0
          ShowOwnedPopups (private->drawable.xwindow, TRUE);
 #endif
@@ -991,7 +1018,7 @@ gdk_window_reparent (GdkWindow *window,
   g_return_if_fail (window != NULL);
 
   if (!new_parent)
-    new_parent = (GdkWindow*) &gdk_root_parent;
+    new_parent = (GdkWindow*) gdk_root_parent;
 
   window_private = (GdkWindowPrivate*) window;
   old_parent_private = (GdkWindowPrivate*)window_private->parent;
@@ -1370,6 +1397,11 @@ void
 gdk_window_set_title (GdkWindow   *window,
                      const gchar *title)
 {
+  gint titlelen;
+  wchar_t *wcstr;
+  gint wlen;
+  char *mbstr;
+
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
@@ -1377,8 +1409,21 @@ gdk_window_set_title (GdkWindow   *window,
                           GDK_DRAWABLE_XID (window), title));
   if (!GDK_DRAWABLE_DESTROYED (window))
     {
-      if (!SetWindowText (GDK_DRAWABLE_XID (window), title))
+      /* As the title most is in UTF-8 we must translate it
+       * to the system codepage.
+       */
+      titlelen = strlen (title);
+      wcstr = g_new (wchar_t, titlelen);
+      mbstr = g_new (char, 3*titlelen + 1);
+      wlen = gdk_nmbstowchar_ts (wcstr, title, titlelen, titlelen);
+      WideCharToMultiByte (GetACP (), 0, wcstr, wlen,
+                          mbstr, 3*titlelen, NULL, NULL);
+
+      if (!SetWindowText (GDK_DRAWABLE_XID (window), mbstr))
        g_warning ("gdk_window_set_title: SetWindowText failed");
+
+      g_free (mbstr);
+      g_free (wcstr);
     }
 }
 
@@ -1527,7 +1572,7 @@ gdk_window_get_geometry (GdkWindow *window,
   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
   
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = (GdkWindow*) gdk_root_parent;
   
   if (!GDK_DRAWABLE_DESTROYED (window))
     {
@@ -1660,7 +1705,7 @@ gdk_window_get_pointer (GdkWindow       *window,
   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
   
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
+    window = (GdkWindow*) gdk_root_parent;
 
   return_val = NULL;
   GetCursorPos (&pointc);
@@ -1724,7 +1769,7 @@ gdk_window_at_pointer (gint *win_x,
 
   if (hwnd == NULL)
     {
-      window = (GdkWindow *) &gdk_root_parent;
+      window = (GdkWindow *) gdk_root_parent;
       if (win_x)
        *win_x = pointc.x;
       if (win_y)
@@ -1902,10 +1947,7 @@ gdk_window_add_filter (GdkWindow     *window,
   if (private && GDK_DRAWABLE_DESTROYED (window))
     return;
   
-  if (private)
-    tmp_list = private->filters;
-  else
-    tmp_list = gdk_default_filters;
+  tmp_list = private->filters;
   
   while (tmp_list)
     {
@@ -1919,10 +1961,7 @@ gdk_window_add_filter (GdkWindow     *window,
   filter->function = function;
   filter->data = data;
   
-  if (private)
-    private->filters = g_list_append (private->filters, filter);
-  else
-    gdk_default_filters = g_list_append (gdk_default_filters, filter);
+  private->filters = g_list_append (private->filters, filter);
 }
 
 void
@@ -1939,10 +1978,7 @@ gdk_window_remove_filter (GdkWindow     *window,
 
   private = (GdkWindowPrivate*) window;
   
-  if (private)
-    tmp_list = private->filters;
-  else
-    tmp_list = gdk_default_filters;
+  tmp_list = private->filters;
   
   while (tmp_list)
     {
@@ -1952,10 +1988,8 @@ gdk_window_remove_filter (GdkWindow     *window,
       
       if ((filter->function == function) && (filter->data == data))
        {
-         if (private)
-           private->filters = g_list_remove_link (private->filters, node);
-         else
-           gdk_default_filters = g_list_remove_link (gdk_default_filters, node);
+         private->filters = g_list_remove_link (private->filters, node);
+
          g_list_free_1 (node);
          g_free (filter);
          
@@ -2091,7 +2125,7 @@ gdk_window_get_toplevels (void)
   GList *new_list = NULL;
   GList *tmp_list;
 
-  tmp_list = gdk_root_parent.children;
+  tmp_list = gdk_root_parent->children;
   while (tmp_list)
     {
       new_list = g_list_prepend (new_list, tmp_list->data);
@@ -2244,7 +2278,7 @@ gdk_window_is_viewable (GdkWindow *window)
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
   while (private && 
-        (private != &gdk_root_parent) &&
+        (private != gdk_root_parent) &&
         (private->drawable.window_type != GDK_WINDOW_FOREIGN))
     {
       if (!private->mapped)
index 7e8f8aded09e4ebec9f59edd0447bb447d63ff07..092765b89e5c41e4e57e9e34ad495526cfb6c4b3 100644 (file)
@@ -34,7 +34,7 @@
 #include <locale.h>
 
 #define GDK_ROOT_WINDOW()             ((guint32) HWND_DESKTOP)
-#define GDK_ROOT_PARENT()             ((GdkWindow *)&gdk_root_parent)
+#define GDK_ROOT_PARENT()             ((GdkWindow *) gdk_root_parent)
 #define GDK_DISPLAY()                 NULL
 #define GDK_DRAWABLE_XDISPLAY(win)    NULL
 #define GDK_DRAWABLE_XID(win)         (((GdkDrawablePrivate*) win)->xwindow)
index 77429ca2e8e0ad9003c50dc728ee5f60456530b9..e067af15c672fafd52992502aae7d8ab761e8a60 100644 (file)
@@ -88,7 +88,7 @@ gdkres.o : rc/gdk.rc
        windres --include-dir rc rc/gdk.rc gdkres.o
 
 gdk-$(GTK_VER).dll : $(gdk_OBJECTS) gdk.def gdkres.o libwntab32x.a
-       $(GLIB)/build-dll gdk $(GTK_VER) gdk.def $(gdk_OBJECTS) -L $(GLIB) -lglib-$(GLIB_VER) -L . -lwntab32x -lgdi32 -luser32 -lshell32 -lole32 -luuid $(LDFLAGS) gdkres.o
+       $(GLIB)/build-dll gdk $(GTK_VER) gdk.def $(gdk_OBJECTS) -L $(GLIB) -lglib-$(GLIB_VER) -L . -lwntab32x -lgdi32 -luser32 -limm32 -lshell32 -lole32 -luuid $(LDFLAGS) gdkres.o
 
 libwntab32x.a : $(WTKIT)/lib/i386/wntab32x.lib
        cp $(WTKIT)/lib/i386/wntab32x.lib libwntab32x.a
diff --git a/gdk/win32/surrogate-dimm.h b/gdk/win32/surrogate-dimm.h
new file mode 100644 (file)
index 0000000..3cc50be
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef __SURROGATE_DIMM_H__
+#define __SURROGATE_DIMM_H__
+
+/* The Win32api headers doesn't include <dimm.h>, thus we need
+ * this file, which coverr just the stuff we need from <dimm.h>.
+ */
+
+typedef struct IActiveIMMApp IActiveIMMApp;
+typedef struct IActiveIMMMessagePumpOwner IActiveIMMMessagePumpOwner;
+
+/* Dummy vtable structs that contain real names and prototypes for
+ * only those methods we need.
+ */
+typedef struct {
+  HRESULT (__stdcall *QueryInterface) (IActiveIMMApp *This,
+                                      REFIID riid,
+                                      void *ppvObject);
+  /* Dummy method prototypes for those we don't use */
+  ULONG (__stdcall *dummy_AddRef)();
+  ULONG (__stdcall *dummy_Release)();
+  HRESULT (__stdcall *dummy_AssociateContext)();
+  HRESULT (__stdcall *dummy_ConfigureIMEA)();
+  HRESULT (__stdcall *dummy_ConfigureIMEW)();
+  HRESULT (__stdcall *dummy_CreateContext)();
+  HRESULT (__stdcall *dummy_DestroyContext)();
+  HRESULT (__stdcall *dummy_EnumRegisterWordA)();
+  HRESULT (__stdcall *dummy_EnumRegisterWordW)();
+  HRESULT (__stdcall *dummy_EscapeA)();
+  HRESULT (__stdcall *dummy_EscapeW)();
+  HRESULT (__stdcall *dummy_GetCandidateListA)();
+  HRESULT (__stdcall *dummy_GetCandidateListW)();
+  HRESULT (__stdcall *dummy_GetCandidateListCountA)();
+  HRESULT (__stdcall *dummy_GetCandidateListCountW)();
+  HRESULT (__stdcall *dummy_GetCandidateWindow)();
+  HRESULT (__stdcall *dummy_GetCompositionFontA)();
+  HRESULT (__stdcall *dummy_GetCompositionFontW)();
+  HRESULT (__stdcall *dummy_GetCompositionStringA)();
+  HRESULT (__stdcall *dummy_GetCompositionStringW)();
+  HRESULT (__stdcall *dummy_GetCompositionWindow)();
+  HRESULT (__stdcall *dummy_GetContext)();
+  HRESULT (__stdcall *dummy_GetConversionListA)();
+  HRESULT (__stdcall *dummy_GetConversionListW)();
+  HRESULT (__stdcall *dummy_GetConversionStatus)();
+
+  HRESULT (__stdcall *GetDefaultIMEWnd)(IActiveIMMApp *This,
+                                       HWND hWnd,
+                                       HWND *phDefWnd);
+
+  HRESULT (__stdcall *dummy_GetDescriptionA)();
+  HRESULT (__stdcall *dummy_GetDescriptionW)();
+  HRESULT (__stdcall *dummy_GetGuideLineA)();
+  HRESULT (__stdcall *dummy_GetGuideLineW)();
+  HRESULT (__stdcall *dummy_GetIMEFileNameA)();
+  HRESULT (__stdcall *dummy_GetIMEFileNameW)();
+  HRESULT (__stdcall *dummy_GetOpenStatus)();
+  HRESULT (__stdcall *dummy_GetProperty)();
+  HRESULT (__stdcall *dummy_GetRegisterWordStyleA)();
+  HRESULT (__stdcall *dummy_GetRegisterWordStyleW)();
+  HRESULT (__stdcall *dummy_GetStatusWindowPos)();
+  HRESULT (__stdcall *dummy_GetVirtualKey)();
+  HRESULT (__stdcall *dummy_InstallIMEA)();
+  HRESULT (__stdcall *dummy_InstallIMEW)();
+
+  HRESULT (__stdcall *IsIME)(IActiveIMMApp *This,
+                            HKL hKL);
+  HRESULT (__stdcall *IsUIMessageA )(IActiveIMMApp *This,
+                                    HWND hWndIME,
+                                    UINT msg,
+                                    WPARAM wParam,
+                                    LPARAM lParam);
+  HRESULT (__stdcall *dummy_IsUIMessageW)();
+  HRESULT (__stdcall *dummy_NotifyIME)();
+  HRESULT (__stdcall *dummy_RegisterWordA)();
+  HRESULT (__stdcall *dummy_RegisterWordW)();
+  HRESULT (__stdcall *dummy_ReleaseContext)();
+  HRESULT (__stdcall *dummy_SetCandidateWindow)();
+  HRESULT (__stdcall *dummy_SetCompositionFontA)();
+  HRESULT (__stdcall *dummy_SetCompositionFontW)();
+  HRESULT (__stdcall *dummy_SetCompositionStringA)();
+  HRESULT (__stdcall *dummy_SetCompositionStringW)();
+  HRESULT (__stdcall *dummy_SetCompositionWindow)();
+  HRESULT (__stdcall *dummy_SetConversionStatus)();
+  HRESULT (__stdcall *dummy_SetOpenStatus)();
+  HRESULT (__stdcall *dummy_SetStatusWindowPos)();
+  HRESULT (__stdcall *dummy_SimulateHotKey)();
+  HRESULT (__stdcall *dummy_UnregisterWordA)();
+  HRESULT (__stdcall *dummy_UnregisterWordW)();
+
+  HRESULT (__stdcall *Activate)(IActiveIMMApp *This,
+                               BOOL restore);
+  HRESULT (__stdcall *Deactivate)(IActiveIMMApp *This);
+  HRESULT (__stdcall *OnDefWindowProc)(IActiveIMMApp *This,
+                                      HWND hWnd,
+                                      UINT Msg,
+                                      WPARAM wParam,
+                                      LPARAM lParam,
+                                      LRESULT *plResult);
+
+  HRESULT (__stdcall *dummy_FilterClientWindows)();
+
+  HRESULT (__stdcall *GetCodePageA)(IActiveIMMApp *This,
+                                   HKL hKL,
+                                   UINT *uCodePage);
+  HRESULT (__stdcall *GetLangId)(IActiveIMMApp *This,
+                                HKL hKL,
+                                LANGID *plid);
+
+  HRESULT (__stdcall *dummy_AssociateContextEx)();
+  HRESULT (__stdcall *dummy_DisableIME)();
+  HRESULT (__stdcall *dummy_GetImeMenuItemsA)();
+  HRESULT (__stdcall *dummy_GetImeMenuItemsW)();
+  HRESULT (__stdcall *dummy_EnumInputContext)();
+} IActiveIMMAppVtbl;
+
+struct IActiveIMMApp {
+  IActiveIMMAppVtbl *lpVtbl;
+};
+
+typedef struct {
+  HRESULT (__stdcall *dummy_QueryInterface)();
+  ULONG (__stdcall *dummy_AddRef)();
+  ULONG (__stdcall *dummy_Release)();
+
+  HRESULT (__stdcall *Start)(IActiveIMMMessagePumpOwner *This);
+  HRESULT (__stdcall *End)(IActiveIMMMessagePumpOwner *This);
+  HRESULT (__stdcall *OnTranslateMessage)(IActiveIMMMessagePumpOwner *This,
+                                         MSG *pMSG);
+
+  HRESULT (__stdcall *dummy_Pause)();
+  HRESULT (__stdcall *dummy_Resume)();
+} IActiveIMMMessagePumpOwnerVtbl;
+
+struct IActiveIMMMessagePumpOwner {
+  IActiveIMMMessagePumpOwnerVtbl *lpVtbl;
+};
+
+static UUID CLSID_CActiveIMM = {
+  0x4955DD33, 0xB159, 0x11d0, { 0x8F,0xCF,0x00,0xAA,0x00,0x6B,0xCC,0x59 } };
+static IID IID_IActiveIMMApp = {
+  0x08C0E040, 0x62D1, 0x11D1, { 0x93,0x26,0x00,0x60,0xB0,0x67,0xB8,0x6E } };
+static IID IID_IActiveIMMMessagePumpOwner = {
+  0xB5CF2CFA, 0x8AEB, 0x11D1, { 0x93,0x64,0x00,0x60,0xB0,0x67,0xB8,0x6E } };
+
+#endif /* __SURROGATE_DIMM_H__ */
index 1171c6eb1a09937a448540c87fe14eeade7f3f87..6305003ff5dcd1eff0df51b0cb2044cd27450165 100644 (file)
@@ -1773,7 +1773,12 @@ gtk_font_selection_load_font (GtkFontSelection *fontsel)
 #ifdef FONTSEL_DEBUG
       g_message("Loading: %s\n", fontname);
 #endif
+#ifndef GDK_WINDOWING_WIN32
       font = gdk_font_load (fontname);
+#else
+      /* Load as a fontset so that gtkentry uses wide chars for it */
+      font = gdk_fontset_load (fontname);
+#endif
       g_free(fontname);
       
       if (font)
index 92ef97e3a6d7075395dc7334c8e02c9c66746054..94a5b621fa0f4a4ff04d9692d344465f5638dcd3 100644 (file)
@@ -405,7 +405,7 @@ gtk_init_check (int  *argc,
   bindtextdomain("gtk+", GTK_LOCALEDIR);
 #else
   {
-    /* GTk+ locale dir is %WinDir%\gtk\locale */
+    /* GTk+ locale dir is %WinDir%\gtk+\locale */
     extern char *get_gtk_sysconf_directory ();
     bindtextdomain ("gtk+", g_strconcat (get_gtk_sysconf_directory (),
                                         G_DIR_SEPARATOR_S,
index 4990532f82d375e0e8363b52d37e87ae150a242a..39517ae6ceba07ee920ace3c1245a14183556b71 100644 (file)
@@ -239,7 +239,7 @@ get_gtk_sysconf_directory (void)
   gchar win_dir[100];
 
   GetWindowsDirectory (win_dir, sizeof (win_dir));
-  sprintf (gtk_sysconf_dir, "%s\\gtk", win_dir);
+  sprintf (gtk_sysconf_dir, "%s\\gtk+", win_dir);
   return gtk_sysconf_dir;
 }
 
@@ -467,10 +467,14 @@ gtk_rc_init (void)
   gchar *locale_suffixes[3];
   gint n_locale_suffixes = 0;
   gint i, j;
+#ifdef G_OS_WIN32
+  char *locale = gwin_getlocale ();
+#else
 #ifdef HAVE_LC_MESSAGES
   char *locale = setlocale (LC_MESSAGES, NULL);
 #else
   char *locale = setlocale (LC_CTYPE, NULL);
+#endif
 #endif
   guint length;
   char *p;